|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Index
IntroductionThe WINDOWSX.H header facilities for Win32 SDK programmersMany beginner and intermediate programmers are often faced with the problem of spaghetti The problem of the thousand lines window procedure can be solved with a header file that is shipped since the days of the C/C++ 7.0 compiler and the Windows Software Development Kit for Windows 3.1. That header is <windowsx.h> and contains a lot of useful macros. According to Microsoft, the facilities of this header file can be resumed in the following groups:
Since Message Cracker Wizard is designed to aid with the message crackers, I will skip the other useful macros the header file makes available. If you are interested in a brief description of what you can do with the WINDOWSX.H file, you can look at the MS Knowledge Base Article #83456. Well, let's introduce the advantages of the message crackers and, of course, why the tool offered here can be useful to work with them in your code. When you are programming with the Win32 SDK, you process window and dialog messages with a window procedure, commonly named Suppose that we want to process LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
// ...
break;
case WM_KEYUP:
// ...
break;
case WM_CLOSE:
// ...
break;
case WM_DESTROY:
//...
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
This is the most used manner since Windows 1.0 days to process window messages, and surely, it works. But the problem is when you begin to add more and more complex features to your program, such as MDI, OLE, common controls, etc., and you get a thousand-lines window procedure. You begin to jump with PageDn and PageUp keys looking for a message you want to modify. This is the first advantage of using message crackers: they convert that case label spaghetti in easy to maintain handling functions, like MFC. And the second advantage is the proper parameter format you use in your handling functions. Instead of doing those The message handling macro #define HANDLE_MSG(hwnd, message, fn) \ case (message) : return HANDLE_##message((hwnd), (wParam), (lParam), (fn)) As you may expect from the macro definition above, to convert your code to the "message-cracked" version, you must supply the cracking macro, LRESULT CALLBACK MainWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
HANDLE_MSG (hwnd, WM_COMMAND, OnCommand);
HANDLE_MSG (hwnd, WM_KEYUP, OnKeyup);
HANDLE_MSG (hwnd, WM_CLOSE, OnClose);
HANDLE_MSG (hwnd, WM_DESTROY, OnDestroy);
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
Wow! This is a better, compact and easily manageable window procedure. Now you would want to define your message processing functions ( The problem is that you must search in the definitions of WINDOWSX.H header and look for the parameters of the matching message processing function every time you add a message handler, because you can't use any parameters you want: the format of the handling function is explicit. Doing this repeated searching in the header file can become a tedious task and can lead to errors. The Message Cracker Wizard Tool comes to the rescue: it allows you to paste the correct function parameters for every message handler you want. And if you're writing from scratch, it can also write a template window or dialog procedure to begin with the window messages you will process. Message Forwarding Macros: Another XWINDOWS.H featureAnother useful feature in windowsx.h header is the possibility of message forwarding. This is used for "unpacking" the message processing function parameters into suitable Suppose that we want to use SendMessage (hwndParent, WM_COMMAND,
MAKEWPARAM(IDC_USERCTL, BN_DBLCLK),
(LPARAM)GetDlgItem(hwnd, ID_USERCTL));
This is a rather complex syntax: the The above code can be converted to WINDOWSX.H message forwarding macros, void myWnd_OnCommand (HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) Well, those cracked parameters are the same to be used by the forwarding macro -- so, as you may expect, the confusing FORWARD_WM_COMMAND (hwndParent, IDC_USERCTL, GetDlgItem(hwnd, ID_USERCTL), BN_DBLCLK, SendMessage); That's easy and works with all Message Cracker Wizard supported messages. Using the Message Cracker Wizard ToolWhen you fire up the Message Cracker Wizard, its interface appears like the following:
The Wizard offers you all the messages handled by WINDOWSX.H in the top-left list box where you can click one or multiple messages. The Window ID edit box allows you to specify an identifier for the window you are specifying the message. Common IDs are To quickly tour the features of the Message Cracker Wizard Tool, let's do it by example. Remember that you must include the <windowsx.h> header with your project using the Quick tour on the Message Cracker Wizard FeaturesLet's begin. Suppose you've already written your Open the Message Cracker Wizard. We need to select messages for our window, because MCW needs it to create our main window procedure from scratch. As you may know, it is very common for Windows programs to handle the Select
But wait... we said that we want a ready window procedure. So click on 'Make Window Procedure' check box, and be sure that Window radio button is selected. Now we are ready. Keep in mind that Dialog works just like this, but modifies the procedure to be a dialog-type procedure. First, we need the window procedure on our source code. Press on the 'Copy Macro' button (or press Ctrl-M), minimize the Wizard (or keep it at hand, since it remains top-most), go to your IDE and paste from the clipboard (Ctrl-V) in the place you want your window procedure. Voilá! You will get code like this: // // main Window Procedure // LRESULT CALLBACK main_WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { HANDLE_MSG (hwnd, WM_CLOSE, main_OnClose); HANDLE_MSG (hwnd, WM_CREATE, main_OnCreate); HANDLE_MSG (hwnd, WM_DESTROY, main_OnDestroy); //// TODO: Add window message crackers here... default: return DefWindowProc (hwnd, msg, wParam, lParam); } } That's the window procedure with the three message cracking macros ready to work! And also, with a TODO comment to remember that you must add new message cracker macros there. Remember to unselect 'Make Window Procedure' checkbox when you want to add a But the code above does nothing, because we need the functions that process those three messages we want. Simply return to the Message Cracker Wizard tool and now click on 'Copy Function' button. Switch to your source code, locate your cursor where you want the functions bodies to be inserted, and paste with Ctrl+V or Edit/Paste menu. The wizard automatically creates the functions with the main Window ID and the correct parameters expected by the WINDOWSX.H header macros: // // Process WM_CLOSE message for window/dialog: main // void main_OnClose(HWND hwnd) { // TODO: Add your message processing code here... } // // Process WM_CREATE message for window/dialog: main // BOOL main_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) { // TODO: Add your message processing code here... } // // Process WM_DESTROY message for window/dialog: main // void main_OnDestroy(HWND hwnd) { // TODO: Add your message processing code here... } The Wizard also automatically creates a heading comment and a TODO line to remind you to add code. Now you can add your message handling and processing logic easily and write complex window procedures. You can remove the comments if you want using the two checkboxes in the main window. More Message Cracker Wizard FeaturesThere are a few more features present in the program, which are rather intuitive. Message FilteringThis was a suggestion by some users of the program and it was implemented. Click on "Filters.." button (or press Ctrl+L) and you get the following dialog box. There you can select which messages appear listed on the listbox, classified on the type (this classification criteria was taken from Microsoft Spy++ utility).
Note that a present issue in v2.0 when using message filtering dialog is that the list box is filled up again when you click OK, so the previous selection is lost (this does not mean that your previous selected messages that appear on the target code window will disappear). Compact Window ModeYou may want to reduce the window size of the Message Cracker Wizard. This is possible by disabling "Show Target Code" option in the View menu (or by pressing Ctrl+F11). The main window will appear without the target code area:
Window Transparency, Exclude Comments and Stay On TopAnother feature that can be useful for low resolution displays or cluttered desktops is the window transparency feature. Click on the View menu, Window Transparency menu and select a transparency percentage (Solid is 100% opaque and 75% is 25% opaque). This feature is only available for Windows 2000/XP and Server 2003 users. On 9X OSes, only "Solid" option is available. The Exclude Comments feature allows the code generator to exclude comments, either heading or "TODO" style commenting. Just select or unselect the checkboxes on the main window. Finally, the Stay On Top feature is pretty self-descriptive. Planned FeaturesThe following features may appear in the following releases:
Have fun and good programming!I hope this little tool to be of interest to any Windows SDK programmer and of course, to be a potential method to write cleaner Win32 API programs. I'm open to suggestions to improve the tool. If you find this program useful, mail me, because I will be very happy to listen to any good comment. Thanks for all support!! You know who you are! As always, check my home page where I mention the updates to this program. History
| ||||||||||||||||||||