Put this code in Form1, and make sure to set the form's AutoRedraw property to True (you won't want printed text disappearing permanently if it's below the form and you just need to resize it).
Put this code in Module1.
When the program is run, two buttons will appear on the form. If you click the one called Test Button 1, it will print "123" on Form1. If you click the button called Test Button 2, it will print "ABC" on Form1.
Each button will respond after releasing it from a click. If you want it to respond at the instant it's clicked, instead of waiting to be released, comment out the line of code:
and uncomment out the line of code:
Code:
Private Declare Function CreateWindowEx Lib "user32.dll" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByRef lpParam As Any) As Long
Private Declare Function DestroyWindow Lib "user32.dll" (ByVal hWnd As Long) As Long
Private Const WS_VISIBLE As Long = &H10000000
Private Const WS_CHILD As Long = &H40000000
Public IsRunning As Boolean
Private Sub Form_Load()
'set the BUTTON window class function
hButton = CreateWindowEx(0, "BUTTON", "", 0, 0, 0, 0, 0, 0, 0, 0, ByVal 0&)
OldWndProc = SetClassLong(hButton, GCL_WNDPROC, AddressOf WndProc)
DestroyWindow hButton
'create buttons
hButton = CreateWindowEx(0, "BUTTON", "Test Button 1", WS_VISIBLE Or WS_CHILD, 50, 20, 120, 30, hWnd, 0, 0, ByVal 0&)
hButton2 = CreateWindowEx(0, "BUTTON", "Test Button 2", WS_VISIBLE Or WS_CHILD, 50, 20 + 30, 120, 30, hWnd, 0, 0, ByVal 0&)
'make sure the button class function knows the program is running
IsRunning = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
'make sure the button class function knows the program is not running
IsRunning = False
'restore original BUTTON window class function
SetClassLong hButton, GCL_WNDPROC, OldWndProc
'remove buttons
DestroyWindow hButton
DestroyWindow hButton2
End Sub
Put this code in Module1.
Code:
Public Declare Function SetClassLong Lib "user32.dll" Alias "SetClassLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GCL_WNDPROC As Long = -24
Public Const WM_LBUTTONDOWN As Long = &H201
Public Const WM_LBUTTONDBLCLK As Long = &H203
Public Const WM_LBUTTONUP As Long = &H202
Public OldWndProc As Long
Public hButton As Long
Public hButton2 As Long
'function to handle all button messages
Public Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Form1.IsRunning Then
'If (uMsg = WM_LBUTTONDOWN) Or (uMsg = WM_LBUTTONDBLCLK) Then ButtonClick hWnd
If uMsg = WM_LBUTTONUP Then ButtonClick hWnd
End If
WndProc = CallWindowProc(OldWndProc, hWnd, uMsg, wParam, lParam)
End Function
'function to handle all button clicks
Private Sub ButtonClick(ByVal hWnd As Long)
Select Case hWnd
Case hButton
Button1Clicked
Case hButton2
Button2Clicked
End Select
End Sub
'click handler for button 1
Private Sub Button1Clicked()
Form1.Print "123"
End Sub
'click handler for button 2
Private Sub Button2Clicked()
Form1.Print "ABC"
End Sub
When the program is run, two buttons will appear on the form. If you click the one called Test Button 1, it will print "123" on Form1. If you click the button called Test Button 2, it will print "ABC" on Form1.
Each button will respond after releasing it from a click. If you want it to respond at the instant it's clicked, instead of waiting to be released, comment out the line of code:
Code:
If uMsg = WM_LBUTTONUP Then ButtonClick hWnd
Code:
'If (uMsg = WM_LBUTTONDOWN) Or (uMsg = WM_LBUTTONDBLCLK) Then ButtonClick hWnd