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)
新聞熱點
疑難解答