December 14, 2019, 12:17:19 pm

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


4c. Messages and Message Handlers

Started by LarryMc, July 30, 2011, 05:12:36 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

Part C

To see a demonstration of messages being sent, let's modify our ex_4.iwb example:

ex_5.iwb
Code Select
openconsole
DEF w1 as WINDOW
OPENWINDOW w1,0,0,350,350,@MINBOX|@MAXBOX|@SIZE,NULL,"Simple Window",&main
WAITUNTIL w1 = 0
closeconsole
END

SUB main
static int cnt=0
cnt++
? cnt,@MESSAGE
IF @MESSAGE = @IDCLOSEWINDOW
CLOSEWINDOW w1
ENDIF
RETURN 0
ENDSUB

Notice the three new lines added at the beginning of the 'main' handler:

Code Select
static int cnt=0
cnt++
? cnt,@MESSAGE


The first line creates a STATIC, INT type, variable with an initial value of zero.
The second line will increment that variable each time the subroutine is called.
The third line will print (to the console window) the value of that variable as well as the message ID contained in @MESSAGE each pass through the handler subroutine.

Compile and run the program and perform the following actions while observing the contents of the console window.
1. Move the cursor around over the "Simple Window" client area (white portion).
2. Click/Double-click in the client area.
3. Move the cursor around over the caption area.
4. Click on the icon to the left of the title and then move the mouse over the resulting menu.
5. Drag the window by the caption bar.
6. Drag an edge of the window to resize the window.
7. Drag the caption bar of the console window so that a portion of that window covers a portion of the "Simple Window".

After playing with this for a few minutes two things should be obvious.
1. It doesn't take long for the cnt value to get rather large; meaning lots of messages are being sent.
2. Although the message numbers do change there appears to be a lot of repetitions of the same numbers.

The latter would lead us to ask, "How can the same numbers appearing over and over be of any real value?"  In order to address this question we need to go a little deeper into the discussion of messages.

Up until this point we've talked about messages as if they consisted of only a message ID.  That was done to simply the discussion. Now is the time to look at the actual structure of messages.  IWBasic has a command for sending messages and is defined in the IWBasic user's Guide as:

QuoteUINT = SENDMESSAGE(win as ANYTYPE, msg as UINT, wparam as UINT,lparam as ANYTYPE,OPT id=0 as UINT)


Let's examine each of the parameters:

win

Can be an IWBasic window, IWBasic dialog, or an OS window handle (wHnd).
______________

msg

The message ID that has been the focus of discussion up to this point.
______________

wparam

A single numeric value relative to the message being sent.
______________

lparam

Any type of variable, constant or UDT relative to the message being sent.
______________

id

Optional control id if message is being sent to a control.
______________

Some messages have no associated data values resulting in wparam and lparam being set to zero. Other messages use either or both variables.

The user's Guide also has a comment that says this IWBasic command is a convenient replacement for the SendMessageA Windows API command. In reality the IWBasic command actually calls the API command.  So what's the difference? The IWBasic version allows the user to pass a variable that is a window, dialog or hWnd and an optional control ID number.  Remember I stated that the OS has no idea what a WINDOWS UDT type variable is.  The OS system deals with handles.  So, basically, all the IWBasic SENDMESSAGE command does it determine the proper hWnd value and plugs that into the OS API version.

NOTE: The key point to remember here is that as far as the OS is concerned, when it comes to sending messages, there is no difference between what we refer to as a window and what we refer to as a control.

So, the message ID is not the only piece of information being sent to a handler (via the @MESSAGE IWBasic system variable). The wparam value is sent via  @WPARAM and the lparam value is sent via @LPARAM.  As with @MESSAGE/@CLASS being interchangeable so are the @WPARAM/@CODE  and @LPARAM/@QUAL pairs.  The IWBaic User's Guide contains a section labeled 'Windows programming' which contains a sub-section labeled 'Message ID's' (under 'Messages and message loops') that contains numerous IWBasic system message constants and their windows OS equivalents. It is highly recommended that the entire section be read and studied further.

Back to our 'Simple Window' example (Ex_4.iwb). Let's look at the handler again.

Code Select
SUB main
IF @MESSAGE = @IDCLOSEWINDOW
CLOSEWINDOW w1
ENDIF
RETURN 0
ENDSUB


Using an IF statement to check for each message we might want to use is rather inefficient. That is because each IF statement will be evaluated each pass through the handler routine. Considering that the handler routine can only be sent one message at a time there is a better way to do the testing.  NOTE: Messages can be sent to a window at a faster rate than can be addressed at any given moment. A 'queue' is used for each window where messages are placed until they can be processed. This is all handled by the OS.

The following shows the restructured handler:

Code Select
SUB main
SELECT @MESSAGE
case @IDCLOSEWINDOW
CLOSEWINDOW w1
ENDSELECT
RETURN 0
ENDSUB


Not a very impressive change but an important one. However, if we add all the messages that we might want to use, that already have IWBasic system variables defined, our example program will look something like this:

ex_6.iwb
Code Select
openconsole
DEF w1 as WINDOW
OPENWINDOW w1,0,0,350,350,@MINBOX|@MAXBOX|@SIZE,NULL,"Simple Window",&main
WAITUNTIL w1 = 0
closeconsole
END

SUB main
SELECT @MESSAGE
CASE @IDLBUTTONDBLCLK
CASE @IDLBUTTONUP
CASE @IDRBUTTONUP
CASE @IDMOUSEMOVE
CASE @IDLBUTTONDN
CASE @IDRBUTTONDN
CASE @IDRBUTTONDBLCLK
CASE @IDCONTROL
CASE @IDMENUPICK
CASE @IDMENUINIT
CASE @IDMOVE
CASE @IDMOVING
CASE @IDSIZE
CASE @IDSIZECHANGED
CASE @IDSIZING
CASE @IDHSCROLL
CASE @IDVSCROLL
CASE @IDINITDIALOG
CASE @IDCANCEL
CASE @IDCHAR
CASE @IDKEYDOWN
CASE @IDKEYUP
CASE @IDTIMER
CASE @IDPAINT
CASE @IDCREATE
CENTERWINDOW w1
CASE @IDBEFORENAV
CASE @IDNAVCOMPLETE
CASE @IDSTATUSTEXTUPDATE
CASE @IDERASEBACKGROUND
CASE @IDDESTROY
CASE @IDCLOSEWINDOW
CLOSEWINDOW w1
ENDSELECT
RETURN 0
ENDSUB

If you compile and run this example you will notice something a little different happening.  Even though we did not change the OPENWINDOW statement (which tells the OS to open the window in the upper left corner of the screen) the window opens in the middle of the screen.  If you look at the list of CASE statements you will see @IDCREATE. That message is sent when a window is going to be opened. So the window is created in the upper, left corner of the screen, relocated, and then displayed, in that order.

The reader might say, "why put the CENTERWINDOW command there?  Why not just put it on the line following the OPENWINDOW command?"  That's a valid question. The answer is that it is a matter of sequence. By placing the command at that location the window will be created in the  upper, left corner of the screen, displayed, and then relocated, in that order.  This will result in the window momentarily flickering in the corner before appearing in the center of the screen.  For the same reason the @IDCREATE message handler is a good place to set fonts, colors, and to initiate data variable displays.  Likewise, the @IDCLOSEWINDOW message can be a good place to put code that will save data before the window is closed

All the messages listed in the example are touched upon in various places in the IWBasic User's Guide.  There are two points to made here, again. One is that we can pick and choose which messages benefit us and we will use.  The other is that messages we choose not to use are still making things happen.  A good example is @IDLBUTTONUP, which is the left mouse button being released. That will cause our window to be displayed on top of other windows if it is not already.  So something is taking care of these things somewhere.

At this point we need to take a look at controls.  After our review there, we will return here and continue.
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library