Right, try again!
Basically dare, at the api level, when you create a window / control you specify the address of a 'callback' function which is used to service the window control and perform such tasks as painting the client area, displaying the caret, responding to resizes etc. This procedure receives all kinds of notifications such as mouse clicks etc. and is called whenever your program executes 'message retrieval code' (GetMessage_(), TranslateMessage_() etc.)
Now the thing is that your window proc cannot possible deal with the umpteen thousands of messages which may be sent to the procedure (e.g. #WM_PAINT), some of which will cripple your program if not processed, and thus to combat this, Windows offers a 'default window procedure' to which you can pass all messages which you decide not to process. This default procedure performs the 'minimum' processing to ensure that the window/control will function in a 'bare bones' kind of way and not crash your program. To pass a message to the 'default procedure' you use the DefWindowProc_() function.
So, having created a new window/control there are two window procedures 'chained together' to handle all messages directed at the window / control :
YourWindowProc
===========
DefWindowProc
===========
Now, this is where things get interesting!
All custom controls (e.g. common controls, Purebasic's scrollarea gadget etc.) already have these two procedures in place. For example, consider a scroll area gadget :
ScrollAreaProc (written by freak)
===========
DefWindowProc (the windows default)
===========
Between them, these two procedures give a scroll area the functionality which we all know and love! For example, freak's procedure probably handles #WM_ERASEBKGND to customise the erasing of the background, but probably passes #WM_PAINT directly to the default win proc instead of handling it directly. Failure to either handle #WM_PAINT directly or pass it along to the default procedure (using DefWindowProc_()) will crash your application because the client area will never get validated!
Now, suppose we wish to look out for mouse clicks on the scroll area gadget. That is, suppose we wish to handle #WM_LBUTTONDOWN messages ourselves. To do this, we need to insert our own code in freak's scroll area window procedure - which of course is not possible because we do not have the source code etc.
Instead, we 'subclass' the scroll area and add a 3rd window procedure to the two procedures already chained together :
YourSublassingProc (written by dare, subject to random crashes
)
===========
ScrollAreaProc (written by freak)
===========
DefWindowProc (the windows default)
===========
To add this extra procedure we use the SetWindowLong_() function.
Now, when messages are generated and are intended for our scroll area gadget, windows will send them to the top procedure in the chain, in this case it will send ALL messages to your custom procedure at the top of the chain shown above. Here we can look out for #WM_LBUTTONDOWN etc.
The question, however, is what do we do with the umpteen thousands of messages which we are not interested in? Do we ignore them, or send them to the default procedure which is at the bottom of the chain?
Ignoring them is out of the question as (already explained) unprocessed messages can crash our application. Passing them to the default procedure will bypass freak's procedure and our scroll area will then lose all the functionality which freak has added etc.
We thus choose to pass all messages we are not interested in to freak's procedure which can then either process them directly or pass them back to the default procedure etc. In fact, we will often pass even those messages we are interested in to freak's procedure once we are done with them anyhow, just to give that procedure a chance to react to the said messages etc.
The important thing is that, between the 3 window procs we now have chained together, ALL messages are accounted for and receive their due attention etc.
To pass a message from one window procedure to another we use the CallWindowProc_() function.
And this is subclassing!
Now, to your question:
Code: Select all
result = CallWindowProc_(gOldPRoc, hwnd, uMsg, wParam, lParam)
Now some messages are sent by windows and windows in turn is awaiting a result. For example, in the #WM_ERASEBKGND message we return a non-zero value to tell windows to halt processing of this message because we have erased the control's background ourselves. Hence, when we use CallWindowProc_() to pass a message down the chain of window procs we need to make a note of any return value and eventually pass it back to windows, just in case the message is one of those which Windows requires a return value etc. There is little point passing a message down the chain only to then ignore the return value etc.
I don't know if this rant will help dare and I have to add that it does contain a couple of 'half truths'. All for simplicty's sake you understand!

I may look like a mule, but I'm not a complete ass.