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; } };
|