There are two general methods of getting the information - repetitive use of API to check mouse/cursor status (such as within a message loop or timer) or responding to Windows messages when they are sent to notify an application that a mouse events has occurred.
As we will see, either method can be used in a PowerBASIC application, but the use of Windows messages often provides a more convenient method of getting to the needed information.
This page covers methods to detect and use the various mouse events (mouse down, mouse up, etc.).
However, it is worth mentioning that all of the common controls provide their own messages on mouse events in areas of interest in the control. Most often, the messages supplied by the common controls are all that a programmer needs to create an application.
But since common control messages do not cover all possible mouse actions, the additional of use of Windows API often proves useful in many applications.
Using Only API to Monitor Mouse Status
Information about the cursor/mouse can be retrieved at any time, regardless of
whether a mouse event has taken place. In particular, the cursor location (x,y
coordinates) within a dialog, the mouse buttons pressed (left/right/middle),
the keys pressed (Ctrl/Alt/Shift), and the handle/control ID of the child
window beneath the cursor can be retrieved using API calls.
This code gets the location, control handle, and control ID.
Local hTemp As Dword, ID as Integer, pt As Point, iResult& 'get xy coordinates GetCursorPos pt 'pt has xy screen coordinates ScreenToClient hDlg, pt 'pt now has client coordinates 'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'child control handle ID = GetDlgCtrlID (hTemp) 'returns control ID from control handle
The next code shows how to use API to get the up/down status of mouse buttons and of the ctrl/alt/shift keys (commonly used with mouse actions). In particular, the GetKeyState() and GetAsyncKeyState() API can access button/key states.
'mouse buttons (left/right/middle) iResult& = GetAsyncKeyState(%vk_lbutton) iResult& = GetAsyncKeyState(%vk_rbutton) iResult& = GetAsyncKeyState(%vk_mbutton) 'keyboard keys (Ctrl/Alt/Shift) iResult& = GetAsyncKeyState(%vk_shift) iResult& = GetAsyncKeyState(%vk_control) iResult& = GetAsyncKeyState(%vk_menu) 'alternate way to get keyboard keys status iResult& = GetKeyState(%vk_shift) iResult& = GetKeyState(%vk_control) iResult& = GetKeyState(%vk_menu)
There are complexities with using these two API, making them not as popular with programmers as the seemingly straight-forward code might suggest. See my tutorial section on key monitoring for more information.
An inconvenience of the all-API approach is that the program must include code to repeatedly test for the mouse information, usually as part of a message loop or by using a timer to trigger periodic use of the code to get the mouse information.
It is generally more convenient to let the Windows operating system send a mouse event message, which contains much of the needed information, to the application for a program response.
Sample Application - Monitoring Mouse Without Messages
Here is a complete sample application using the code above. Note that
in this example, a PowerBASIC Dialog DoEvents loop is used to repeatedly
call the monitoring code. When the sub MouseInfo is run, the results are
placed in a pair of labels.
#Compile Exe #Include "win32api.inc" Global hDlg As Dword Function PBMain() As Long Dialog New Pixels, 0, "Button Test",300,300,200,200, ) %WS_OverlappedWindow, 0 To hDlg Control Add Label, hDlg, 100,"", 50,50,100,20, %WS_Border Control Add Label, hDlg, 101,"", 50,80,100,20, %WS_Border Dialog Show Modeless hDlg Do Dialog DoEvents 0 To Count& MouseInfo Loop While Count& End Function Sub MouseInfo Local hTemp As Dword, Id As Integer, pt As PointAPI GetCursorPos pt 'pt has screen position of cursor ScreenToClient hDlg, pt 'pt now has hDlg client coordinates hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'handle of child Id = GetDlgCtrlID (hTemp) 'returns control ID hTemp = GetDlgItem(hDlg, Id) 'returns control handle Control Set Text hDlg, 100, Str$(htemp) Control Set Text hDlg, 101, Str$(Id) Control ReDraw hdlg, 100 Control ReDraw hdlg, 101 End Sub
As was noted above, this example displays the dialog as modeless and uses a message loop to continually monitor mouse information.
An alternative to the DDT DoEvents loop would be to create a timer, allowing the MouseInfo subroutine to run from within the recurring %wm_timer event messages.
More often, however, the cursor information is only needed when a mouse event (click, etc.) takes place. That's where Mouse messages come into play.
API vs DDT Comparison: Retrieving Control ID and Control Handle
This might be as good a time as any to mention some code that works
both inside and outside mouse events. Given either the ID or the handle
of a child control, PowerBASIC and the Windows API offers functions which
allow you to get the other value.
ID = GetDlgCtrlID (hTemp) 'API: use handle to get ID hTemp = GetDlgItem(hDlg, ID) 'API: use ID to get handle Window Get ID hTemp to ID 'DDT: use handle to get ID Control Handle hDlg, ID TO hTemp 'DDT: use ID to get handle
The API mentioned here were used in the first example on this page. The DDT code is provided by PowerBASIC as an alternative to the API solutions. The choice of which code to use is a personal selection, however more experienced programmers tend to use API solutions which are considered more portable between languages.
Now, on to discussing mouse messages.
Mouse Messages: Overview
Whenever a mouse event (move, up, down, doubleclick, scroll and hover) takes
place, Windows sends one or more messages to the PowerBASIC application.
The messages are sent to the callback function of the control in which
the mouse event took place. If no control callback function is available,
the mouse message is sent to the dialog callback function of the control's
parent dialog.
PowerBASIC programmers commonly use a dialog callback function to handle all messages, avoiding the use of creating a callback function for each control.
The following table lists the available mouse messages.
Client Area Non-Client Area Miscellaneous ---------------- ----------------- ------------------- WM_LBUTTONDBLCLK WM_NCLBUTTONDBLCLK WM_MOUSEMOVE WM_LBUTTONDOWN WM_NCLBUTTONDOWN WM_NCMOUSEMOVE WM_LBUTTONUP WM_NCLBUTTONUP WM_NCHITTEST WM_MBUTTONDBLCLK WM_NCMBUTTONDBLCLK WM_MOUSEACTIVATE WM_MBUTTONDOWN WM_NCMBUTTONDOWN WM_CAPUTRECHANGED WM_MBUTTONUP WM_NCMBUTTONUP WM_MOUSEHOVER WM_RBUTTONDBLCLK WM_NCRBUTTONDBLCLK WM_NCMOUSEHOVER WM_RBUTTONDOWN WM_NCRBUTTONDOWN WM_MOUSELEAVE WM_RBUTTONUP WM_NCRBUTTONUP WM_NCMOUSELEAVE WM_XBUTTONDBLCLK WM_NCXBUTTONDBLCLK WM_MOUSEWHEEL WM_XBUTTONDOWN WM_NCXBUTTONDOWN WM_MOUSEHWHEEL WM_XBUTTONUP WM_NCXBUTTONUP
Note that there are equivalent messages for client and non-client area mouse events (up/down/doubleclick) in the first two columns. The messages in the third column cover a wide range of events.
The purpose of many of these messages is self-explanatory, but additional discussion is provided below - particularly for the messages in the "Miscellaneous" column.
Mouse Terminology - Background
But before discussing how to use the mouse messages from the table above, some
mouse/cursor background information and definitions are needed.
1. WM_LBUTTONDOWN 2. WM_LBUTTONUP
There is no "click" event (such as WM_LBUTTONCLICK), but there is a doubleclick event.
1. WM_LBUTTONDOWN 2. WM_LBUTTONUP 3. WM_LBUTTONDBLCLK 4. WM_LBUTTONUP
Edit Control TreeView Trackbar Scrolls ListBox ListView Rich Edit Control ComboBox Up/Down Scrollbars
Mouse Message Content
Like any Windows message, the mouse messages listed above contain 4 numbers,
all Long data types.
hWnd | handle of the dialog/control in which the event occurred |
---|---|
Msg | message description (WM_MOUSEMOVE, WM_LBUTTONUP, ...) |
wParam | content is message dependent |
lParam | content is message dependent |
The Msg value is a numerical named_constant defined by Windows. Msg values are documented on MSDN and are included in the PowerBASIC win32api.inc include file.
Within a PowerBASIC application, the actual numerical value or text description of a Msg is not used. Only the named constants (WM_MOUSEMOVE, etc.) are used in the code.
To know what a named constants means, you'll have to visit MSDN. There is no Windows API or utility which can return a text string description of a mouse event named constant. However, a DLL (winmsg.dll) is distributed with the PowerBASIC sample applications which offers a lookup capability.
There are even a few web pages - here, here, and here - which provide lists.
Mouse Messages: wParam and lParam Data Extraction
As noted above, wParam and lParam contain values which vary from message
to message. To maximize the information that these values can send to an application,
it is common to place two numerical values into these Long (4 bytes) variables - using the
lower two bytes (low word) to store one integer value and the upper two bytes (high word)
to store a second integer value. Many, but not all, messages use this technique.
Getting the Lo/Hi word from a Long or DWord (also 4 bytes) variable can be done in several ways, using API, mathematical operations, or with DDT commands.
Here's example code that uses the PowerBASIC Lo/Hi functions to extract lo/hi values from a wParam value. There's also a line of code which will place integer values in the low and high words of a Long/DWord variable.
LoValue% = Lo(Word, wParam) HiValue% = Hi(Word, wParam) Result = Mak(DWORD, LoValue%, HiValue%)
In a PowerBASIC program, the wParam value is normally retrieved within a callback function using the CB function, so wParam would be normally be replaced with CB.wParam, as would the lParam message value be retrieved with CB.lParam.
Mouse Messages: Up, Down, DblClick
Finally - we're getting to actual mouse messages! Here's the listing of the
24 mouse messages corresponding to the up/down/dblclick (remember, Windows has no
"click" mouse event) messages. There are corresponding messages for the client
area and non-client area mouse messages.
Client Area Non-Client Area ---------------- ----------------- WM_LBUTTONDBLCLK WM_NCLBUTTONDBLCLK WM_LBUTTONDOWN WM_NCLBUTTONDOWN WM_LBUTTONUP WM_NCLBUTTONUP WM_MBUTTONDBLCLK WM_NCMBUTTONDBLCLK WM_MBUTTONDOWN WM_NCMBUTTONDOWN WM_MBUTTONUP WM_NCMBUTTONUP WM_RBUTTONDBLCLK WM_NCRBUTTONDBLCLK WM_RBUTTONDOWN WM_NCRBUTTONDOWN WM_RBUTTONUP WM_NCRBUTTONUP WM_XBUTTONDBLCLK WM_NCXBUTTONDBLCLK WM_XBUTTONDOWN WM_NCXBUTTONDOWN WM_XBUTTONUP WM_NCXBUTTONUP
The great thing about these messages is that the message values all have the same content.
Here's more information about the content of wParam and lParam, and how to extract the information. Remember, this only applies to the 24 mouse events listed above. The Miscellaneous column of mouse messages have different wParam/lParam message value content.
MK_LBUTTON - Left button MK_CONTROL - Ctrl Key MK_MBUTTON - Middle button MK_SHIFT - Shift Key MK_RBUTTON - Right button MK_XBUTTON1 - 1st XButton MK_XBUTTON2 - 2nd XButton
To test if any button/key was pressed, use the following code (substituting %MK_LBUTTON with any of the key constants listed above).
If Lo(Word, CB.wParam) AND %MK_LBUTTON Then ... 'left button was pressed
Except for the XButton messages, the hi word of wParam is empty. So for the Left/Right/Middle button message, the entire value of CB.wParam can be used instead of having to first extract the lo word.
The high word of wParam is not used except for the XButton messages, in which case the hi word of wParam indicates whether XButton1 or XButton2 was pressed.
x = Lo(Word, CB.lParam) 'returns x coordinate y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code from the first example at the top of this page.
'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, x, y) 'get control handle ID = GetDlgCtrlID (hTemp) 'get control ID
It's worth mentioning again that almost all of the common controls provide their own events to indicate when a mouse clicks on areas of the control. Most often, those events are all that a programmer needs to create a user interface. However the dialog does not provide such events, nor do the control events cover all possible mouse actions, so the information just presented can be useful.
As helpful as these events might seem, monitoring 24 different mouse events can be pretty cumbersome. In the following discussion of the Miscellaneous column of mouse messages, we'll see that other mouse messages can simplify the task of monitoring for mouse events.
Miscellaneous Mouse Messages
Here is a description of the remaining mouse messages. Though fewer in
number, you'll find several of these to be generally more useful than
the messages already discussed.
WM_MOUSEMOVE - moves within the client area WM_NCMOUSEMOVE - moves within the non-client area WM_NCHITTEST - determines if event was in non-client area WM_MOUSEACTIVATE - set top-level window as active WM_CAPTURECHANGED - sent to window losing mouse capture WM_MOUSEHOVER - hovers for a certain time period over client area WM_NCMOUSEHOVER - hovers for a certain time period over non-client area WM_MOUSELEAVE - leaves the client area WM_NCMOUSELEAVE - leaves the non-client area WM_MOUSEHWHEEL - detects movement of mouse wheel WM_MOUSEWHEEL - detects movement of mouse wheel
Each of these are discussed below, including the content of wParam/lParam and how it might be used.
WM_PARENTNOTIFY
Surprise! This message was not discussed earlier, because it
is not a mouse message, but rather a dialog message. This message
is sent to the dialog when the user clicks a mouse on a child
window. This is one of the most common mouse clicks. So if the
child control does not provide an event for the click, then the
WM_PARENTNOTIFY event is the first place to go, even before the
dedicated mouse event messages!
Which mouse button was pressed and the xy coordinates of the cursor (client coordinates) are provided by WM_PARENTNOTIFY.
WM_LBUTTONDOWN WM_RBUTTONDOWN WM_MBUTTONDOWN
To test if any button/key was pressed, use the following code with one of the above values.
If CB.wParam AND %WM_LBUTTONDOWN Then ... 'left button was pressed
x = Lo(Word, CB.lParam) 'returns x coordinate y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code, which has been discussed already.
'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, x, y) 'child control handle ID = GetDlgCtrlID (hTemp) 'returns control ID from control handle
WM_SETCURSOR
Surprise, again! This message was not discussed earlier, because it
is not a mouse message, but rather a cursor message (the only
cursor message Windows provides).
Nonetheless, it provides information useful to a PowerBASIC programmer in working with a mouse. Whereas the WM_MOUSEMOVE and WM_NCMOUSEMOVE work only on either the client and non-client areas, respectively, the WM_SETCURSOR message is sent when mouse movement occurs anywhere within a window.
The dialog/control where the mouse was located, the message identifier, and the section of the window beneath the cursor are provided by WM_SETCURSOR.
hWnd = CB.wParam 'may be a dialog or child control
The hit-test returns one of these values, indicating where the cursor is located.
HTBORDER border of a window that does not have a sizing border HTBOTTOM lower-horizontal border of a resizable window HTBOTTOMLEFT lower-left corner of a border of a resizable window HTBOTTOMRIGHT lower-right corner of a border of a resizable window HTCAPTION title bar HTCLIENT client area HTCLOSE close button HTERROR screen background or on a dividing line between windows HTGROWBOX size box (same as HTSIZE) HTHELP Help button HTHSCROLL horizontal scroll bar HTLEFT left border of a resizable window HTMENU menu HTMAXBUTTON Maximize button HTMINBUTTON Minimize button HTNOWHERE screen background or on a dividing line between windows HTREDUCE Minimize button HTRIGHT right border of a resizable window HTSIZE size box (same as HTGROWBOX) HTSYSMENU window menu or in a Close button in a child window HTTOP upper-horizontal border of a window HTTOPLEFT upper-left corner of a window border HTTOPRIGHT upper-right corner of a window border HTTRANSPARENT window currently covered by another window in the same thread HTVSCROLL vertical scroll bar HTZOOM Maximize button
To test which area the cursor is over, use this code with one of the above values.
If CB.lParam = %HTCLIENT Then ... 'mouse moved over client area
With the handle available, the xy coordinates and control ID can be retrieved with these lines of API code. The alternate approach of using DDT code to get the control ID is also shown.
'get xy coordinates GetCursorPos pt 'pt has xy screen coordinates ScreenToClient hDlg, pt 'pt now has client coordinates 'get control handle and ID hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'get control handle ID = GetDlgCtrlID (hWnd) 'API: get control ID Window Get ID hTemp to ID 'DDT: get control ID
WM_MOUSEMOVE, WM_NCMOUSEMOVE
These messages are sent when a mouse is moved in the client
or non-client areas, respectively.
MK_LBUTTON - Left button MK_CONTROL - Ctrl Key MK_MBUTTON - Middle button MK_SHIFT - Shift Key MK_RBUTTON - Right button MK_XBUTTON1 - 1st XButton MK_XBUTTON2 - 2nd XButton
To test if any button/key was pressed, use the following code (substituting %MK_LBUTTON with any of the key constants listed above).
If Lo(Word, CB.wParam) AND %MK_LBUTTON Then ... 'left button was pressed
Except for the XButton messages, the hi word of wParam is empty. So for the Left/Right/Middle button message, the entire value of CB.wParam can be used instead of having to first extract the lo word.
The high word of wParam is not used except for the XButton messages, in which case the hi word of wParam indicates whether XButton1 or XButton2 was pressed.
x = Lo(Word, CB.lParam) 'returns x coordinate y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code, which has been discussed already. Note that since xy are screen coordinates, they must first be converted to dialog coordinates.
'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, x, y) 'returns control handle ID = GetDlgCtrlID (hTemp) 'returns control ID
WM_NCHITTEST
This message is sent to a window when the cursor moves, or when a
mouse button is pressed or released - basically the entire waterfront
of events.
The only information provided is the xy coordinates of the cursor (screen coordinates). But, once the user sends this message on to the DefWindowProc, a return value will be received which is one of the hit-test position indicators (see values in WM_SETCURSOR discussion above).
To send the message on the DefWindowProc, use the following code:
iResult& = DefWindowProc(CB.hWnd,CB.Msg,CB.wParam,CB.lParam)
And here's the information provided by wParam and lParam.
pt.x = Lo(Word, CB.lParam) 'returns x coordinate pt.y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code, which has been discussed already. Note that since xy are screen coordinates, they must first be converted to dialog coordinates.
'get child handle and ID ScreenToClient hDlg, pt 'pt now has hDlg client coordinates hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'returns control handle ID = GetDlgCtrlID (hTemp) 'returns control ID
WM_MOUSEACTIVATE
This message is sent when the cursor is over an inactive window and the
user presses a mouse button.
The hit-test returns one of these values, indicating where the cursor is located. See the list of hit-test values in WM_SETCURSOR above
To test which area the cursor is over, use this code with one of hit-test values.
If CB.lParam = %HTCLIENT Then ... 'mouse moved over client area
With the handle available, the xy coordinates and control ID can be retrieved with these lines of API code. The alternate approach of using DDT code to get the control ID is also shown.
'get xy coordinates GetCursorPos pt 'pt has xy screen coordinates ScreenToClient hDlg, pt 'pt now has client coordinates 'get control handle and ID hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'get control handle ID = GetDlgCtrlID (hWnd) 'API: get control ID Window Get ID hTemp to ID 'DDT: get control ID
WM_CAPTURECHANGED
At any one time, only one window can receive mouse inputs. That window
is said to have gained the mouse capture.
Normally, clicking on a window gives it focus and captures the mouse. However, a window can use SetCapture to capture the mouse. A window that has captured the mouse receives all mouse input, regardless of the position of the cursor, except when a mouse button is clicked while the cursor is in the window of another thread. The ReleaseCapture functions releases mouse capture from a window and restores normal mouse input processing.
When a window loses mouse capture, it is sent the message WM_CAPTURECHANGED.
WM_MOUSEHOVER
Hovering is only tracked when a TrackMouseEvent function is
called, specifying a window to track and the time interval which
constitutes "hovering". Once TrackMouseEvent is called, the
WM_MOUSEHOVER, WM_NCMOUSEHOVER, WM_MOUSELEAVE, and WM_NCMOUSELEAVE
messages will be generated.
WM_MOUSEHOVER is posted when the cursor hovers over the non-client area for a specified time.
MK_LBUTTON - Left button MK_CONTROL - Ctrl Key MK_MBUTTON - Middle button MK_SHIFT - Shift Key MK_RBUTTON - Right button MK_XBUTTON1 - 1st XButton MK_XBUTTON2 - 2nd XButton
To test if any button/key was pressed, use the following code (substituting %MK_LBUTTON with any of the key constants listed above).
If Lo(Word, CB.wParam) AND %MK_LBUTTON Then ... 'left button was pressed
Except for the XButton messages, the hi word of wParam is empty. So for the Left/Right/Middle button message, the entire value of CB.wParam can be used instead of having to first extract the lo word.
The high word of wParam is not used except for the XButton messages, in which case the hi word of wParam indicates whether XButton1 or XButton2 was pressed.
x = Lo(Word, CB.lParam) 'returns x coordinate y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code, which has been discussed already. Note that since xy are screen coordinates, they must first be converted to dialog coordinates.
'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, x, y) 'returns control handle ID = GetDlgCtrlID (hTemp) 'returns control ID
WM_NCMOUSEHOVER
Hovering is only tracked when a TrackMouseEvent function is
called, specifying a window to track and the time interval which
constitutes "hovering". Once TrackMouseEvent is called, the
WM_MOUSEHOVER, WM_NCMOUSEHOVER, WM_MOUSELEAVE, and WM_NCMOUSELEAVE
messages will be generated.
WM_NCMOUSEHOVER is posted when the cursor hovers over the non-client area for a specified time.
The hit-test returns one of these values, indicating where the cursor is located. See the list of hit-test values in WM_SETCURSOR above
To test which area the cursor is over, use this code with one of hit-test values.
If CB.lParam = %HTCLIENT Then ... 'mouse moved over client area
With the handle available, the xy coordinates and control ID can be retrieved with these lines of API code. The alternate approach of using DDT code to get the control ID is also shown.
'get xy coordinates GetCursorPos pt 'pt has xy screen coordinates ScreenToClient hDlg, pt 'pt now has client coordinates 'get control handle and ID hTemp = ChildWindowFromPoint(hDlg, pt.x, pt.y) 'get control handle ID = GetDlgCtrlID (hWnd) 'API: get control ID Window Get ID hTemp to ID 'DDT: get control ID
Dim pt as POINTS 'a Type Points is contained in "win32api.inc" pt = @CB.lParam 'lParam has pointer to POINTS structure
WM_MOUSELEAVE, WM_NCMOUSELEAVE
These messages work with WM_MOUSEHOVER and WM_NCMOUSEHOVER,
and are posted when the cursor leaves the client (WM_MOUSELEAVE)
or the non-client (WM_NCMOUSELEAVE) area of the window specified
in a prior call to TrackMouseEvent.
Tracking requested by TrackMouseEvent is canceled when this message is generated.
The TrackMouseEvent() specifies a handle of the window to track, so any information supplied to wParam/lParam would be redundant.
WM_MOUSEWHEEL, WM_MOUSEHWHEEL
The wheel on a mouse can be pressed, or rotated.
When pressed, it is treated as a middle mouse button, whose events were covered further up this page.
When the wheel is rotated, the WM_MOUSEWHEEL message is sent to the focus window.
The WM_MOUSEWHEEL message return the amount of rotation, which keys are down, and the xy screen coordinates of the pointer.
MK_LBUTTON - Left button MK_CONTROL - Ctrl Key MK_MBUTTON - Middle button MK_SHIFT - Shift Key MK_RBUTTON - Right button MK_XBUTTON1 - 1st XButton MK_XBUTTON2 - 2nd XButton
To test if any button/key was pressed, use the following code (substituting %MK_LBUTTON with any of the key constants listed above).
If Lo(Word, CB.wParam) AND %MK_LBUTTON Then ... 'left button was pressed
The hi word value of xParam gives the distance the wheel is rotated. Positive and negative values are returned.
x = Lo(Word, CB.lParam) 'returns x coordinate y = Hi(Word, CB.lParam) 'returns y coordinate
Then, the handle and ID of a child control under the cursor can be retrieved from this code, which has been discussed already. Note that since xy are screen coordinates, they must first be converted to dialog coordinates.
'get child handle and ID hTemp = ChildWindowFromPoint(hDlg, x, y) 'returns control handle ID = GetDlgCtrlID (hTemp) 'returns control ID
MousePTR DDT Function
Slightly outside the topic of mouse messages, is the PowerBASIC
function MousePTR, which can set the mouse pointer to a new shape.
MousePTR is often used as part of the response to mouse events.
MOUSEPTR iStyle& TO iResult& 'TO is optional
iResult is set to zero if the operation fails, or to a handle for the old cursor if it succeeds. The handle may be used to restore the cursor by using it in place of iStyle&
iStyle options are:
0 - Hide 7 - Pointer: Vertical 1 - Arrow 8 - Pointer: NW-SE diagonal 2 - Cross 9 - Pointer: Horizontal 3 - I-Beam 10 - Up arrow 4 - Arrow 11 - Hourglass 5 - Pointer: all directions 12 - No mouse pointer 6 - Pointer: NE-SW diagonal 13 - Arrow w/hourglass
If you have any suggestions or corrections, please let me know.