
圖 1:動態變化的選單背景圖
商業軟體常駐系統匣並提供右鍵選單是標準配備。本文透過一個「背景圖隨選單狀態變化」的範例,完整說明如何實作系統匣圖示與右鍵彈出選單功能。
標準流程三步驟:
在 XXDlg.cpp 檔頭加入:
#define WM_NOTIFYICON (WM_USER + 5)
NOTIFYICONDATA nd;
nd.cbSize = sizeof(NOTIFYICONDATA);
nd.hWnd = m_hWnd;
nd.uID = IDR_MAINFRAME;
nd.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nd.uCallbackMessage = WM_NOTIFYICON;
nd.hIcon = m_hIcon;
strcpy(nd.szTip, "我的系統匣");
Shell_NotifyIcon(NIM_ADD, &nd);
Shell_NotifyIcon(NIM_DELETE, &nd);

圖 2:選單資源編輯畫面
建立選單資源並對應四個命令處理函式:
void CbackdropDlg::OnShow() { ShowWindow(SW_SHOWNORMAL); }
void CbackdropDlg::OnExit() { ::PostQuitMessage(0); }
void CbackdropDlg::OnHide() { ShowWindow(SW_HIDE); }
void CbackdropDlg::OnMin() { ShowWindow(SW_SHOWMINIMIZED); }
LONG CbackdropDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG_MAP
ON_MESSAGE(WM_NOTIFYICON, OnNotifyIcon) // 手動加入
END_MESSAGE_MAP()
LONG CbackdropDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
{
switch (lParam)
{
case WM_RBUTTONDOWN: // 右鍵點擊彈出選單
{
CMenu menu;
if (menu.LoadMenu(IDR_MENU1))
{
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CPoint pt;
GetCursorPos(&pt);
// 依視窗狀態啟用/停用選單項
if (IsIconic())
pPopup->EnableMenuItem(IDC_MIN, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
if (IsWindowVisible())
{
if (!IsIconic())
pPopup->EnableMenuItem(IDC_SHOW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
else
pPopup->EnableMenuItem(IDC_HIDE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
// 動態切換選單文字(對應背景圖狀態)
if (bkbmp)
menu.ModifyMenu(IDC_FIX, MF_STRING, IDC_FIX, "變化背景");
else
menu.ModifyMenu(IDC_FIX, MF_STRING, IDC_FIX, "固定背景");
SetForegroundWindow();
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
}
}
break;
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
// OnShow(); // 可選:雙擊/單擊左鍵還原視窗
break;
}
return 0;
}
感謝 VCKBASE 論壇諸位高手指點,本文整合了系統匣選單與動態背景圖技術。若想深入了解背景圖實作細節,請參考原始碼範例;更多系統匣技術請搜尋本站相關文章。限於水平,缺漏在所難免,敬請批評指正。