文章来源:互联网 作者:ggg82/CSDN
现在许多用户界面都使用工具栏制作菜单条,小弟最近对此感兴趣,便从网上求助,可是得到的帮助大多是BCGControlBar的源代码或者是SizableRebar的源代码,对于只希望是自己的界面具有该功能的朋友来说,这也许是不错的选择,只要看一下demo,然后直接调用别人的类库就可以了,但对于我等对此话题感兴趣,希望弄懂其来龙去脉的读者来说,直接看这些没有详细解释的源代码,要从中弄出个所以然来,实不是件容易的是,至少对于像我这样的菜鸟来说是这样的,本文出于此种原因,希望对还在寻求此帮助的读者能提供一些帮助。
下面我们边看边侃:
在接收到toolbarbutton按下消息时,我们一般使用TrackPopupMenuEx弹出菜单,问题的关键是,在菜单未关闭时,TrackPopupMenuEx并不返回,并拦截鼠标和键盘消息,使用spy可以看到,此时的工具栏收不到任何消息,当然无从改变热点,这就需要我们自己探测鼠标位置并在鼠标移动到下一个热点时关闭上一个菜单并显示下一个菜单。这里我们使用钩子函数SetWindowsHookEx在调用TrackPupupMenuEx前安装WH_MSGFILTER钩子,代码如下:
m_hMsgHook = SetWindowsHookEx( WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId() );
MssageProc是钩子函数,代码如下:
void TrackPopup(HWND hWndToolBar, int iButton)
{
while (iButton >= 0)
{
SendMessage(hWndToolBar,TB_SETHOTITEM,iButton,0);
iPopup = iButton;
//安装钩子
g_hMsgHook = SetWindowsHookEx(WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId());
//弹出菜单
TrackPopupMenuEx(…);
//卸载钩子
UnhookWindowsHookEx(g_hMsgHook);
iButton = iNextPop; //下一个弹出项,若为负,则退出
}
SendMessage(hWndToolBar,TB_SETHOTITEM,-1,0);
}
(经验与建议:如果button使用样式TBSTYLE_DROPDOWN,请不要在消息TBN_DROPDOWN中直接调用该函数,应使用中间消息,然后使用PostMessa个发送该消息,以使TBN_DROPDOWN可以直接返回,否则消除第一个高亮热点是很麻烦的事。)
iPopup为当前弹出项,iNextPop为下一个弹出项,这些变量需要在函数HookMessageProc中处理,示例代码如下: