VBcoders Guest



Don't have an account yet? Register
 


Forgot Password?



Windows Messages and Subclassing

by IRBMe (22 Submissions)
Category: Windows System Services
Compatability: Visual Basic 3.0
Difficulty: Intermediate
Date Added: Wed 3rd February 2021
Rating: (34 Votes)

Subclassing ofers great advantages to VB programmres. This article should teach you all about the message system Windows Uses, and how to implement it into your Visual Basic Programs.

Rate Windows Messages and Subclassing

xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns="http://www.w3.org/TR/REC-html40">






Windows Programming





Windows Programming
Part 1 – Messages
 


How does the Window Operating System know what you are
doing? How does it know when you click, where you click and with what button
you click? How does it know when you press a key, what key you pressed and what
window you are typing in?  There are
many questions with only one simple answer. The answer being a message system.


 


There are many hundreds of common Windows messages, which
include the left mouse click, the right mouse click and also the key down, and
key up messages. There are other messages other than those used to indicate
user input. There is also a message for instance that tells a window to repaint
(or redraw) itself and also a timer message.


 


So how do applications receive these messages? The answer is
a “window procedure”, although not official, it is generally agreed that it
should be called “WindowProc”. The window procedure is a function that will be
called every time a message is sent to that window. It must be declared as a
public function in a module! It looks like this:


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Publicstyle='font-size:10.0pt;font-family:"Courier New";color:black'> style='font-size:10.0pt;font-family:"Courier New";color:navy'>Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'> WindowProc(style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> hwnd style='font-size:10.0pt;font-family:"Courier New";color:navy'>Asstyle='font-size:10.0pt;font-family:"Courier New";color:black'> style='font-size:10.0pt;font-family:"Courier New";color:navy'>Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> uMsg style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, _ 


none;text-autospace:none'>color:navy'>ByValcolor:black'> wParam color:navy'>As Longcolor:black'>, color:navy'>ByValcolor:black'> lParam color:navy'>As Longcolor:black'>) color:navy'>As Longcolor:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


color:navy'>End Function


 


Parameters: -


            hwnd – The window
handle of your window. A window handle is a unique number, which is assigned to
your window. Whenever you call an API function that wants to do something with
your window, you must pass the hwnd property


 


uMsg – This is the number of the message that was sent your
window. For example:


 


color:navy'>Publiccolor:black'> color:navy'>Constcolor:black'> WM_DRAWCLIPBOARD = &H308 
color:green'>‘Declare this message as ayes">           const, making it easier to deal with.


color:green'> 


You
would then use it like this:


 


color:navy'>Declare Function"Courier New";color:black'> CallWindowProc font-family:"Courier New";color:navy'>Libfont-family:"Courier New";color:black'> "user32" style='font-size:10.0pt;font-family:"Courier New";color:navy'>Aliasstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"CallWindowProcA" ("Courier New";color:navy'>ByVal"Courier New";color:black'> lpPrevWndFunc font-family:"Courier New";color:navy'>Asfont-family:"Courier New";color:black'> font-family:"Courier New";color:navy'>Longfont-family:"Courier New";color:black'>, font-family:"Courier New";color:navy'>ByValfont-family:"Courier New";color:black'> hwnd 10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> Msg style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> wParam style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> lParam style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>) style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New"'>


 


color:green'>‘...In windowproc


 


color:navy'>Select case
uMsg


style="mso-spacerun: yes">  Case style='color:black'>DRAWCLIPBOARD


color:black'>    style='font-size:10.0pt;font-family:"Courier New";color:green'>‘The data in the
clipboard has changed, so do something


color:black'>  style='font-size:10.0pt;font-family:"Courier New";color:green'>‘Case ... Other
messages go here


color:green'>  style='font-size:10.0pt;font-family:"Courier New";color:navy'>Case Else


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">      WindowProc = CallWindowProc(PrevProc,
hwnd, uMsg, wParam,   lParam) style='font-size:10.0pt;font-family:"Courier New";color:green'>‘Process all
those other messages that we don’t care about


