A Aldeia Numaboa ancestral ainda está disponível para visitação. É a versão mais antiga da Aldeia que eu não quis simplesmente descartar depois de mais de 10 milhões de pageviews. Como diz a Sirley, nossa cozinheira e filósofa de plantão: "Misericórdia, ai que dó!"

Se você tiver curiosidade, o endereço é numaboa.net.br.

Leia mais...

Informática Numaboa - Tutoriais e Programação

Criando uma mini-calculadora em Assembly para Win32

Qua

14

Jan

2009


20:06

(11 votos, média 4.45 de 5) 


Dando funcionalidade aos botões

Agora vem a parte onde você tem que programar o que o botão vai fazer ao ser clicado pelo usuário. É só verificar se a mensagem agora é um WM_COMMAND. Se for, teremos que fazer outra verificação, teremos que pegar o valor retornado na mensagem no parâmetro do procedimento que nós chamamos anteriormente de lParam. Certo? Vamos ver como fazer isso na prática.

Logo abaixo do código do último botão (o botão "C"), vamos ter que implementar mais código, agora pra dizermos o que os botões irão fazer.

... .ELSEIF uMsg == WM_COMMAND ;;Movendo o valor de lParam para edx Mov edx, lParam ;;Comparando edx com o Handle do Botão 1 .if edx == Botao1_Handle

Bem, nesse momento você deve ter pensado que agora era só colocar uma chamada para SetWindowText passando o valor do título para o botão. Se você pensou assim, você não errou. Porém há algo mais a se pensar: se o usuário clicar no botão 1, logicamente o texto do nosso edit seria 1, certo? Mas se o usuário clicasse no 2, então o texto do edit seria 2 e não 12. É ai onde entra a função lstrcat.

Breve explicação sobre a função lstrcat:

lstrcat recebe duas strings terminadas em 0 e retorna um ponteiro que nos indica onde está a junção das duas strings que foram passadas, e esse ponteiro é retornado no registrador eax.

Já que sabemos isso, vamos programar; só precisamos da lógica. Primeiro pegaremos o texto que está no Edit. Então vamos lá! Vamos criar uma variável para guardar o texto do edit lá em data?.

.DATA? ... Edit_Texto db 100 dup (?)

Indo agora para o código do Botao1, chamaremos a função GetWindowText para pegar o texto do Edit:

... Invoke GetWindowText, Edit_Handle, ADDR Edit_Texto, 100

E agora chamamos lstrcat passando as duas strings.

Invoke lstrcat, ADDR Edit_Texto, ADDR Botao1_Titulo

E você terá que guardar o valor do ponteiro retornado em alguma variável. Então declare uma em Data? do tipo DWORD.

.DATA ... Endereco_String DWORD ?

Agora que já temos a variável é só mover o valor para dentro dela.

Mov Endereço_String, eax

Agora, como você tinha pensado (ou não), chamaremos a API SetWindowText.

Invoke SetWindowText, Edit_Handle, [Endereco_String] .endif

Pronto, terminamos o código do botao1. Pense e faça a mesma coisa para os outros botões, menos virgula, adição, subtração e tal, tal, tal...

Aqui vai o código completo de mais dois botões. Faça o mesmo para os botões restantes:

... .if edx == Botao2Handle Invoke GetWindowText, EditHandle, ADDR Edit_Texto, 100 Invoke lstrcat, ADDR Edit_Texto, ADDR Botao2_Titulo Mov Endereco_String, eax Invoke SetWindowText, EditHandle, [Endereco_String] .endif .if edx == Botao3Handle Invoke GetWindowText, EditHandle, ADDR Edit_Texto, 100 Invoke lstrcat, ADDR Edit_Texto, ADDR Botao3_Titulo Mov Endereco_String, eax Invoke SetWindowText, EditHandle, [Endereco_String] .endif

Tendo todos os botões codificados, agora só precisamos configurar os botões das operações. Iremos começar pelo botão de Adição, os outros três são semelhantes mudando poucas funções.

.if edx == BotaoMaisHandle

Agora vamos ter que fazer algo bem legal - conversões. Você não pode somar duas strings, então você tem que converte-la num valor inteiro e salvá-lo em algum lugar. Então vamos pensar um pouco: quando o usuário digitar alguns números e depois clicar em mais, você terá que salvar o valor digitado e já convertido e limpar o edit para a entrada do outro valor. Isto nos diz que precisaremos de 3 variáveis, uma para salvar o primeiro valor, outra para o segundo valor e a terceira para salvar qual operação está sendo selecionada. Então vamos criá-las:

.DATA? .... Valor1 DWORD ? Valor2 DWORD ? Resultado DWORD ? ;; aqui é uma variável que vai ser usada mais a frente para salvar o ;;resultado da adição, subtração, Multiplicação ou Divisão. Operacao DWORD ?

Continuando com o botão de adição...

