dedecms织梦内容管理系统    
首页 | java | C/C++ | PHP | 操作系统 | ajax | 脚本编程 | 安全技术 | 本站下载页 | flex | CRM | 专题 | QQ群 | 测试中心 | 会员中心 | 积分规则
  当前位置:主页>C/C++>C/C++技术资料>文章内容
Toolbar制作菜单条过程详解
来源:编程爱好者     作者:    
现在许多用户界面都使用工具栏制作菜单条,小弟最近对此感兴趣,便从网上求助,可是得到的帮助大多是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);
(经验与建议:不要试图在此处调用TrackPopup,我曾试图取消该函数内的while循环,直接在此调用该函数,结果是在TrackPopupMenuEx未返回之前,该已被调用)
    }
    else
    {
      iNextPop = -1;
    }
  }
}
这里,仅仅处理了鼠标移动消息,真正的菜单还应处理键盘导航消息,详细的代码可以参考
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

 

 

上一篇:MFC应用程序框架入门   下一篇:改造MFC编写的控件在Win32ASM中使用
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论
  热点文章
·C语言数组排序小结
·Python 与 C++ 程序的简单实例对
·c++ 数组与指针
·C++中的内存管理(new、delete、
·如何用C语言开发DSP嵌入式系统
·如何用C语言开发DSP嵌入式系统
·Linux下C语言编程
·学习arm的话先看哪本书?
·C++初学者应该关心的优秀图书一
·利用C语言小程序来解决大问题
·用C语言写PHP扩展的步骤
·用C语言扩展PHP功能
  相关文章
·MFC应用程序框架入门
·改造MFC编写的控件在Win32ASM中
·谈新手对CString的使用
·在MFC扩展DLL中输出对话框
·Visual C++窗口标题改变的几种方
·如何编写控制面板程序
·熟悉标准库
·如何获取某个进程的主窗口以及创
·如何改变MFC默认文档操作方式
·如何用VC++和Visual Foxpro进行A
·如何创建有模式对话框
·如何自动截获输出到打印机的文本
  相关信息
copy right @ 百家拳软件项目研究室 2007 辽ICP备07011763