Quick Search for:  in language:    
Subclassing,ofers,great,advantages,programmre
   Code/Articles » |  Newest/Best » |  Community » |  Jobs » |  Other » |  Goto » | 
CategoriesSearch Newest CodeCoding ContestCode of the DayAsk A ProJobsUpload
Visual Basic Stats

 Code: 3,011,557. lines
 Jobs: 115. postings

 How to support the site

 
Sponsored by:

 

You are in:

 
Login



Latest Code Ticker for Visual Basic.
Locate Database
By Erica Ziegler-Roberts on 6/30


Organize the errors of your programs
By Toni on 6/30


how to open and close access database
By Freebug on 6/29


Click here to see a screenshot of this code!PSC-Browser
By Ralph LONG Metz on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Quadratic Solver 2
By Guillaume Couture-Levesqu e on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Array Example
By Cold Fire on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Reconstructor 3.0
By Peter Scale on 6/29

(Screen Shot)

Click here to see a screenshot of this code!Subtitles Manager
By KarahaNa on 6/29

(Screen Shot)

XPlorer
By ZProse on 6/29


Click here to put this ticker on your site!


Add this ticker to your desktop!


Daily Code Email
To join the 'Code of the Day' Mailing List click here!





Affiliate Sites



 
 
   

Windows Messages and Subclassing

Print
Email
 

Submitted on: 4/25/2002 2:40:11 PM
By: Coding Genius 
Level: Intermediate
User Rating: By 32 Users
Compatibility:VB 5.0, VB 6.0

Users have accessed this article 6349 times.
 

(About the author)
 
     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.

 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.   
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
Windows Programming <--[if gte mso 9]> Christopher Waddell Christopher Waddell 3 94 2002-04-25T17:06:00Z 2002-04-26T15:50:00Z 5 1596 9098 Developement 75 18 11172 9.4402

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:


 

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, _

ByVal wParam As Long, ByVal lParam As Long) As Long

 

 

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:

 

Public Const WM_DRAWCLIPBOARD = &H308  ‘Declare this message as a           const, making it easier to deal with.

 

You would then use it like this:

 

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

 

‘...In windowproc

 

Select case uMsg

  Case DRAWCLIPBOARD

    ‘The data in the clipboard has changed, so do something

  ‘Case ... Other messages go here

  Case Else

      WindowProc = CallWindowProc(PrevProc, hwnd, uMsg, wParam,   lParam) ‘Process all those other messages that we don’t care about

End select

 

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:

 

 

 

Declare Function GetMessage Lib "user32" Alias "GetMessageA" (lpMsg As Msg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long

 

Declare Function TranslateMessage Lib "user32" (lpMsg As Msg) As Long

 

Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As Msg) As Long

 

Type POINTAPI

    x As Long

    y As Long

End Type

 

Type Msg

    hWnd As Long

    message As Long

    wParam As Long

    lParam As Long

    time As Long

    pt As POINTAPI

End Type

 

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


 

Dim aMsg as Msg

 

Call GetMessage (aMsg, 0, 0, 0)

Call TranslateMessage (aMsg)

Call DispatchMessage (aMsg)

 

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?

 

a)      VB hides a lot of the Messages from us

b)      VB deals with some messages in a way that might not suit what we want

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:

 

Private Declare Function GetWindowLong Lib _

"user32" Alias "GetWindowLongA" (ByVal hWnd _

As Long, ByVal nIndex As Long) As Long

 

Private Declare Function SetWindowLong Lib _

"user32" Alias "SetWindowLongA" (ByVal hWnd _

As Long, ByVal nIndex As Long, ByVal dwNewLong _

As Long) As Long

 

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:

 

 

Public Const GWL_WNDPROC = -4

 

Private Sub Form_Load() ‘Of course it doesn’t have to go in form load

   PrevProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf 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) ‘Again, doesn’t have to be in Form_Unload

    If PrevProc <> 0 Then

       SetWindowLong hwnd, GWL_WNDPROC, PrevProc

       PrevProc = 0

    End If

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

 

 

'Create a new project, add a module to it

'Add a command button to Form1

'In the form

Private Sub Form_Load()

    'KPD-Team 1999

    'URL: http://www.allapi.net/

    'E-Mail: KPDTeam@Allapi.net

    'Subclass this form

    HookForm Me

    'Register this form as a Clipboardviewer

    SetClipboardViewer Me.hwnd

End Sub

 

Private Sub Form_Unload(Cancel As Integer)

    'Unhook the form

    UnHookForm Me

End Sub

 

Private Sub Command1_Click()

    'Change the clipboard

    Clipboard.Clear

    Clipboard.SetText "Hello !"

End Sub

 

'In a module

'These routines are explained in our subclassing tutorial.

'http://www.allapi.net/vbtutor/subclass.php

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

Declare Function SetClipboardViewer Lib "user32" (ByVal hwnd As Long) As Long

 

Public Const WM_DRAWCLIPBOARD = &H308

Public Const GWL_WNDPROC = (-4)

 

Dim PrevProc As Long

 

Public Sub HookForm(F As Form)

    PrevProc = SetWindowLong(F.hwnd, GWL_WNDPROC, AddressOf WindowProc)

End Sub

 

Public Sub UnHookForm(F As Form)

    SetWindowLong F.hwnd, GWL_WNDPROC, PrevProc

End Sub

 

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

    WindowProc = CallWindowProc(PrevProc, hwnd, uMsg, wParam, lParam)

    If uMsg = WM_DRAWCLIPBOARD Then

        MsgBox "Clipboard changed ..."

    End If

End Function

 

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

 

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:

 

Declare Function RegisterWindowMessage 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”)

 

 

 

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!

 

 

 

 

 

 

 

 

 

 

 

 

 


Other 51 submission(s) by this author

 

 
Report Bad Submission
Use this form to notify us if this entry should be deleted (i.e contains no code, is a virus, etc.).
Reason:
 
Your Vote!

