Source: Internet Author: ggg82/CSDN
Nowadays, many user interfaces use the toolbar to create menu bar. Recently, younger brother is interested in this and asks for help from the Internet. However, most of the help is the source code of BCGControlBar or the source code of SizableRebar, this may be a good choice for friends who only want to have this function on their own interface. Just look at the demo and then directly call others' class libraries, however, for readers who are interested in this topic and want to understand the ins and outs of the topic, it is not easy to look at the source code without a detailed explanation, at least for cainiao like me, for this reason, I hope to provide some help to readers who are still seeking help.
Let's take a look at it:
When we receive a toolbarbutton to press a message, we usually use TrackPopupMenuEx to bring up the menu. The key to the problem is that when the menu is not closed, TrackPopupMenuEx does not return and intercepts mouse and keyboard messages, with spy, you can see that no messages are received in the toolbar at this time, and the hotspot cannot be changed, this requires us to test the mouse position and close the previous menu and display the next menu when the mouse moves to the next hotspot. Here we use the hook function SetWindowsHookEx to install the WH_MSGFILTER hook before calling TrackPupupMenuEx. The Code is as follows:
M_hMsgHook = SetWindowsHookEx (WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId ());
MssageProc is a hook function with the following code:
Lresult callback MessageProc (int code, WPARAM wParam, LPARAM lParam)
{
If (code = MSGF_MENU)
{
HookMessageProc (lParam );
}
Return CallNextHookEx (m_hMsgHook, code, wParam, lParam );
}
The function checks the message. If it is from the menu, the message is passed to the HookMessageProc function for processing. All we need to do is to detect the message WM_MOUSEMOVE in the function and test the mouse position, if the mouse has been moved to another button, close the menu and display the next menu. Close the menu and use the message WM_CANCELMODE. When the menu is closed, release the hook, re-install the hook when the next menu is displayed. The sample code of the pop-up menu is as follows:
Void TrackPopup (HWND hWndToolBar, int iButton)
{
While (iButton> = 0)
{
SendMessage (hWndToolBar, TB_SETHOTITEM, iButton, 0 );
IPopup = iButton;
// Install the hook
G_hMsgHook = SetWindowsHookEx (WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId ());
// Pop-up menu
TrackPopupMenuEx (...);
// Uninstall the hook
UnhookWindowsHookEx (g_hMsgHook );
IButton = iNextPop; // The next pop-up item. If it is negative, exit.
}
SendMessage (hWndToolBar, TB_SETHOTITEM,-1, 0 );
}
(Experience and Suggestion: If the button uses the style TBSTYLE_DROPDOWN, do not directly call this function in the message TBN_DROPDOWN. Use an intermediate message and then use PostMessa to send the message, so that TBN_DROPDOWN can be returned directly, otherwise it is very troublesome to eliminate the first highlighted hotspot .)
IPopup is the current pop-up item, and iNextPop is the next pop-up item. These variables need to be processed in the HookMessageProc function. The sample code is as follows:
Void HookMessageProc (MSG * pMsg)
{
If (pMsg-> message = WM_MOUSEMOVE)
{
Int iButton, iCount;
POINT pt = {LOWORD (pMsg-> lParam), HIWORD (pMsg-> lParam )};
ScreenToClient (hWndToolbar, & pt );
IButton = SendMessage (hWndToolbar, TB_HITTEST, 0, & pt );
ICount = SendMessage (hWndToolbar, TB_BUTTONCOUNT, 0, 0 );
If (iPopup! = IButton & iButton = 0)
{
INextPop = iButton;
SendMessage (hWndMain, WM_CANCELMODE, 0, 0 );
}
Else
{
INextPop =-1;
}
}
}
(Experience and Suggestion: do not try to call TrackPopup here. I tried to cancel the while loop in the function and call the function directly here. The result is that before TrackPopupMenuEx returns, this function has been called)
Here, only the mouse moves the message, the real menu should also process the keyboard navigation message, detailed code can refer
BCGControlBar (http://www.vckbase.com/code/downcode.asp? Id = 1382)
Or SizableRebar (http://www.codeproject.com/docking/sizablerebar/SizableRebar_demo.zip
)
With this underlying framework, these processing processes should no longer be difficult. For some API functions involved in this article, refer to msdn.
Related information on Msdn:
Http://msdn.microsoft.com/library/default.asp? Url =/library/en-us/shellcc/platform/commctls/faq/iemenubar. asp
Http://www.microsoft.com/msj/0199/c/c0199.aspx