• 在菜单条上添加泡泡提示


    该功能的实现来源于codeproject上面的一个例子《Tooltips for Menu Item and popup menuitem》,其实例子讲的步骤很简单,不过我不打算简单的翻译一下,林语堂先生不是说:“只用一样东西,不明白它的道理,实在不高明”。
       实现该功能的核心在于作者自己建立的一个MenuToolTip类,182行的代码实现了菜单提示的功能,下面我就将其一一解释开来,在每行代码的后面有具体的解释。
       #ifndef _MENU_TOOLTIP //条件编译语句,判断是否定义了_MENU_TOOLTI宏
    #define _MENU_TOOLTIP
    //以下定义一些常量标识符
    #ifndef TTS_NOANIMATE
     #define TTS_NOANIMATE           0x10
     #define TTS_NOFADE              0x20
     #define TTS_BALLOON             0x40
     #define TTS_CLOSE               0x80

     #define TTM_SETTITLEA           (WM_USER + 32)  // wParam = TTI_*, lParam = char* szTitle
     #define TTM_SETTITLEW           (WM_USER + 33)  // wParam = TTI_*, lParam = wchar* szTitle

     #ifdef UNICODE
     #define TTM_SETTITLE            TTM_SETTITLEW
     #else
     #define TTM_SETTITLE            TTM_SETTITLEA
     #endif
    #endif


    class CMenuToolTip
    {

      public:
     CMenuToolTip():m_hToolTip(0), m_hParent(0) {}

     // 创建与菜单项相关的提示
     void Create(HWND hParent, LPCTSTR sczTipText,
       HINSTANCE hInstance = NULL,
       DWORD dwStyle = 0,
       LPCTSTR sczTipTitle = NULL);
     //触发WM_MENUSELECT消息时调用此函数
     void OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSubMenu);

     // 显示或隐藏提示的函数
     void ShowToolTip(BOOL bShow)
     {
      TOOLINFO    ti;//TOOLINFO是一个存放控件提示信息的结构
                     //以下初始化该结构中的一些变量
      ti.cbSize = sizeof(TOOLINFO);//设定结构的大小
      ti.uFlags = TTF_IDISHWND;//指出uid成员是窗口的句柄
      ti.hwnd   = m_hParent;//包含提示的窗口的句柄
      ti.uId    = (UINT)m_hParent;//应用程序定义的标识符
      //发送出现提示的消息
      ::SendMessage(m_hToolTip,TTM_TRACKACTIVATE,(WPARAM)bShow,(LPARAM)&ti);
     }

     // 设置提示出现的位置
     void SetToolTipPosition(HMENU hMenu, UINT nItemID)
     {
      RECT rt = {0,0,0,0};
      
      // find Item Rectangle and position
      //根据菜单项的数量完成以下循环
      for(int nItem = 0; nItem < ::GetMenuItemCount(hMenu); nItem++) {
       UINT cmd = ::GetMenuItemID(hMenu, nItem);//将当前菜单项的标识符存放到一个变量中
       //如果当前菜单项是选定的菜单项,则获取菜单项的区域
       if(cmd == nItemID) {
        ::GetMenuItemRect(m_hParent, hMenu, nItem, &rt);
       }
      }
      
      
      //发送消息以设定显示提示的位置
      ::SendMessage(m_hToolTip, TTM_TRACKPOSITION, 0,
          (LPARAM)MAKELPARAM(rt.right, rt.bottom + 2));
      //将提示显示在最顶层,否则的话提示箭头会出现在菜单下面,试试看:->
      ::SetWindowPos(m_hToolTip, HWND_TOPMOST ,0,0,0,0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOMOVE);
     }

     // 更新提示信息
     void UpdateToolTipText(LPCTSTR szBuff, HINSTANCE hInstance = 0)
     {

      TOOLINFO    ti;
      ti.cbSize = sizeof(TOOLINFO);
      ti.uFlags = TTF_IDISHWND;
      ti.hwnd   = m_hParent;
      ti.uId    = (UINT)m_hParent;
      ti.hinst = hInstance;
      ti.lpszText  = const_cast<LPTSTR>(szBuff);//更新提示文本的内容
      //发送更新的消息
      ::SendMessage(m_hToolTip,TTM_UPDATETIPTEXT,(WPARAM)0,(LPARAM)&ti);
     }
    //重载句柄操作符
     operator HWND()
     {
      return m_hToolTip;
     }

      private:
      HWND m_hToolTip;
      HWND m_hParent;
      TCHAR m_szDefault[_MAX_PATH] ;//存放缺省提示的串
      HINSTANCE m_hInstance;
    };

    inline//以下内联函数创建提示控件
    void CMenuToolTip::Create(HWND hParent, LPCTSTR sczTipText, HINSTANCE hInstance,
           DWORD dwStyle, LPCTSTR sczTipTitle)
    {
     INITCOMMONCONTROLSEX icex;//在公用控件的动态链接库中注册公用控件类
     TOOLINFO    ti;
     // Load the ToolTip class from the DLL.
     icex.dwSize = sizeof(icex);
     icex.dwICC  = ICC_BAR_CLASSES;
     //如果注册失败,则返回
     if(!InitCommonControlsEx(&icex))
        return;

     m_hParent = hParent;
     m_hInstance = hInstance;
       
     // 创建提示控件
     m_hToolTip = ::CreateWindow(TOOLTIPS_CLASS, TEXT(""),
            WS_POPUP| dwStyle,
            CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, (HMENU)NULL, hInstance,
            NULL);

     // 设置控件的一些初始参数
     ti.cbSize = sizeof(TOOLINFO);
     ti.uFlags = TTF_IDISHWND | TTF_TRANSPARENT | TTF_TRACK | TTF_ABSOLUTE;//TTF_CENTERTIP
     ti.hwnd   = hParent;
     ti.uId    = (UINT)hParent;
     ti.hinst  = hInstance;
     ti.lpszText  = const_cast<LPTSTR>(sczTipText);
     if(sczTipText != LPSTR_TEXTCALLBACK) {
      //以下设定缺省提示文本
      if(sczTipText) {//如果当前菜单存在提示文本,则将其存放到m_szDefault
       _tcscpy(m_szDefault, sczTipText);
      }
      else {//如果不存在提示文本,则显示以下字符串
       _tcscpy(m_szDefault, _T("No Text associated"));
      }
     }

     ti.rect.left = ti.rect.top = ti.rect.bottom = ti.rect.right = 0;

     //把提示添加到控件中
     ::SendMessage(m_hToolTip,TTM_ADDTOOL,0,(LPARAM)&ti);

     ::SendMessage(m_hToolTip, TTM_SETMAXTIPWIDTH, 0, 300);
     if(sczTipTitle) {
      ::SendMessage(m_hToolTip, TTM_SETTITLE, 1, (LPARAM)sczTipTitle);
     }
    }

    inline //以下内联函数设定在选定菜单时所做的操作
    void CMenuToolTip::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSubMenu)
    {
     if(nFlags & MF_POPUP
      || (nFlags == 0xFFFF && hSubMenu == NULL)) { // 菜单关闭时不出现提示
      ShowToolTip(FALSE);
     }

     if(!(nFlags & MF_POPUP)) {
      
      // 设置提示的位置
      SetToolTipPosition(hSubMenu, nItemID);

      // 更新提示的文本
      TCHAR szBuff[256];//定义一个存放提示文本的字符数组
      szBuff[0] = 0;
      //将指定的提示文本存放到预先设定的缓冲区中
      int nRet = ::LoadString(m_hInstance, nItemID, szBuff, 256);
    #if 0
      for(int i = 0; i < nRet; i++)
      {
       if(szBuff[i] == _T('/n'))
       {
        szBuff[i] = 0;
        break;
       }
      }
    #endif  
      //以下部分主要用于更新提示文本,否则文本是固定的
      if(szBuff[0] != 0) {
       UpdateToolTipText(szBuff);
      }
      else {
       UpdateToolTipText(m_szDefault);
      }
      ShowToolTip(TRUE);//设定需要显示提示
     }
    }

    #endif _MENU_TOOLTIP
    上面的注释写的比较详细了,您可以在相应的地方做修改,以更改提示的位置和内容,将上面的代码存为一个名为menutooltip.h的头文件,将其加入到您的工程当中,然后在需要处理提示信息的类的初始函数(如对话框的OnInitDialog函数或者是类的构造函数)中添加如下语句:
     myMenuToolTip.Create(m_hWnd, _T("Sample Menu Text"), AfxGetResourceHandle()
       ,TTS_NOPREFIX | TTS_BALLOON
       , _T("My Best Tool Tip Title")
       );
    同时在相应的类中创建OnMenuSelect函数如下:
    void CMenuItemToolTipDlg::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSubMenu)
    {
     myMenuToolTip.OnMenuSelect(nItemID, nFlags, hSubMenu);
     CWnd::OnMenuSelect(nItemID, nFlags, hSubMenu);
    }
    同时不要忘了加入上述头文件,并定义一个提示信息类的变量
    #include "MenuToolTip.h"
    CMenuToolTip myMenuToolTip;
    最后在消息循环中加入ON_WM_MENUSELECT()
    一切ok了。
    Ps:在这里显示的提示信息都是您在定义菜单资源时设定的,也就是在定义一个菜单项时,右键选定属性,在general中有一个prompt文本框,用于设定提示文本,如果文本过长,可以在其中加上“/r/n”进行换行。




    CNBIE BLOG

    在菜单中加入图标

    原文:在菜单中加入图标
     
    'API函数声明
    Option Explicit
    Private Declare Function GetMenu Lib "user32"(Byval hwnd As Long) _
    As Long '取得窗口的菜单句柄,hwnd是窗口的句柄
    Private Declare Function GetSubMenu Lib "user32"(Byval hMenu As _
    Long,Byval nPos As Long) As Long '取得子菜单句柄,nPos是菜单的位置
    Private Declare Function SetMenuItemBitmaps Lib "user32"(Byval _
    hMenu As Long,Byval nPos As Long,Byval wFlags As Long,Byval _
    hBitUnchecked As Long,Byval hBitChecked As Long) As Long
    '为菜单设置相应的图形
    Const MF_BITMAP=&H400&
    '用image或picture或imagelist控件装入图形(必须是bmp格式),16*16左右
    '建好菜单
    Private Sub Form_Load()
    Dim hMenu,hSubMenu1,hSubMenu2 As Long
    hMenu=GetMenu(me.hwnd)
    hSubMenu1=GetSubMenu(hMenu,0) '取得第一项菜单的子菜单句柄
    SetMenuItemBitmaps hSubMenu1,0,MF_BITMAP,imagelist1.listimages(1) _
    .picture,imagelist1.listimages(1).picture
    '为hSubMenu1的第一项设置图形,假设用imagelist控件装入图形
    SetMenuItemBitmaps hSubMenu1,1,MF_BITMAP,imagelist1.listimages(2) _
    .picture,imagelist1.listimages(2).picture
    '设置第二项,同样你还可以设置第xx项。

    hSubMenu2=GetSubMenu(hMenu,1) '取得第二项菜单的子菜单句柄

    '也可用SetMenuItemBitmaps来设置它的图形,只更改hSubMenu1为hSubMenu2
    '即可
    End Sub



  • 相关阅读:
    centOS6.8 安装Nginx
    Linux 的su 与sudo 的区别,查看所有用户
    查看电脑 8080端口号被哪个应用占用
    配置文件出错 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
    IDEA 代码格式化,快捷键
    学习servlet心得
    nodejs笔记
    Tomcat 7.0.3x 启动慢并且遇到StackOverflowError的异常的解决办法
    国管公积金取房本
    前端准备技术汇总
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/2422351.html
Copyright © 2020-2023  润新知