Improving the "peg" handler - step 1
Compile your program and run it. Remember what happens when we don't have a resize handler to move the button relative to the edge of the window? Take a look at how it reacts now. Pretty cool! The thing is, however, that you would want to use this sort of funtionality in many of your programs and, right now, it's a bit "hard-wired" into this program. You'd have to cut and paste each time you wanted to use it and perhaps even change the names of the labels and so on. This really flies in the face of good programming practice, so we rally should try to improve it - and learn some more new stuff in the process.
The first thing we shoud know is that it is not generally considered to use "magic numbers" in our code. These are absolute numbers which appear, often for no apparent reason, in our programs and our handler has a couple of them. Can you see where they are? Yes, it's the number "4" we used for our two borders. Now, you would probably say "big deal" and, certainly, it is a very small transgression. But imagine that you did not write this code. Also imagine that there were no comments in the code. If you were to look at the handler to work out what it was doing, you see me put the width of the button into EAX and then add 4 to it. You'd be saying "why did he do that?". It is much better practice to declare a label and initialise it to the value you want. So, declare a byte called (say) "pegBorder" in the .Data setion, initialise it to 4 and then use this variable instead of the "4" in your handler. The declaration looks like this, now:
See if you can do the code for the handler yourself before looking at my solution below. Remember that the behaviour of the program (if you got the code right!) should be completely unaffected but an you see that the code is more "readble"? You don't have to puzzle over the use of "4" in the handler. You have something now called "pegBorder" and that helps the code to become more "self-documenting".
Did you remember the square brackets? Using a variable instead of a magic number has another benefit. In your code, you might be doing this addition several times. If you decided that 4 wasn't enough, you would have to go through your code and change all fours to whatever was the new value. Big danger of missing one or two. But with this approach, all you have to do is to change the initialisation value. Go ahead and try that - change the 4 to 8, for example, and then recompile. You didn't have to change a single line of code in the handler. But a word of warning - how big can you make the border using this approach? The answer is 255. You should know the reason for this - it's because we declared "pegBorder" as a byte and bytes can only hold values in the range 0-255. If you really need to have borders beyond that value, you could delare it as a DW. Try this - initialise the DB to 256 and compile it. It'll fail with a "too big" message. Now change the type to "DW", leaving the 256 as the initial value and recompile. It works. Of course, if your window is only 200 pixels wide, the button will appear to have disappeared - you will have placed it to far to the left to be visible! Same goes for the height. Keep that sort of thing in mind.
MESSAGES DD WM_CREATE, OnCreate
DD WM_CLOSE, OnClose
DD WM_SIZE, OnResize
hButton DD ?
pBox RECT
pegBorder DD 4
OnResize:
UseData winMainProcedure
; 1. Get a handle on the button
Invoke GetWindowItem, [hWnd], IDC_WINMAIN_BTNEXIT
Mov [hButton], Eax
; 2. Get the new size of the window's client area
Invoke GetClientRect, [hWnd], Addr pBox
; 3. Get the width of the button and subtract it from the width of the
; client area, together with any border
Invoke GetWidth, [hButton] ; Get the button's current width
Add Eax, [pegBorder] ; A border of 4
Mov Ebx, [pBox.right] ; Retrieve the parent's width
Sub Ebx, Eax ; Subtract the button's (plus border) width from it.
; 4. Set the "left" position of the button to the above value
Invoke SetLeft, [hButton], Ebx ; Set the button's left position to the new value
; 5. Get the height of the button and subtract it from the height of the
; client area, together with any border
Invoke GetHeight, [hButton] ; Get the button's current height
Add Eax, [pegBorder] ; A border of 4
Mov Ebx, [pBox.bottom] ; Retrieve the parent's height
Sub Ebx, Eax ; Subtract the button's (plus border) height from it.
; 6. Set the "top" position of the button to the above value
Invoke SetTop, [hButton], Ebx ; Set the button's top position to the new value
; 7. Return back to the main event loop
Return (TRUE)
; End OnResize
EndU