该功能的实现来源于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;
// 创建提示控件