What do you think of this article(in the Intermediate category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor See Voting Log
 
Other User Comments
4/25/2002 3:20:41 PM:Almar Joling
Good work. This really clears up some stuff! The Windows messages are certainly interesting, but they (the contants) lack some documentation (for example sending the message to auto-size columns in a listview). Good work!
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 4:35:55 PM:Coding Genius
Thanks for leaving a comment Almar, your the only person out of the 145 so far that has.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 6:06:22 PM:?
ey men theres a program called winzip to put all the project in only one file. kind of boring copying and pasting
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 6:20:59 PM:John L Whittington
I appreciate this. This is the kind of these that kick me in the butt. 5 globes
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 6:22:17 PM:John L Whittington
*Things
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 9:21:17 PM:Dunlop Chulullapops
Hi mans : ) Im am really like your tutorial and ihave got to say how informatique it is (like strong) : ))) Please keep up the good works and please dont not worries about the others are not leaving comments because even though they are view the tutor it is help enough from you so thank you so so much : ))) and plz keep up the good works! from, dunny
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 9:24:11 PM:Dunlop Chulullapops
To Kwang: WHY YOU ONLY GIVE TO HIM 4 GLOBES???? HE DESERVES 5 MANS!!! PLEASE TO CHANGE IT ASAP!! THANK YOU FROM DUNNYS : ))
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/25/2002 11:02:19 PM:Freddy
Thank you, and Great Job! Does anyone have a simple solution to detect the IDE so we don't crash it by accident when subclassing? 5 from me!
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 1:37:55 AM:Trevor Herselman
Your tutorial did help, still a lot left to learn though and I realize you can't explain everything in one go ... keep up the good work and thanx for the effort! Everyone who reads this should apreciate it as well ... :)))
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 2:37:20 AM:John Galanopoulos
A really good tutorial. Very helpfull for those who seek knowledge for subclassing. 5 from me as well, although you made the common mistake on message queue processing many programmers do. Also Ms Word isn't the best html authoring solution for this site :)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 10:51:34 AM:sYNAPSE
Freddy: MS had issued a patch some time ago that makes the VB IDE aware that it is running subclassed code. There are also 3rd party controls that allows you to Subclass (or even Hook) windows safely.. There is a very *very* good tutorial (and a control) over at vbaccelerator.com: 'Subclassing Without The Crashes' - check it out Coding Genius: This is a good tutorial. 5 from me.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 11:52:19 AM:Coding Genius
Wow, I didn't expect so much feedback/votes. Oh and John...what mistake? Also, I have now updated the tutorial to include the RegisterWindowMessage API call.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 1:11:56 PM:Almar Joling
no problem Coding Genius =-). Are you going to write another "part" about this stuff (or related), since this tutorial is 'part 1', just wondering =-)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 1:41:13 PM:Coding Genius
That was the initial plan yes. I'm thinking GDI next. What do you think?
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 6:56:16 PM:Oscarreno
=)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/26/2002 9:11:15 PM:Tuan Hai
Really great artical. I am wating for part 2,... 5 GLOBES from me
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/27/2002 9:27:02 AM:Coding Genius
Had alot on my plate right now. I'm trying to network 2 computers, and having all sotrs of network card incompatibility issues and all sorts...So I dunno when I'll get round to doing part 2, but I'll definetly try and get it up as soon as I have some spare time.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/27/2002 1:00:08 PM:Tom Pydeski
Great! I have a question for you. I had written a clipboard buffer that used a timer to constantly check the clipboard for changes. Now with yours it becomes part of the winproc and i deleted the timer. Here's the question...Do you know for sure how each way utilized resources? Instincts tell me the new way (thanks to you) uses less, but I would be curious for quantifiable results.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/27/2002 1:58:04 PM:Coding Genius
The timer is one of the lowest priotities in the system, which means that it usually won't fire any quicker than every 70 milliseconds no matter how low you set it. Also, because it fires so much, it does take up resources. However, the windowproc is something that actually makes up your windows. Every window comes with one, so by coding your own, you aren't using up any more resources than normal, uless the code inside it does. Using the Window Proc, theres no need to ocnstantly check for clipboard changes. You'l be automatically notified y windows. Like your own personal message.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/27/2002 5:13:14 PM:Amritanshu
I must say ... it is a very well written tuitorial. Very elegently presented, simple and effective. 5 Globes from me.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/28/2002 7:11:32 PM:Squirrel
Spiffy. The only word fully qualified.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/29/2002 8:21:15 AM:cucuzz0
wish ther were more articles like this one.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
4/29/2002 11:37:19 AM:Coding Genius
Network's nearly fixed. (Fault card grrrr), so new article will be written soon. Any ideas then please leave feedback, greatly appreciated. I still think GDI is best idea so far though.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/3/2002 6:27:49 PM:7H3_1083
This is a great tutorial and i'm giving it 5 globes. but I have a question. if I register a custsom message, how can I send my message.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
5/4/2002 7:49:28 AM:Coding Genius
You must use the SendMessage (or Postmessage on older machines). See http://www.allapi.net/apilist/apifunctio n.php?apifunction=SendMessage for SendMessage, and see http://www.allapi.net/apilist/apifunctio n.php?apifunction=PostMessage for PostMessage.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/13/2002 8:41:08 PM:MatthewJ
This is some great code! But it's a bit confusing for me. Is there any way i could get an example of this. i have looked at the www.allapi.com site but it didn't have an example either. Thanks Coding Genius -MJ
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
12/19/2002 7:00:04 PM:
Need help, i dont get this??
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
1/8/2003 4:18:26 AM:
I need part two ;P 6 globes from me...errr 5 only?
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
3/6/2003 8:59:07 AM:MaxAndrews
Thanks , it it interesting to know how other people achive these things
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
3/21/2003 5:22:28 PM:Jim Walker
Was reading hom many 5 globes you had and just thought Id give you 5 as well :)
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
Add Your Feedback!
Note:Not only will your feedback be posted, but an email will be sent to the code's author in your name.

NOTICE: The author of this article has been kind enough to share it with you.  If you have a criticism, please state it politely or it will be deleted.

For feedback not related to this particular article, please click here.
 
Name:
Comment:

 

Categories | Articles and Tutorials | Advanced Search | Recommended Reading | Upload | Newest Code | Code of the Month | Code of the Day | All Time Hall of Fame | Coding Contest | Search for a job | Post a Job | Ask a Pro Discussion Forum | Live Chat | Feedback | Customize | Visual Basic Home | Site Home | Other Sites | About the Site | Feedback | Link to the Site | Awards | Advertising | Privacy

Copyright© 1997 by Exhedra Solutions, Inc. All Rights Reserved.  By using this site you agree to its Terms and Conditions.  Planet Source Code (tm) and the phrase "Dream It. Code It" (tm) are trademarks of Exhedra Solutions, Inc.