color:navy'>Endcolor:black'> color:navy'>select


color:navy'> 


wParam/lParam – These are general parameters and can store pretty
much any values including other sub-messages. If memory serves me correctly
then the mouse move message comes with the X and Y coordinates of the mouse
stored in the wParam and lParam parameters.


 


Now some of you may be thinking, “I hope I don’t have to
process all of the hundreds of messages, my code could be thousands of lines
long”. For those of you who weren’t, well you are now. The answer is thankfully
no. There is a default window procedure that will carry out the basic commands
like painting your window, resizing it, moving it, giving it focus, and all of
the hundreds of other things.


 


We have a lot of control when it comes to messages. We can
create our own messages, send messages to the system and look at all the
messages in the message queue. Consider the following API functions:


 


 


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Declare Function style='font-size:10.0pt;font-family:"Courier New";color:black'>GetMessage style='font-size:10.0pt;font-family:"Courier New";color:navy'>Libstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"user32" color:navy'>Aliascolor:black'> "GetMessageA" (lpMsg 10.0pt;font-family:"Courier New";color:navy'>As10.0pt;font-family:"Courier New";color:black'> Msg, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> hWnd style='font-size:10.0pt;font-family:"Courier New";color:navy'>Asstyle='font-size:10.0pt;font-family:"Courier New";color:black'> style='font-size:10.0pt;font-family:"Courier New";color:navy'>Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> wMsgFilterMin style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> wMsgFilterMax style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>) style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Declare Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
TranslateMessage color:navy'>Libcolor:black'> "user32" (lpMsg font-family:"Courier New";color:navy'>Asfont-family:"Courier New";color:black'> Msg) 10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Declare Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'> DispatchMessage
Libstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"user32" color:navy'>Aliascolor:black'> "DispatchMessageA" (lpMsg style='font-size:10.0pt;font-family:"Courier New";color:navy'>Asstyle='font-size:10.0pt;font-family:"Courier New";color:black'> Msg) style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Typestyle='font-size:10.0pt;font-family:"Courier New";color:black'> POINTAPI


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    x font-family:"Courier New";color:navy'>As Long10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    y font-family:"Courier New";color:navy'>As Long10.0pt;font-family:"Courier New";color:black'>


color:navy'>End Type


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Type Msg


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    hWnd font-family:"Courier New";color:navy'>As Long10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    message 10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    wParam font-family:"Courier New";color:navy'>As Long


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    lParam font-family:"Courier New";color:navy'>As Long10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    time font-family:"Courier New";color:navy'>As Long10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    pt font-family:"Courier New";color:navy'>Asfont-family:"Courier New";color:black'> POINTAPI


color:navy'>End Type


color:navy'> 


Complicated looking isn’t it? We can use these API
functions as follows:


 


Dim aMsg style='color:navy'>as Msg


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Callstyle='font-size:10.0pt;font-family:"Courier New";color:black'> GetMessage
(aMsg, 0, 0, 0)


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Callstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
TranslateMessage (aMsg)


color:navy'>Callcolor:black'> DispatchMessage (aMsg)


color:black'> 


I think that is pretty self-explanatory. 


 


VB has a built in message handler in its form object. This
is where the events come from on your forms, and also the controls as well.
These events are just generated whenever the corresponding messages are detected
in the window Procedure. And the X and Y values in the MouseDown event for
example are just extracted from the lParam and wParam arguments in the
WindowProc function.


 


Now, why would you want to write our own message handler if
VB already provides a perfectly good one?


 


tab-stops:list 36.0pt'>a)     
VB hides a lot of the Messages from us


tab-stops:list 36.0pt'>b)     
VB deals with some messages in a way that might not suit what
we want


tab-stops:list 36.0pt'>c)     
VB processes its messages before sending us the event. What if
we don’t want it to do anything?


 


Let us consider the rather complicated topic of Winsock API.
The way Winsock lets us know what is going on is through messages sent to our
window’s message handler. However VB hides these ones from us. In order to see
them, we will have to create a window procedure of our own.


 


Now, how do we tell windows to send messages to our new
window procedure? Like so:


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Private Declarestyle='font-size:10.0pt;font-family:"Courier New";color:black'> style='font-size:10.0pt;font-family:"Courier New";color:navy'>Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'> GetWindowLong style='font-size:10.0pt;font-family:"Courier New";color:navy'>Libstyle='font-size:10.0pt;font-family:"Courier New";color:black'> _


style='font-size:10.0pt;font-family:"Courier New";color:black'>"user32"
Aliasstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"GetWindowLongA" ("Courier New";color:navy'>ByVal"Courier New";color:black'> hWnd _


style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> nIndex style='font-size:10.0pt;font-family:"Courier New";color:navy'>Asstyle='font-size:10.0pt;font-family:"Courier New";color:black'> style='font-size:10.0pt;font-family:"Courier New";color:navy'>Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>) style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Private Declare
Functioncolor:black'> SetWindowLong "Courier New";color:navy'>Lib"Courier New";color:black'> _


style='font-size:10.0pt;font-family:"Courier New";color:black'>"user32"
Aliasstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"SetWindowLongA" ("Courier New";color:navy'>ByVal"Courier New";color:black'> hWnd _


style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> nIndex style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> dwNewLong _


color:navy'>As Longcolor:black'>) color:navy'>As Long


color:navy'> 


Those are 2 new API calls, one creates a window procedure,
and the other returns the address of a window procedure given the hwnd (window
handle remember)


 


So, to set up a window procedure, we do this:


 


 


color:navy'>Publiccolor:black'> color:navy'>Constcolor:black'> GWL_WNDPROC = -4


 


Private Sub Form_Load() style='color:green'>‘Of course it doesn’t have to go in form load


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">   PrevProc = SetWindowLong(hwnd, GWL_WNDPROC,
AddressOfstyle='font-size:10.0pt;font-family:"Courier New";color:black'> WindowProc)


End sub


 


You can replace the “AddressOf WindowProc” with the name you
have given to your window procedure, but I suggest you keep the name to
WindowProc. Also remember WindowProc must be a public Function, written with
the correct parameters and everything, in a public Module.


 


This API call returns the handle to the previous window
procedure if one exists


We must store a value into PrevProc so that we can return
the default Window Procedure when we are finished. So, how do we return the
previous window procedure? Like this:


 


Private Sub
Form_Unload(Cancel as Integer) style='color:green'>‘Again, doesn’t have to be in Form_Unload


style='font-size:10.0pt;font-family:"Courier New";color:navy'>style="mso-spacerun: yes">    Iffont-family:"Courier New";color:black'> PrevProc <> 0 style='font-size:10.0pt;font-family:"Courier New";color:navy'>Thenstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">       SetWindowLong hwnd, GWL_WNDPROC,
PrevProc


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">       PrevProc = 0


color:black'>    style='font-size:10.0pt;font-family:"Courier New";color:navy'>End If


color:navy'>End Sub


 


So
now we know how to:


 


Create
the WindowProc Function.


Set
the WindowProc function as a window procedure.


Look
for messages that we want.


Extract
values from the lParam and wParam arguments.


Process
all the other messages with the default handler.


Remove our window procedure.


 


Here
is a small example taken from AllApi.Net


 


 


style='font-size:10.0pt;font-family:"Courier New";color:green'>'Create a new
project, add a module to it


style='font-size:10.0pt;font-family:"Courier New";color:green'>'Add a command
button to Form1


style='font-size:10.0pt;font-family:"Courier New";color:green'>'In the formstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Private Substyle='font-size:10.0pt;font-family:"Courier New";color:black'> Form_Load()


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    font-family:"Courier New";color:green'>'KPD-Team 1999


