|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Intrinsic Control
Routines SendMessage: Visually Pressing a Command Button Through Code |
||
Posted: | Wednesday June 2, 1999 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB4-32, VB5, VB6 | |
Developed with: | VB6, Windows NT4 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Related: |
SetWindowLong: Changing Button Caption Alignment (non-graphical only) Pure VB: Mimicking a Command Button ForeColor Property WM_DRAWITEM: Set Command Button ForeColor SendMessage: Visually Pressing a Command Button Through Code |
|
Prerequisites |
None. |
|
While
option and check buttons each provide a way to both visually indicate a change in state and activate its associated code through setting the
Value properties, the Command button's value property simply fires the underlying button click event without providing any visual feedback
that the event was fired. Some circumstances may dictate a need to not only execute the button's Click event code, but also indicate visually
to the user that the button has been activated. This code provides two simple demos to achieve the same end.
The first demo, coded in the Timer1 routine, shows how to "press a button" strictly through code using the BM_SETSTATE message. This message simply changes the highlight state of a button via the argument passed as the wParam member of SendMessage. Since "highlighting" is defined as positioning the cursor over a button and pressing and holding the left mouse button, with subsequent removal when the user releases the button, the BM_SETSTATE message therefore only changes the appearance of a button. It has no effect on the actual pressed state of a button, so it will not fire the button's associated Click event. To add the expanded functionality of firing the button's Click event, the code is duplicated in Timer2 where two additional messages are sent - WM_LBUTTONDOWN and WM_LBUTTONUP. In normal operation, these messages are posted when the user presses or releases the left mouse button while the cursor is in the client area of a window (or in our case button). For a click to register, both messages must occur. Paired with the BM_SETSTATE message, sending the WM_LBUTTONxxx messages will cause the click events to fire as well as appearing visually depressed. Without the BM_SETSTATE message, the click events to fire but with only a change in focus (the button's focus rect is set) as the visual indicator that the code has executed. Normally this code would be placed in a routine called passing the hwnd of the button to activate. For this example however, I've chosen to demo the code in Timer events. And as usual, most code below simply supports the logic to enable/disable buttons and timers - the actual code needed to perform the visual press is 3 to 5 lines.. |
BAS Module Code |
None. |
|
Form Code |
On a new form, add two timers (Timer1 & Timer2), and seven buttons in a control array (Command1(0) - Command1(6). Delete Command1(0) to allow use of the RND function in the Timer event to select the button index 1through 6. Add two additional buttons (Command 2 and Command 3), and a label (Label1). Add the following to the form: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Private Const BM_SETSTATE = &HF3 Private Const WM_LBUTTONDOWN = &H201 Private Const WM_LBUTTONUP = &H202 Private Sub Command1_Click(Index As Integer) Label1.Caption = "Button " & Index & " pressed." End Sub Private Sub Command2_Click() 'assure the other timer is disabled Timer2.Enabled = False 'Set the timer and toggle the caption Timer1.Interval = 750 Timer1.Enabled = Not Timer1.Enabled 'disable/enable the other button as appropriate Command3.Enabled = Not Timer1.Enabled Command2.Caption = IIf(Timer1.Enabled, "Press to stop", _ "Start visual press only demo") End Sub Private Sub Command3_Click() 'assure the other timer is disabled Timer1.Enabled = False 'Set the timer and toggle the caption Timer2.Interval = 750 Timer2.Enabled = Not Timer2.Enabled 'disable/enable the other button as appropriate Command2.Enabled = Not Timer2.Enabled Command3.Caption = IIf(Timer2.Enabled, "Press to stop", _ "Start visual press && click demo") End Sub Private Sub Form_Load() 'randomize the random number generator Randomize CSng(TimeValue(Time)) 'set the initial captions Command2.Caption = IIf(Timer1.Enabled, "Press to stop", _ "Start visual press only demo") Command3.Caption = IIf(Timer2.Enabled, "Press to stop", _ "Start visual press && click demo") Label1.Caption = "Click event shown here" End Sub Private Sub Timer1_Timer() Static currButton As Integer Static currHwnd As Long 'restore the last button state to normal Call SendMessage(currHwnd, BM_SETSTATE, 0, ByVal 0&) 'generate a random button index between 1 and 6 currButton = Int(Rnd(1) * 6) + 1 'get the handle to that button currHwnd = Command1(currButton).hwnd 'and change its state. Call SendMessage(currHwnd, BM_SETSTATE, 1, ByVal 0&) End Sub Private Sub Timer2_Timer() Static currButton As Integer Static currHwnd As Long 'restore the last button state to normal Call SendMessage(currHwnd, BM_SETSTATE, 0, ByVal 0&) 'generate a random button index between 1 and 6 currButton = Int(Rnd(1) * 6) + 1 'get the handle to that button currHwnd = Command1(currButton).hwnd 'and send mouse down and up messages to 'fire its click event, and visibly indicate 'its pressed state. Call SendMessage(currHwnd, WM_LBUTTONDOWN, 0, ByVal 0&) Call SendMessage(currHwnd, WM_LBUTTONUP, 0, ByVal 0&) Call SendMessage(currHwnd, BM_SETSTATE, 1, ByVal 0&) 'allow the label to repaint DoEvents End Sub |
Comments |
When Command2 is pressed, the different buttons in the
command button array will alternate becoming pressed/unpressed via the timer code. The label, reflecting the firing of the Click event, will
remain unchanged. Pressing Command3 will again toggle the pressed/unpressed state, but now Label 1 will indicate the button
"clicked".
This same technique can be extended to pressing buttons in other applications once the button hwnd has been determined. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |