wtl嵌入类的架构可以使整个程序很清晰,系统托盘气泡提示、上下文菜单处理可以分别独立出来,以下是实现代码,很清晰就不注释了。基本上这两个类很少需要修改,因此我把它们放到了系统包含文件搜索路径中。
//contextmenu.h
#pragma once
template <class t>
class ccontextmenu
{
public:
bool createcontextmenu(uint id_menu)
{
t* pt = static_cast<t*>(this);
cmenu menu;
menu.loadmenu(id_menu);
cmenu submenu(menu.getsubmenu(0));
point pos;
getcursorpos(&pos);
submenu.trackpopupmenu(tpm_leftalign | tpm_rightbutton, pos.x, pos.y, pt->m_hwnd);
return true;
}
};
//shellicon.h
#pragma once
#define wm_icon wm_user + 180
template <class t, class menut, int menuid>
class cshellicon : public menut
{
private:
notifyicondata m_data;
uint m_msgtaskbarrestart;
cstring m_appname;
public:
cshellicon()
{
m_appname.loadstring(ids_appname);
m_msgtaskbarrestart = registerwindowmessage(text("taskbarcreated"));
}
~cshellicon()
{
shell_notifyicon(nim_delete, &m_data);
}
bool createshellicon()
{
t* pt = static_cast<t*>(this);
securezeromemory(&m_data, sizeof(m_data));
m_data.cbsize = sizeof(m_data);
m_data.hicon = loadicon(_module.get_m_hinst(), makeintresource(idr_mainframe));
m_data.hwnd = pt->m_hwnd;
m_data.uid = idr_mainframe;
m_data.uflags = nif_icon | nif_message | nif_info | nif_tip;
m_data.ucallbackmessage = wm_icon;
m_data.dwinfoflags = niif_user;
strcpy_s(m_data.szinfotitle, m_appname);
strcpy_s(m_data.sztip, m_appname);
return shell_notifyicon(nim_add, &m_data);
}
void modifytooltips(lpctstr info)
{
strcpy_s(m_data.szinfo, info);
}
bool dispalytooltips()
{
return shell_notifyicon(nim_modify, &m_data);
}
bool balloontooltips(lpctstr info)
{
modifytooltips(lpctstr info);
return dispalytooltips();
}
begin_msg_map(cshellicon)
message_handler(wm_icon, onicon)
message_handler(m_msgtaskbarrestart, onrestart)
message_handler(wm_size, onsize)
chain_msg_map(menut)
end_msg_map()
lresult onicon(uint umsg, wparam wparam, lparam lparam, bool& bhandled)
{
t* pt = static_cast<t*>(this); char t;
if (wparam != idr_mainframe) return 1;
switch(lparam)
{
case wm_rbuttonup:
t = *m_data.szinfo;
*m_data.szinfo = '/0';
shell_notifyicon(nim_modify, &m_data);
pt->createcontextmenu(menuid);
*m_data.szinfo = t;
break;
case wm_lbuttonup:
pt->showwindow(sw_show);
openicon(pt->m_hwnd);
break;
//去掉下面的注释可以使鼠标悬停在图标上时出现气泡提示,个人不太喜欢
case wm_mousemove:
// dispalytooltips(); break;
default:
;
}
return 0;
}
//处理explorer外壳崩溃后任务栏重建,你会发现很多程序都没处理,结果就是explorer一崩溃
//图标就找不到了,如果最小化到任务栏更惨,还得用任务管理器关闭,这个函数我没机会测试,希望有作用
lresult onrestart(uint umsg, wparam wparam, lparam lparam, bool& bhandled)
{
t* pt = static_cast<t*>(this);
securezeromemory(&m_data, sizeof(m_data));
m_data.cbsize = sizeof(m_data);
m_data.hwnd = pt->m_hwnd;
m_data.uid = idr_mainframe;
shell_notifyicon(nim_delete, &m_data);
createshellicon();
return 0;
}
//最小化到系统托盘
lresult onsize(uint /*umsg*/, wparam /*wparam*/, lparam /*lparam*/, bool& /*bhandled*/)
{
t* pt = static_cast<t*>(this);
if (pt->isiconic()) pt->showwindow(sw_hide);
return 0;
}
};
//myiconmenu.h
#pragma once
#include "stdafx.h"
#include <contextmenu.h>
template <class t>
class cmyiconmenu : public ccontextmenu<t>
{
public:
begin_msg_map(ccontextmenu)
command_id_handler(id_resume, onresume)
command_id_handler(id_quit, onquit)
end_msg_map()
lresult onresume(word /*wnotifycode*/, word wid, hwnd /*hwndctl*/, bool& /*bhandled*/)
{
t* pt = static_cast<t*>(this);
pt->showwindow(sw_show);
openicon(pt->m_hwnd);
return 0;
}
lresult onquit(word /*wnotifycode*/, word wid, hwnd /*hwndctl*/, bool& /*bhandled*/)
{
postquitmessage(0);
return 0;
}
};
ccontextmenu的使用
如果你的窗口需要上下文菜单,只需要从ccontextmenu派生一个类,例如:template <class t> class cmycontextmenu : public ccontextmenu<t>
然后完成消息映射,例如cmyiconmenu所做的。在你的窗口类(假设为cmywindowclass)的继承列表里面添加public cmycontextmenu<cmywindowclass>,在消息映射表中添加chain_msg_map(cmycontextmenu<cmywindowclass>)
接下来只要在需要显示上下文菜单的地方,调用creatcontextmenu(uint id_menu)就可以了。
cshellicon的使用
首先要把stdafx.h中ie的版本改成5或者6,例如:
#define _win32_ie 0x0600
然后加入cstring支持,可能每个项目都几乎用到cstring,大家不妨直接修改模板文件,让向导直接把cstring加进去算了。
从ccontextmenu派生一个类来完成菜单映射,例如cmyiconmenu所作的。
以下用模式对话框来演示如何给其加入托盘功能,蓝色的部分为添加的部分。
#pragma once
#include "myiconmenu.h"
#include <shellicon.h>
class cmaindlg : public cdialogimpl<cmaindlg>, public cshellicon<cmaindlg, cmyiconmenu<cmaindlg>, idr_iconmenu>
{
public:
enum { idd = idd_maindlg };
typedef cshellicon<cmaindlg, cmyiconmenu<cmaindlg>, idr_iconmenu> cmyshellicon;
begin_msg_map(cmaindlg)
message_handler(wm_initdialog, oninitdialog)
command_id_handler(id_app_about, onappabout)
command_id_handler(idok, onok)
command_id_handler(idcancel, oncancel)
chain_msg_map(cmyshellicon)
end_msg_map()
lresult oninitdialog(uint /*umsg*/, wparam /*wparam*/, lparam /*lparam*/, bool& /*bhandled*/)
{
// center the dialog on the screen
centerwindow();
// set icons
hicon hicon = (hicon)::loadimage(_module.getresourceinstance(), makeintresource(idr_mainframe),
image_icon, ::getsystemmetrics(sm_cxicon), ::getsystemmetrics(sm_cyicon), lr_defaultcolor);
seticon(hicon, true);
hicon hiconsmall = (hicon)::loadimage(_module.getresourceinstance(), makeintresource(idr_mainframe),
image_icon, ::getsystemmetrics(sm_cxsmicon), ::getsystemmetrics(sm_cysmicon), lr_defaultcolor);
seticon(hiconsmall, false);
createshellicon();
return true;
}
……………………
};
在想弹出气泡的时候调用bool balloontooltips(lpctstr info)
新闻热点
疑难解答