style='font-size:10.0pt;font-family:"Courier New";color:green'>style="mso-spacerun: yes">    'URL: http://www.allapi.net/


style='font-size:10.0pt;font-family:"Courier New";color:green'>style="mso-spacerun: yes">    'E-Mail: [email protected]


style='font-size:10.0pt;font-family:"Courier New";color:green'>style="mso-spacerun: yes">    'Subclass this form


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    HookForm Me


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    font-family:"Courier New";color:green'>'Register this form as a Clipboardviewer


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    SetClipboardViewer Me.hwnd


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Sub


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Private Substyle='font-size:10.0pt;font-family:"Courier New";color:black'>
Form_Unload(Cancel color:navy'>As Integercolor:black'>)


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    font-family:"Courier New";color:green'>'Unhook the form


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    UnHookForm Me


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Sub


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Private Substyle='font-size:10.0pt;font-family:"Courier New";color:black'>
Command1_Click()


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    font-family:"Courier New";color:green'>'Change the clipboard


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    Clipboard.Clear


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    Clipboard.SetText "Hello !"


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Sub


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:green'>'In a module


style='font-size:10.0pt;font-family:"Courier New";color:green'>'These routines
are explained in our subclassing tutorial.


style='font-size:10.0pt;font-family:"Courier New";color:green'>'http://www.allapi.net/vbtutor/subclass.php


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Declare Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'> SetWindowLong style='font-size:10.0pt;font-family:"Courier New";color:navy'>Libstyle='font-size:10.0pt;font-family:"Courier New";color:black'>
"user32" color:navy'>Aliascolor:black'> "SetWindowLongA" (font-family:"Courier New";color:navy'>ByVal hwnd As Long, ByVal nIndex As Long,
ByVal dwNewLong As Long) As Longfont-family:"Courier New";color:black'>


Declare Function
CallWindowProc Lib "user32" style='color:navy'>Alias "CallWindowProcA" (style='color:navy'>ByVal lpPrevWndFunc As Long,
ByVal hwnd As Long,
ByVal Msg As Long,
ByVal wParam As Long,
ByVal lParam As Long)
As Long


Declare Function
SetClipboardViewer Lib "user32" (style='color:navy'>ByVal hwnd As Long) style='color:navy'>As Long


 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Public Conststyle='font-size:10.0pt;font-family:"Courier New";color:black'>
WM_DRAWCLIPBOARD = &H308


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Public Conststyle='font-size:10.0pt;font-family:"Courier New";color:black'> GWL_WNDPROC =
(-4)


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Dimstyle='font-size:10.0pt;font-family:"Courier New";color:black'> PrevProc style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Long


style='font-size:10.0pt;font-family:"Courier New";color:black'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Public Substyle='font-size:10.0pt;font-family:"Courier New";color:black'> HookForm(F As
Form)


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    PrevProc = SetWindowLong(F.hwnd,
GWL_WNDPROC, color:navy'>AddressOfcolor:black'> WindowProc)


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Sub


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Public Substyle='font-size:10.0pt;font-family:"Courier New";color:black'> UnHookForm(F style='font-size:10.0pt;font-family:"Courier New";color:navy'>Asstyle='font-size:10.0pt;font-family:"Courier New";color:black'> Form)


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    SetWindowLong F.hwnd, GWL_WNDPROC,
PrevProc


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Sub


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'>Public Functionstyle='font-size:10.0pt;font-family:"Courier New";color:black'> WindowProc(style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> hwnd style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> uMsg style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Lonstyle='font-size:10.0pt;font-family:"Courier New";color:black'>g, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> wParam style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>, style='font-size:10.0pt;font-family:"Courier New";color:navy'>ByValstyle='font-size:10.0pt;font-family:"Courier New";color:black'> lParam style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>) style='font-size:10.0pt;font-family:"Courier New";color:navy'>As Longstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    WindowProc = CallWindowProc(PrevProc,
hwnd, uMsg, wParam, lParam)


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">    font-family:"Courier New";color:navy'>Iffont-family:"Courier New";color:black'> uMsg = WM_DRAWCLIPBOARD style='font-size:10.0pt;font-family:"Courier New";color:navy'>Thenstyle='font-size:10.0pt;font-family:"Courier New";color:black'>


