Informática Numaboa - Tutoriais e Programação
Menu malandro (masm)
Qui 16 Abr 2009 20:57 |
- Detalhes
- Categoria: Assembly Numaboa (antigo oiciliS)
- Atualização: Domingo, 21 Junho 2009 18:47
- Autor: vovó Vicki
- Acessos: 9487
Trabalhando com variáveis do sistema. Brinque com o usuário. Resolução de tela, coordenadas de janelas, data e hora do sistema são algumas das novidades usadas para criar uma janela que "foge" do cursor do mouse.
Neste tutorial vamos fazer uma brincadeira com o usuário. Aproveitando o código fonte do tutorial anterior, o Criando menus em Assembly, vamos obter algumas informações do contexto (as assim chamadas variáveis do sistema) e fazer com que a janela "fuja do cursor do mouse". Veremos como obter a resoluçãoo de tela, o tamanho de uma janela, hora e data do sistema e a posição de uma janela na tela. Veremos também como interagir com estes dados para obter os resultados desejados.
O tipo da janela
O código fonte base é o mesmo escrito para o tutorial "Criando menus em Assembly", assim como o arquivo de recursos. O arquivo de recursos não precisa ser alterado. Fazendo algumas pequenas modificações no código fonte, podemos fazer uma brincadeira com o usuário - escolhendo determinados itens do menu, a janela "foge". A primeira pequena modificação será feita na função CreateWindowEx: fixaremos o tamanho da janela em 300 x 200 pixels e tiraremos os elementos do canto superior direito da janela que permitem maximizar ou minimizar a janela.
Trocando o texto
Primeiramente vamos trocar o texto que será mostrado ao usuário quando escolher algum item do menu. Use a imaginação e divirta-se. Minha sugestão não está "aquelas coisas", mas serve como exemplo:
Trocando caixas de mensagens por texto na tela
Ao invés de utilizar a função MessageBox para criar caixas de mensagem para indicar o item de menu escolhido, vamos "pintar" o texto referente a cada item do menu na área cliente da janela. O procedimento já foi descrito em detalhes no tutorial Pintando Texto. A lógica é a seguinte:
- Criamos uma variável global que recebe o endereço do texto referente ao item de menu selecionado. Este valor é obtido quando interceptamos a mensagem WM_COMMAND.
- No final da rotina do WM_COMMAND chamamos a função InvalidateRect, a qual força uma repintura da área cliente da janela, ou seja, invalida a área e envia uma mensagem WM_PAINT.
- Interceptamos a mensagem WM_PAINT e fazemos a pintura do texto indicado pelo endereço da variável global.
A coisa fica com esta cara:
Se você quiser, neste ponto é possível compilar um executável e testá-lo. A janela ainda não "foge", porém as mensagens relativas aos itens de menu aparecem na área cliente da janela.
Criando a função que desloca a janela
Os itens escolhidos para deslocarem a janela são "Sopa de Piranha" e "Amendoim". Quando o usuário os escolher, a janela deve se deslocar na tela para uma posição diferente. Para tanto, vamos declarar a função "foge". Esta função calcula as novas coordenadas do canto superior esquerdo da janela e fará com que assuma a nova posição.
Declarando a função foge
A primeira providência será declarar o protótipo da função e, logo a seguir, declarar a pópria função. Vamos precisar do manipulador da janela para podermos alterar algumas das suas propriedades e, por isto, o único parâmetro da função será o manipulador:
Calculando a resolução da tela
Tudo bem. Queremos deslocar nossa janela pela tela, porém ainda não sabemos quantos pixels poderemos deslocá-la no sentido horizontal ou vertical por que desconhecemos quantos pixels estão disponíveis. A função que pode nos fornecer todas as medidas de elementos do sistema, entre elas a resolução de tela, é a GetSystemMetrics:
O parâmetro nIndex, entre outros, pode ser SM_CXSCREEN. Neste caso, o valor de retorno é o número de pixels da horizontal (eixo X). Usando o SM_CYSCREEN obtemos o número de pixels na vertical (eixo Y). Como usaremos as coordenadas do canto superior esquerdo da janela para movimentá-la na tela, os pixels disponíveis na horizontal serão os do eixo X MENOS o número de pixels da largura da janela. Se não descontarmos os pixels da largura da janela corremos o risco de posicioná-la fora da tela (ou mostrá-la apenas parcialmente). Da mesma forma, os pixels disponíveis na vertical serão os do eixo Y MENOS o número de pixels da altura da janela. Os valores assim obtidos serão armazenados nas variáveis locais largMax e altMax.
Determinando a posição atual da janela
A posição atual de uma janela pode ser obtida através da função GetWindowRect. Esta função precisa do manipulador da janela e de uma estrutura RECT, onde serão armazenadas as coordenadas de tela da posição da janela cujo manipulador foi fornecido:
Obtendo a hora do sistema
As posições que a janela deve ocupar são aleatórias e, para calculá-las, usaremos um expediente: a nova posição dependerá dos milésimos de segundo indicados pelo relógio do sistema, pois a possibilidade de repetição deste valor é muito remota. A função GetSystemTime não possui valor de retorno, mas preenche uma estrutura SYSTEMTIME com a hora do sistema:
A estutura SYSTEMTIME possui os seguintes membros:
Para obter os dados desejados, precisamos declarar uma variável local do tipo SYSTEMTIME e chamar a função GetSystemTime que tenha como parâmetro o endereço da nossa variável:
O valor que desejamos será encontrado em system_time.wMilliseconds.
Calculando a nova posição da janela
Teremos que calcular o novo valor de X (posição horizontal na tela) e de Y (posição vertical na tela). A posição atual está no membro da estrutura retang.left e retang.top. Se somarmos o valor de retang.left (posição X atual da janela) aos milésimos de segundo que estão em system_time.wMilliseconds, podem ocorrer duas situações: o novo valor de X ou é maior ou é menor do que a largMax calculada. Caso seja maior, se movermos a janela para este ponto, ela ficará parcialmente visível ou então fora da tela. Faremos uso da sintaxe de alto nível do MASM para criar um loop: se o novo valor de X for maior que largMax, diminuímos este valor de X (novo X - largMax) tantas vezes quantas forem necessárias para que o novo valor de X seja menor que largMax. Assim que o novo valor de X for menor que largMax, saímos do loop e guardamos o valor de X na variável local novoX. O mesmo raciocínio se aplica para o cálculo do novo valor de Y.
Note que transferimos para AX (e não EAX) o valor dos milisegundos. É que a estrutura system_time foi criada a partir do modelo SYSTEMTIME, cujos membros são todos do tipo WORD (16 bits). Caso você tentar transferir para EAX (32 bits) o valor de qualquer membro de system_time (16 bits), o assembler indicará o erro "instruction operands must be the same size", ou seja, os operandos da instrução precisam ser do mesmo tamanho.
Mudando a posição da janela
De posse de todos os parâmetros necessários para mudar a posição da janela, agora podemos chamar a função MoveWindow:
O parâmetro hWnd veio como parâmetro para nossa função "foge". Os parâmetros X e Y são os nossos novoX e novoY. A largura e a altura não serão modificadas, portanto usaremos as variáveis globais largJanela e altJanela. O indicador de repintura será TRUE (verdadeiro) para forçar o sistema a enviar uma mensagem WM_PAINT, devidamente interceptada e onde faremos nossa pintura personalizada. Depois disto, basta um ret para terminarmos a função foge:
Tutorial para download
Este tutorial, juntamente com o código fonte, imagens e o executável está na seção de Downloads / Tutoriais / Assembly Numaboa, mas você também pode baixá-lo aqui.