Previous page Select page Next page

Click handlers

Knowing how to shift bits around helps us in another way - we can now handle button clicks. The Windows message is WM_COMMAND, which means we need to catch and handle it. So, let's call the handler "onClickBtn".


  MESSAGES	DD WM_CREATE, OnCreate

		DD WM_CLOSE, OnClose

		DD WM_COMMAND, onClickBtn

Make yourself a window like the one shown here. Make the captions as shown with two buttons called "btn1" and "btn2" The idea is that when a button is clicked, it will display an appropriate message in the caption bar of the window, such as "You clicked Button One!!!".

So, we now have the window, the buttons and the event message. Let's now turn to the "onClickBtn" handler code. The first thing is to do is to use the winMainProcedure parameters by means of the UseData command with its corresponding EndU. That will give us the same information that was passed to the main window when the event occurred. Take a look at winMainProcedure, noting the parameters. We have:

We know that hWnd represents our winMain and the uMsg is the WM_COMMAND message. We can disegard lParam for our purposes, so that just leaves us with wParam. We need, therefore to get this value into a register so that we can process it a little further and compare it with known values. This is how we could begin coding the handler:


  onClickBtn:

    UseData winMainProcedure

    Mov Eax, [wParam]

    EndU

  ; End onClickBtn

Now, we know that the lower 16 bits of wParam represent the ID of the control. Our two buttons have IDs of IDC_WINMAIN_BTN1 and IDC_WINMAIN_BTN2, so we could do a CMP and a jump to help us move to the correct part of our routine to handle the specific button involved. If the ID is in the lower 16 bits of Eax, that means it is in the Ax part of the register.


  onClickBtn:

    UseData winMainProcedure

    Mov Eax, [wParam]

    Cmp Ax, IDC_WINMAIN_BTN1	; Is this button 1?

      Jnz >.notButton1

    ... ... ...

    Return (TRUE)



  .notButton1			; This is not button 1

    Cmp Ax, IDC_WINMAIN_BTN2	; Is this button 2?

      Jnz >.exitProcedure

    ... ... ...

    Return (TRUE)



  .exitProcedure		; This is neither button 1 nor button 2

    Return (FALSE)

    EndU

  ; End onClickBtn

You can see from the fragment above that we compare the contents of Ax sub-register against the ID of Button 1. If the Zero Flag is not set, we know it isn't that button and we jump to the label called ".notButton1" where we compare Ax with the ID for Button 2. This time, if the Zero flag is clear, we jump to our third label where we exit from the routine, since the user has clicked something which is neither of the buttons. However, you must remember to put "Returns" in the code as shown to prevent a successful comparison from executing "too much" code. For example, imagine that we clicked Button 1. In the first comparison, the Zero Flag will be set. We will not jump to ".notButton1". Instead, we will execute the code which we have not shown yet. But what stops the program from going on and then executing the code which follows the ".notButton1" label? The Return(TRUE) which we have placed before that label, is the answer. OK, so we're in the right "leg" of the branch. How do we compare the upper 16 bits of the Eax register to find out whether it was a click, a double-click, a right-click, etc? Well this is where the shoft commands come in - all we have to do is to shift Eax 16 bits to the right and the top 16 will be shifted into the place currently occupied by the lower 16. Then, all we have to do is to do a CMP with the Windows constant BN_CLICKED. If the zero flag is set, we have a left click, otherwise we again jump to the ".exitProcedure" label and leave the routine by the fire escape. Here's the full routine, complete with the code to change the caption of the main window:


  onClickBtn:

    UseData winMainProcedure

    Mov Eax, [wParam]

    Cmp Ax, IDC_WINMAIN_BTN1	; Is this button 1?

      Jnz >.notButton1

    Shr Eax, 16

    Cmp Ax, BN_CLICKED

    Jnz >.exitProcedure

    Invoke SetText, [hWnd], "You clicked Button One!!!"

    Return (TRUE)



  .notButton1			; This is not button 1

    Cmp Ax, IDC_WINMAIN_BTN2	; Is this button 2?

      Jnz >.exitProcedure

    Shr Eax, 16

    Cmp Ax, BN_CLICKED

    Jnz >.exitProcedure

    Invoke SetText, [hWnd], "You clicked Button Two!!!"

    Return (TRUE)



  .exitProcedure		; This is neither button 1 nor button 2

    Return (FALSE)

    EndU

  ; End onClickBtn

Previous page Select page Next page