|
-
Oct 13th, 2000, 09:08 AM
#1
Thread Starter
Hyperactive Member
Ok, I've basically been able to use the simplicity of the VB forms and just draw whatever I need for a program. But for C++, you kinda need to use the API to draw your windows! Now, I don't intend to sit here and make my own windows so I don't have to bother with VB ones, but I was wondering how you would use API to capture the key presses ,clicks, resizes, all that good stuff, sent to that window. I know the API, but a little unsure of how to make it work. Can anyone example something for me?
-
Oct 13th, 2000, 10:29 AM
#2
Guru
Every window (including controls, etc.) has its Window Procedure.
A Window Procedure is a function, associated with the window. The operating system sends a message to the window whenever something happens to it - the message is processed in one of those Window Procedures.
Here's how it generally looks like:
Code:
Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
' Blah
End Select
End Function
The parameters:
- hWnd: The handle of the window associated with this message.
- uMsg: The message code.
- wParam: A parameter associated with the message.
Usually, wParam is used to pass a long value.
- lParam: Another parameter associated with the message.
Usually, lParam is used to pass a pointer to a structure or to a string, but sometimes it is also just a long value.
The WindowProc returns a value, depending on the message. For some messages, it also changes the structure specified by lParam.
uMsg is an important parameter here: It specifies the message code, which is basically what happened to the window.
Such a window code is a constant value, which looks like this: WM_SOMETHING
You can find a lot of those in the API Viewer, and in MSDN.
Common messages:
- WM_PAINT: This occurs when a window needs to be painted.
The wParam specifies the hDC of the window that needs painting, and lParam is unused.
WindowProc should return zero.
When VB processes this, it raises the Paint event.
- WM_CREATE: This happens when a window (or a control) is created.
wParam is unused, and lParam is a pointer to a CREATESTRUCT structure containing information about the window being created.
WindowProc returns zero to confirm the creation of the window, or -1 to cancel it.
VB raises the Load event here.
- WM_CLOSE: This happens when a window needs to be closed.
wParam and lParam are both unused, and WindowProc returns zero.
The closing of the window can be cancelled.
VB translates it to an Unload event.
- WM_SIZE: This happens when a window is resized.
wParam is a flag specifying how the window is resized.
lParam is two integers (words) combined - the low-order word is the new width, and the high-order word is the new height.
WindowProc returns zero.
VB uses the Resize event.
I hope you aren't too confused by now. 
Here's some more confusion:
The address of the WindowProc is stored in an internal variable.
You can access this variable by using GetWindowLong and SetWindowLong.
The variable index is GWL_WNDPROC.
So, you can replace VB's WindowProc with your own (This is called subclassing).
If you want the old (VB's) WindowProc to process most of the messages, and your own to process just a few - you can use the CallWindowProc function to pass the message to the old one.
Here's an example subclassed form:
Note! This example uses the AddressOf keyword, which was unavailable before VB4. So, you must have at least VB5 to use this.
Form code:
Code:
Option Explicit
Private Sub Form_Load()
' Subclass this form:
Call Subclass(Me)
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
' Unhook the form from the subclass:
Call RemoveSubclass
' Warning: If you don't unhook the subclass when the form unloads,
' your program will crash!
End Sub
Sub Form_FormMove(ByVal X As Long, ByVal Y As Long)
' New event, thanks to the subclass!
Debug.Print "New position (pixels): (" & X & ", " & Y & ")"
End Sub
Module code:
Code:
Option Explicit
Public Const GWL_WNDPROC = (-4)
Public Const WM_MOVE = &H3
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim lpPrevWndProc As Long
Dim frmSubclass As Form
Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim X As Long, Y As Long
' No need for a Select Case here, because we're only processing one message.
If uMsg = WM_MOVE Then
' The form has been moved.
' wParam: Unused.
' lParam: Double-word.
' Low word of lParam: New X coordinate.
' High word of lParam: New Y coordinate.
' Put the low word of lParam in X:
X = lParam And &HFFFF&
' Put the high word of lParam in Y:
Y = lParam \ &H10000
' Raise the event in the form:
Call frmSubclass.Form_FormMove(X, Y)
' WindowProc should return zero when processing WM_MOVE.
WindowProc = 0 ' This line isn't needed (zero by default) - just for explanation.
Exit Function
End If
' If the message isn't WM_MOVE, we want VB's WindowProc to process it.
' The address of the old WindowProc is in the variable lpPrevWndProc,
' and all the parameters are right here.
' So, we're ready to call it (and return the correct value):
WindowProc = CallWindowProc(lpPrevWndProc, hWnd, uMsg, wParam, lParam)
End Function
Sub Subclass(frmToSubclass As Form)
' Set the frmSubclass object to the form we want to subclass:
Set frmSubclass = frmToSubclass
' Subclass it:
' SetWindowLong returns the old value of GWL_WNDPROC.
' This old value is the address of VB's WindowProc.
' The third parameter is the new value for GWL_WNDPROC:
' The address of our own WindowProc.
lpPrevWndProc = SetWindowLong(frmSubclass.hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Sub RemoveSubclass()
' Set the WindowProc back to VB's WindowProc:
Call SetWindowLong(frmSubclass.hWnd, GWL_WNDPROC, lpPrevWndProc)
' Invalidate the frmSubclass object (we don't need it anymore):
Set frmSubclass = Nothing
End Sub
Now you're probably REALLY confused! 
You'll get over it.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|