Windows API window message shunt

Source: Internet
Author: User

For those familiar with Windows API programming, the header file windowsx. H should not be too unfamiliar. The content to be discussed this time comes from the header file windowsx. h.

It is often found on msdn that such a function is clearly a function and looks the same as an ordinary API function, but it is called macro. Why? Pay attention to the requirement used by the function. You will find that its declaration is in the header file windowsx. h.

Windowsx. h contains the following content:
Macro API, window message shunt, control API;

All these macro definitions can make your program safer, more concise, and clearer, greatly improving the readability of the program. The window message shunt (Message cracker) this is the topic we will discuss today. It can make our API programs more concise. Next let's go to our topic: (for more information about windowsx. H, refer to the MS Knowledge Base Article #83456 .)

Message shunt is a set of macros provided by windows. It has two major functions. In ms, it is:

● Secure data types, because the message shunt completes a lot of type conversion work;
● Making the conversion from a program to a 32-bit windows easier;

Of course, the use of message shunt will greatly change the appearance of the program, you can also choose not to use it.

Next we will take the message processing process in a dialog box window as an example to see how the message shunt works.

1. Basic use of message shunt
First, let's look at a common window message processing function. It may need to process messages such as window initialization and invalid customer re-painting:

Lresult callback wndproc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Case wm_create:
//...
Return 0;

Case wm_paint:
//...
Return 0;

Case wm_destroy:
//...
Return 0;
}
Return defwindowproc (hwnd, MSG, wparam, lparam );
}

By using the message shunt, we can write each case to the corresponding message processing function, as shown below:

Lresult callback wndproc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Case wm_create:
Return handle_wm_create (hwnd, wparam, lparam, cls_oncreate );

Case wm_paint:
Return handle_wm_paint (hwnd, wparam, lparam, cls_onpaint );

Case wm_destroy:
Return handle_wm_destroy (hwnd, wparam, lparam, cls_ondestroy );
}
Return defwindowproc (hwnd, MSG, wparam, lparam );
}

Three macro definitions are used here: handle_wm_create, handle_wm_paint, and handle_wm_destroy. These three macro definitions are our three message shunt (don't look at what the shunt is, it's not worth a few dollars if it is used ), they are in Windows X. H is defined as follows:

# Define handle_wm_create (hwnd, wparam, lparam, FN)
(FN) (hwnd), (lpcreatestruct) (lparam ))? 0l: (lresult)-1l)
# Define handle_wm_paint (hwnd, wparam, lparam, FN)
(FN) (hwnd), 0l)
# Define handle_wm_destroyclipboard (hwnd, wparam, lparam, FN)
(FN) (hwnd), 0l)

Replace these three macro definitions with the following:

Lresult callback wndproc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Case wm_create:
Return cls_oncreate (hwnd, (lpcreatestruct) (lparam )? 0l: (lresult)-1l;
// If the message is processed, cls_oncreate should return true, causing wndproc to return 0; otherwise, cls_oncreate will return false, causing wndproc to return-1;
Case wm_paint:
Return cls_onpaint (hwnd), 0l;
// Comma expression; cls_onpaint is of the void type, and 0 is returned here;
Case wm_destroy:
Return cls_ondestroy (hwnd), 0l; // same as cls_onpaint
}
Return defwindowproc (hwnd, MSG, wparam, lparam );
}

Then we can write the corresponding message processing function according to the definition of the message shunt:

Bool cls_oncreate (hwnd, lpcreatestruct ){...};
Void cls_onpaint (hwnd ){...};
Void cls_ondestroyclipboard (hwnd ){...};

Windowsx. H also provides a simpler method: Use the handle_msg macro, which is defined as follows:

# Define handle_msg (hwnd, message, FN)
Case (Message): Return handle _ # message (hwnd), (wparam), (lparam), (FN ))

