分享
 
 
 

Toolbar制作菜单条过程详解

王朝other·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

现在许多用户界面都使用工具栏制作菜单条,小弟最近对此感兴趣,便从网上求助,可是得到的帮助大多是BCGControlBar的源代码或者是 SizableRebar的源代码,对于只希望是自己的界面具有该功能的朋友来说,这也许是不错的选择,只要看一下demo,然后直接调用别人的类库就可以了,但对于我等对此话题感兴趣,希望弄懂其来龙去脉的读者来说,直接看这些没有详细解释的源代码,要从中弄出个所以然来,实不是件容易的是,至少对于像我这样的菜鸟来说是这样的,本文出于此种原因,希望对还在寻求此帮助的读者能提供一些帮助。

下面我们边看边侃:

在接收到toolbarbutton按下消息时,我们一般使用TrackPopupMenuEx弹出菜单,问题的关键是,在菜单未关闭时, TrackPopupMenuEx并不返回,并拦截鼠标和键盘消息,使用spy可以看到,此时的工具栏收不到任何消息,当然无从改变热点,这就需要我们自己探测鼠标位置并在鼠标移动到下一个热点时关闭上一个菜单并显示下一个菜单。这里我们使用钩子函数SetWindowsHookEx在调用 TrackPupupMenuEx前安装WH_MSGFILTER钩子,代码如下:

m_hMsgHook = SetWindowsHookEx( WH_MSGFILTER, MessageProc, 0, GetCurrentThreadId() );

MssageProc是钩子函数,代码如下:

LRESULT CALLBACK

MessageProc(int code, WPARAM wParam, LPARAM lParam)

{

if (code == MSGF_MENU)

{

HookMessageProc(lParam);

}

return CallNextHookEx(m_hMsgHook, code, wParam, lParam);

}

函数检查消息,如果是来自菜单,则将消息传递给函数HookMessageProc处理,我们所要做的就是在该函数中检测消息 WM_MOUSEMOVE,并测试鼠标位置,如果鼠标已经移动到另一个按钮上,则关闭菜单并显示下一个菜单,关闭菜单使用消息 WM_CANCELMODE,当菜单关闭后,我们要释放钩子,在下一个菜单弹出时重新安装钩子,弹出菜单示例代码如下:

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中处理,示例代码如下:

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 < iCount && iButton >= 0)

{

iNextPop = iButton;

SendMessage(hWndMain, WM_CANCELMODE, 0, 0);

}

else

{

iNextPop = -1;

}

}

}

(经验与建议:不要试图在此处调用TrackPopup,我曾试图取消该函数内的while循环,直接在此调用该函数,结果是在TrackPopupMenuEx未返回之前,该函数已被调用)

这里,仅仅处理了鼠标移动消息,真正的菜单还应处理键盘导航消息,详细的代码可以参考

BCGControlBar(http://www.vckbase.com/code/downcode.asp?id=1382)

或SizableRebar(http://www.codeproject.com/docking/sizablerebar/SizableRebar_demo.zip

有了这底层框架,这些处理过程应该不再困难,文章所涉及到的一些API函数可以参考msdn。

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有