style='font-size:10.0pt;font-family:"Courier New";color:black'>style="mso-spacerun: yes">        MsgBox "Clipboard changed
..."


style='font-size:10.0pt;font-family:"Courier New";color:navy'>style="mso-spacerun: yes">    End If


style='font-size:10.0pt;font-family:"Courier New";color:navy'>End Function


style='font-size:10.0pt;font-family:"Courier New"'> 


If
you want, you can create your own windows messages. However, problems can
arise. Imagine you use a message in a DLL as follows:


 


style='color:navy'>Const MYMSG = WM_USER + 7


 


However,
lets then imagine that another DLL uses the exact same message for something
completely different. Now to make matters worse, some poor person tries to use
the two DLL’s in the same project. Let the errors and bugs and problems
commence. Well, there is a way around this:


 


style='color:navy'>Declare Function RegisterWindowMessage style='color:navy'>Lib "user32" Alias
"RegisterWindowMessageA" (ByVal
lpString As String) As
Long


 


What
this will do is allow you to create unique message numbers. Lets say you wanted
to create your own message, you would do something like this:


 


MY_MESSAGE
= RegisterWindowMessage (“MyUniqueString”)


 


This
will assign MY_MESSAGE a new unique message number every time it is run.
However, if you put this in a DLL then how will the applications using the DLL
know what the number of your message is? They do EXACTLY the same thing as
above. When they enter “MyUniqueString” into the lpString Parameter, because it
already exists (it was originally made by your DLL remember), it will now
return the number that it assigned to MY_MESSAGE. Consider the following
example:


 


 


MESSAGE_ONE
= RegisterWindowMessage (“MyFirstString”)


Msgbox
“Your first new message is “ & MESSAGE_ONE


MEASSAGE_TWO
= RegisterWindowMessage (“MySecondString”)


Msgbox
“Your second new message is “ & MESSAGE_TWO


 


Msgbox
“How do we retrieve message one? Like this: “ & RegisterWindowMessage (“MyFirstString”)


Msgbox
“How do we retrieve message two? Like this: “ & RegisterWindowMessage (“MySecondString”)style='font-size:10.0pt;font-family:"Courier New"'>


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


style='font-size:10.0pt;font-family:"Courier New";color:navy'> 


Well,
that’s the end of this tutorial. Let me just tell you that the technical name
for this is called Sub classing, in case you ever hear it referred to as that.


 


I
hope that after reading this you understand everything, however if there is
anything you still don’t understand then visit http://www.AllAPI.net
and search for one of the API declarations mentioned in the tutorials.
Alternately, search for WindowProc, or Subclass. They should get you something.


 


I’d
just like to say how long it took me to highlight all that code in its correct
colouring, so if anybody has a good program to do that automatically, I’d be
grateful!


 


Also,
I know there are loads of people out there who know the ins and outs of Windows
messaging, and have read this for whatever reason. I know I read tutorials on
things I know inside out anyway. So, for any of you experts who have read this,
any concerns with the tutorial (Misinformation, bugs in code, even typo’s),
then I’d like to know, so leave a comment if you want.


 


I
also like to know if I have helped people, and if so, how much. So some
comments there wouldn’t go amiss.


 


Enjoy!


 


 


 


 


 


 


 


 


 


 


 


 


 





Download this snippet    Add to My Saved Code

Windows Messages and Subclassing Comments

No comments have been posted about Windows Messages and Subclassing. Why not be the first to post a comment about Windows Messages and Subclassing.

Post your comment

Subject:
Message:
0/1000 characters