The macro is to convert itself into a macro in the form of handle_xxxxmessage according to different message (# used to connect the front and back strings, then execute the Message Processing code through the corresponding macro;
For example, write in the actual code:

Handle_msg (hwnd, wm_create, cls_oncreate)

After conversion, it becomes:

Case (wm_create): Return handle_wm_create (hwnd), (wparam), (lparam), (cls_oncreate ))

In this way, we can directly write the program:
Lresult callback wndproc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Handle_msg (hwnd, wm_create, cls_oncreate );
Handle_msg (hwnd, wm_paint, cls_onpaint );
Handle_msg (hwnd, wm_destroy, cls_ondestroy );
}
Return defwindowproc (hwnd, MSG, wparam, lparam );
}

Then you can directly write the corresponding message processing process. Is it much simpler? In addition, you can use vs to directly jump to the function by encapsulating message processing in the function, and you no longer need to find the case. Note that although windows X. h contains the shunt corresponding to all messages, but their parameters are explicitly stated by macro definition. When writing a message processing function, the parameter type in the macro definition must be followed; otherwise, errors may occur; every time we write a new message processing function for so many message splitters, we have to check whether the parameter settings are correct. This process is tedious and lengthy. Fortunately, there is already a tool called message cracker wizard that can help us generate message shunt and related processing processes. For details, see http://www.codeproject.com/win32/ms?ackwizard.asp.

2. Use message shunt in the dialog box
In dialog box message processing, window subclass is a commonly used method, which can also be implemented through message shunt, but it is a little problem:>
The following is a dialog box using windowsx. h message shunt and its processing process:
......
Int winapi _ twinmain (hinstance hinstexe, hinstance, ptstr psz1_line, INT)
{
Dialogboxparam (
Hinstexe, makeintresource (idd_passthru), null, (dlgproc) dlg_proc, 0 );

Return (0 );
}
......

Lresult callback dlg_proc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Handle_msg (hwnd, wm_initdialog, cls_oninitdialog); // The handle_msg macro cannot be used directly.
Handle_msg (hwnd, wm_command, cls_oncommand); // The handle_msg macro cannot be used directly.
}

Return false;
}

The direct use of handle_msg in the above program may cause errors. Why? The problem lies in the return value of the sub‑type message processing process. the return value of the Message Processing Process in the dialog box is described as follows in msdn:

In general, the dialog box process function should return true when the message is processed. if the message is not processed, false is returned. If the dialog box returns false, the dialog box manager Prepares the default dialog operation for this message.

If the dialog box processes a message that requires a specific return value, the return value of the dialog box should be set to call setwindowlong (SetwindowlongFunction changes an attribute of the specified window. the function also sets a 32-bit (long) value at the specified offset into the extra window memory of a window .) and returns this value immediately before returning true. Note that you must call setwindowlong immediately (this function is used to call the window subclass process). This will cause the dwl_msgresult value to be rewritten by a nested dialog box message. Messages with special values returned include:
• Wm_chartoitem
• Wm_compareitem
• Wm_ctlcolorbtn
• Wm_ctlcolordlg
• Wm_ctlcoloredit
• Wm_ctlcolorlistbox
• Wm_ctlcolorscrollbar
• Wm_ctlcolorstatic
• Wm_initdialog
• Wm_querydragicon
• Wm_vkeytoitem
No? Our message wm_initdialog is also in it. The process of processing this message cannot simply return true, indicating that the message is processed, but it has another intention; it will be converted:

Case (wm_initdialog): Return handle_wm_initdialog (hwnd, wparam, lparam, cls_oninitdialog );

Macro handle_wm_initdialog is defined as follows:

# Define handle_wm_initdialog (hwnd, wparam, lparam, FN)
(Lresult) (DWORD) (uint) (bool) (FN) (hwnd), (hwnd) (wparam), lparam)

For wm_initdialog processing, if true is returned, it indicates to set the keyboard focus to the default control of the dialog box; otherwise, false is returned. At this time, it seems that no problem is found, for another message wm_command, handle_msg simply converts it:

Case (wm_command): Return handle_wm_command (hwnd, wparam, lparam, cls_oncommand );

The macro handle_wm_command is defined as follows:

# Define handle_wm_command (hwnd, wparam, lparam, FN)
(FN) (hwnd), (INT) (loword (wparam), (hwnd) (lparam), (uint) hiword (wparam), 0l)

The question comes out. Because cls_oncommand is a void function, there is no return value. Therefore, in windows, a 0 value must be returned for this message processing process by default, if the return value is 0, does it mean that our message process does not process this message? This conflict cannot be solved by handle_msg. What can we do to make the message process correctly return a true value after processing the wm_command message? The answer is to use another macro in windowsx. h: setdlgmsgresult (hwnd, MSG, result)

This macro is defined as follows:

# Define setdlgmsgresult (hwnd, MSG, result )((
(MSG) = wm_ctlcolormsgbox |
(MSG) = wm_ctlcoloredit |
(MSG) = wm_ctlcolorlistbox |
(MSG) = wm_ctlcolorbtn |
(MSG) = wm_ctlcolordlg |
(MSG) = wm_ctlcolorscrollbar |
(MSG) = wm_ctlcolorstatic |
(MSG) = wm_compareitem |
(MSG) = wm_vkeytoitem |
(MSG) = wm_chartoitem |
(MSG) = wm_querydragicon |
(MSG) = wm_initdialog
)? (Bool) (result): (setwindowlongptr (hwnd), dwlp_msgresult, (lparam) (lresult) (result), true ))

(Have you noticed that there is a wm_ctlcolormsgbox in it? This message is a 16-bit winapi message that was converted to a Win32 API. It is now deleted from the latest 32-bit API. Keeping this message may take compatibility into account, I will not discuss it further here)
As you can see, if the message processed during the dialog box happens to return one of the specific values, the result is returned truthfully. Do not be blinded by the previous bool, the bool definition in the header file is actually an int type. Once you need to return other values other than true or false, you can do the same. In this way, our cls_oninitdialog can return its bool value correctly, and after cls_oncommand is processed, a true value can also be returned by the comma expression following it to indicate that the message has been processed.

In the book windows core programming, Daniel Jeffrey defined a macro to make it easier to use the setdlgmsgresult macro:

# Define chhandle_dlgmsg (hwnd, message, FN)
Case (Message): Return (setdlgmsgresult (hwnd, umsg,
Handle _ # message (hwnd), (wparam), (lparam), (FN ))))

It can be seen that this macro is simply encapsulated with the setdlgmsgrseult macro.

In this way, the final code can be written:

Lresult callback dlg_proc (hwnd, uint MSG,
Wparam, lparam)
{
Switch (MSG)
{
Chhandle_dlgmsg (hwnd, wm_initdialog, cls_oninitdialog); // use the chhandle_dlgmsg macro of Daniel
Chhandle_dlgmsg (hwnd, wm_command, cls_oncommand );
}

Return false;
}

The entire framework of the original program is listed below:

Lresult callback dlg_proc (hwnd, unit umsg, wparam, lparam)
{
Switch (MSG)
{
Case wm_command: // each case is replaced by a message cracker.
// Do something; // chhandle_dlgmsg macro; this macro filters, processes, and returns corresponding values for messages.
Return true;

Case wm_initdialog:
// Do something;
Return xxxx;
}

Return false; // if the message is not processed during the dlgproc process, the message that calls this dlgproc is notified,
} // Notify the system's dialog box manager. We will not process this message and you will be given it.

The effect of message shunt is self-evident.

The above only introduces some of the Application of message shunt. More creative usage will be explored by yourself in practice.

Some useful references are listed below:

Http://support.microsoft.com/default.aspx? SCID = KB; en-US; 83456 introduces the strict macro definition and windowsx. h
The http://www.codeproject.com/win32/msgcrackwizard.asp provides download of message cracker wizard with source code
Windows core programming:> he used message cracker in his own sample.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.