How to make the view respond to menu events?
In wtl, the message loop of cmainframe is as follows:
Program code
Begin_msg_map (cmainframe)
Message_handler (wm_create, oncreate)
Chain_msg_map (cupdateui <cmainframe>)
Chain_msg_map (cframeworkwimpl <cmainframe>)
End_msg_map ()
The message loop in the view is as follows:
Program code
Begin_msg_map (cgameview)
Message_handler (wm_paint, onpaint)
Message_handler (wm_create, oncreate)
Command_id_handler (id_game_start_new, ongamestartnew)
End_msg_map ()
Although I clearly wrote an ongamestartnew to respond to the menu item id_game_start_new, it can be confirmed through the experiment that cmainframe did not forward the message, but instead intercepted the useless message and threw it away. So, how to let cmainframe hand over the message to the view is the problem that I want to solve.
First of all, I want to write an article on the pretranslatemessage function. Because the pretranslatemessage of cmainframe indeed calls the pretranslatemessage function of view, it is quite easy to intercept this message, however, because I want to write an explicit message loop, the code is ugly and uncomfortable. I only use it as the final solution.
Next, I thought of registering the message Filter Method to the message loop, that is, adding the following code in oncreate of view:
Program code
// Register object for message filtering and idle updates
Cmessageloop * ploop = _ module. getmessageloop ();
Atlassert (ploop! = NULL );
Ploop-> addmessagefilter (this );
In addition, view must be derived from cmessagefilter as follows:
Program code
Class cgameview
: Public cscroll1_wimpl <cgameview>
, Public cmessagefilter
{
//...
};
However, it is a pity that only framewindow can enjoy the flexibility brought about by message filter, and view cannot.
Next, I tried to use chain_msg_map_member () and inserted the view message loop in the message loop of cmainframe:
Program code
Begin_msg_map (cmainframe)
Message_handler (wm_create, oncreate)
Chain_msg_map (cupdateui <cmainframe>)
Chain_msg_map (cframeworkwimpl <cmainframe>)
Chain_msg_map_member (m_view)
End_msg_map ()
However, I am very frustrated that it is very concise and clear to capture menu messages, but view intercepts a lot of messages that should not have been received, the display of the entire cmainframe is messy! This is not acceptable!
Finally, I found chain_msg_map_alt_member () and alt_msg_map () and used them together to make things simple and easy to use!
First, you need to change the message loop in the view and write it as follows:
Program code
Begin_msg_map (cgameview)
Message_handler (wm_paint, onpaint)
Message_handler (wm_create, oncreate)
Alt_msg_map (1) // handle Y message.
Command_id_handler (id_game_start_new, ongamestartnew)
End_msg_map ()
Then add chain_msg_map_alt_member () to the message loop of cmainframe ():
Program code
Begin_msg_map (cmainframe)
Message_handler (wm_create, oncreate)
Chain_msg_map (cupdateui <cmainframe>)
Chain_msg_map (cframeworkwimpl <cmainframe>)
Chain_msg_map_alt_member (m_view, 1)
End_msg_map ()
Okay, that's all.
Finally, let's talk about the principle.:
In ATL/wtl, in order to be able to concatenate several message loops, this msgmapid is specially implemented. The message loops are all switched first (msgmapid ), then, find the corresponding message response function in different map IDs. By default, Windows messages always use the message response function with a map ID of 0. You can manually change it to the specified map ID if necessary. Note that message response functions of different map IDs are mutually exclusive, and only one map can be used at a time (of course, you have to manually add multiple map IDs to the same message loop ......).
For specific implementation code, you can refer to the wtl source code. If you have a certain degree of Windows Programming basics, you should be very familiar with it.
Additional benefits of using map ID:
Through this mechanism, we can easily distribute messages to different controls in cmainframe, which is much more flexible than the message mechanism in MFC.