Introduction
Ever had the annoyance in MFC that you need the messages sent from each control in window proc? Some messages, such as WM_SETFOCUS
are sent and not posted. Therefore, some messages do not reach the PreTranslateMessage
stage. This can be really annoying when you need the messages for the controls. What's the solution, then? You need to derive each control for which you want its messages with a new class and override the WindowProc
. That's disturbing, isn't it? However... because of this, I took some time to devise a solution to this. All you need now is to derive each control whose messages you want from a single class. The class will automatically forward any messages it receives to a custom WindowProc
. This is very small and simple, and yet so powerful! Through function pointers and templates, I present you this code...
The code is available for download. You need only include the header file and derive your classes. Although they will need to be initialized, as well. BUT, you can do this in your constructor's initializer list ^_^.
As for how the code works... it's quite easy. Using templates, you must specify the parent class, the function pointer to be used, and the class whose function shall be called. Using this, it does a callback in its WindowProc
to the specified class and function. Easy!
I'll demonstrate how to use it...
#include "MsgForward.h"
typedef LRESULT (CMainDlg::*ProcPtr)(CWnd*, UINT, WPARAM, LPARAM);
class CMainDlg: public CDialog
{
public:
CMsgForward<CEdit,ProcPtr,CMainDlg> m_MyEdit;
protected:
LRESULT WindowProc(CWnd* pCtrl, UINT message, WPARAM wParam, LPARAM lParam);
}
CMainDlg::CMainDlg() :
m_MyEdit(WindowProc,this,PROCESS_AFTER)
{ }
It's that easy! Now, let me explain a little... Since it uses templates, we must specify the types. First type is the parent class. This class derives from the parent, so it retains all the functionality that the object is supposed to be! The second is a function pointer to the function you are going to use to forward the messages to. It must be a WindowProc
as described above. It's like a normal WindowProc
, but the first parameter is the control that sent the message. The third argument for the template is the class within the function lies.
Now for the constructor... all arguments are optional. But without the first two arguments, it will not and cannot forward any messages. The first argument is the address of the function to receive the messages. The second argument is the class within which the function lies (usually pointed to by the this
pointer). Also remember: it is usually not a good idea to pass the this
pointer to the initializer of the constructor. You will get a warning by the compiler most likely. But it's perfectly safe here! And as for the third parameter, also optional... it specifies how the messages will be processed.
There are three options:
PROCESS_BEFORE
- All messages are forwarded to the base class for processing before forwarded to your function.
PROCESS_AFTER
- Same here, but it's after sent to your function.
DONOT_PROCESS
- No messages are forwarded to the base class for processing - beware of this one! Not recommended.
Default is PROCESS_AFTER
. You might want to change this for some controls if you want the base class to process the messages before you intercept them. You can at any time change the eMsgProcessing
variable of the class to change this behaviour. You can also change class and function address by manipulating the public variables.
Oh and if you're asking me why I'm using public variables (yes I know it's bad programming), the fact is that I don't care =). I see no fault in it, and find it annoying to create Set
/Get
for all variables that need be manipulated. Feel free to change.
And this, my friends... is all about it. Now you can intercept all these messages. As always, happy coding, and feel free to leave a comment if there's some flaw or something else you wish to discuss.