Mov Operacao, 01h ;; Nesse momento definimos que a operação atual é adição representada ;;pelo número 1 Invoke GetWindowText, EditHandle, ADDR Edit_Texto, 100

Voltamos a usar nossa variável Edit_Texto em outro lugar, mas não se preocupe, trabalhar com ela aqui não vai atrapalhar o funcionamento dos outros botões. Agora chegamos num ponto onde chamaremos uma função de conversão, porque teremos que converter os dados de string para dword. Esta função se encontra na biblioteca chamada masm32.lib e é só você adicionar lá no começo no cabeçalho "include \masm32\include\masm32.inc" e "includelib \masm32\lib\masm32.lib".

Agora podemos chamar as funções "atodw" e "dwtoa", abreviações de "AsciiToDword" e "DwordtoAscii". Para chamar a função "atodw" nós passamos como parâmetro a string a ser convertida e o valor é retornado em eax.

Invoke atodw, ADDR Edit_Texto Mov Valor1, eax ;; Movendo o valor convertido para a variável Valor1 Invoke SetWindowText, EditHandle, NULL ;; Deixando o Edit vazio para a entrada do ;; segundo valor .endif

Este é o código para o botão da soma. Para o botão da subtração a operação será mudada de 01h para 02h, e quando o clique for no botão multiplicar, 03h e é claro, quando o botão clicado for dividir 04h. Então programe smile

O código dos outros botões estarão no fim do tutorial quando for mostrado o código completo. Estamos chegando no fim deste tutorial onde programaremos o código do botão Igual. É onde chamaremos os quatro procedimentos de adição, subtração, multiplicação e divisão. Teremos o seguinte código:

invoke GetWindowText, EditHandle, ADDR Edit_Texto, 100 invoke atodw, ADDR Edit_Texto mov Valor2, eax ;; O valor2 foi pego, então já podemos fazer a operação .if Operacao == 01h invoke Soma, Valor1, Valor2 .elseif Operacao == 02h invoke Subtracao, Valor1, Valor2 .elseif Operacao == 03h invoke Multiplicacao, Valor1, Valor2 .elseif Operacao == 04h

Na divisão temos que verificar se o valor digitado pelo usuário foi zero ("0"). Se sim, mostraremos uma mensagem dizendo que é impossível dividir por zero. Então crie duas variáveis, uma para ser o texto da mensagem e a outra o caption. O código segue abaixo.

.if Valor2 == 0 invoke MessageBox, hWnd, ADDR Texto_Msg, ADDR Titulo_Msg, MB_OK + MB_ICONEXCLAMATION invoke SetWindowText, EditHandle, NULL .elseif invoke Divisao, Valor1, Valor2 .endif invoke Divisao, Valor1, Valor2 .endif

Não execute o programa agora, pois ele daria erros dizendo que os procedimentos não existem. Então vamos criá-los. Primeiros temos que add os prototypes no início do programa.

... Gerenciador_Janela proto :DWORD, :DWORD, :DWORD, :DWORD Soma proto :DWORD, :DWORD, :DWORD, :DWORD Subtracao proto :DWORD, :DWORD, :DWORD, :DWORD Multiplicacao proto :DWORD, :DWORD, :DWORD, :DWORD Divisao proto :DWORD, :DWORD, :DWORD, :DWORD

Nesse momento você pode terminar o procedimento GerenteMensagem. Nada mais será posto lá. Então, primeiro iremos criar o procedimento de soma, o procedimento abaixo pode ser digitado antes de end inicio e fora de qualquer "proc". Considerando que já temos os dois valores predefinidos, o que precisaremos fazer? Somente adicionar um valor a outro. Procurei preservar os valores de eax e ebx, então os "pushs" e "pops" serão usados:

Soma proc Val1: DWORD, Val2: DWORD push eax push ebx xor eax, eax xor ebx, ebx ;; Zerando os valores dos dois registradores para receberem os valores Val1 e Val2 mov eax, Val1 mov ebx, Val2 ;; Agora fazendo a soma entre os dois add eax, ebx ;; Movendo o resultado para a variável que já criamos mov Resultado, eax ;; Agora como sabemos não podemos mostrar uma variável DWORD como texto ela tem ;; que ser convertida então usaremos de dword para string, na chamada passamos como ;;parâmetro o valor a ser convertido e a string que irá receber o valor. invoke dwtoa, Resultado, ADDR Edit_Texto invoke SetWindowText, EditHandle, ADDR Edit_Texto xor eax, eax mov Valor1, eax mov Valor2, eax mov Resultado, eax pop ebx pop eax ret Soma endp

Se você entendeu esse procedimento, os outros não mudam grande coisa. O da subtração (Subtracao proc Val1: DWORD, Val2: DWORD), ao invés de add eax,ebx vai usar sub eax,ebx; o da multipilicação (Multiplicacao proc Val1: DWORD, Val2: DWORD) vai usar mul ebx e o da divisão (Divisao proc Val1: DWORD, Val2: DWORD) vai usar div ebx.

Informações adicionais