Unlike the interface libraries such as MFC and wtl, winx considers message distribution as a basic service that can exist independently of the window. In winx, The winx: Window <t> class is not responsible for message distribution, but the winx: windowmessage <t> class. Winx: Window <t> only inherits from winx: windowmessage <t>. In the previous article, I intentionally bought a customs sub. If you read the article "winx message distribution mechanism" and read the winx header file to learn more about it, I feel very comfortable. This topic continues. The Basic specification of windowmessage <t> is as follows: Template <class T>
Class windowmessage
{
Void ondestroy (hwnd );
Void onpaint (hwnd );
Void onkeydown (hwnd, uint uvkchar, uint ukeydata );
...
Lresult internaldefault (
Hwnd, uint message, wparam, lparam );
Bool dispatchmessage (
Hwnd, uint message, wparam, lparam, lresult & lresult );
Lresult processmessage (
Hwnd, uint message, wparam, lparam );
};
According to the contract of windowmessage <t>, the customer must forward all messages sent to the window
ProcessmessageFunction. The key functions involved are as follows:
- ProcessmessageCall a function firstDispatchmessageFor message distribution, ifDispatchmessageIf the message is not processed, callInternaldefaultTo process the message.
- DispatchmessageThe function distributes messages based on the Message ID, that is, the uint message parameter. For example, the wm_paint message is sent to onpaint for processing, the wm_destroy message is sent to ondestroy for processing, and the wm_keydown message is sent to onkeydown for processing.
- InternaldefaultFunctions abstract different types of windows. For a normal window, it calls defwindowproc; for an mdiframe window, it needs to call defframeproc; for an mdichildframe window, it calls defmdichildproc; for a dialog box, it only needs to return false directly.
Obviously, the most important thing here is
Dispatchmessage. If optimization is not considered, it does not seem complicated. Here we implement a version based on the virtual function (virtual) mechanism:
Class windowmessage
{
Virtual void onpaint (hwnd) {default ();}
Virtual void onkeydown (hwnd, uint uvkchar, uint ukeydata) {default ();}
...
Lresult default ();
Bool dispatchmessage (
Hwnd, uint message, wparam, lparam, lresult & lresult)
{
Switch (Message)
{
Case wm_paint: onpaint (hwnd); break;
Case wm_keydown: onkeydown (hwnd, wparam, lparam); break;
...
Default: Return false;
}
Return true;
}
};
You must not care about this:
DefaultFunctions seem a little interesting (introduced later) and are implemented using a very large switch... case.
Dispatchmessage"Originality", but it is a little boring. Someone immediately suggested using a template-higher performance. Therefore, the template-based version is available:
Template <class T>
Class windowmessage
{
Void onpaint (hwnd) {default ();}
Void onkeydown (hwnd, uint uvkchar, uint ukeydata) {default ();}
...
Lresult default ();
Bool dispatchmessage (
Hwnd, uint message, wparam, lparam, lresult & lresult)
{
T * pthis = static_cast <t *> (this );
Switch (Message)
{
Case wm_paint: pthis-> onpaint (hwnd); break;
Case wm_keydown: pthis-> onkeydown (hwnd, wparam, lparam); break;
...
Default: Return false;
}
Return true;
}
};
In many cases, templates are the same as virtual ones. There is no essential difference between the two versions of windowmessage. In fact, it is just a mechanical code transformation. It is necessary to understand the equivalence of this transformation. It is undeniable that, with this change, the performance has improved a lot. In the previous article "ATL interface class -- talking about polymorphism and generics", we will detail this. This template-based windowmessage class is equally boring. Although there is no overhead for calling virtual functions, the dispatchmessage function is still a giant and far from the exquisite wtl function. So, what else can we do? Next article: winx message distribution mechanism (Continued 2) To be continued...