首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 系統托盤 程式開發完整指南 (Shell_NotifyIcon)

     編輯:VC 教學

托盤區基本概念

  • 位於工作列通知區域 (系統托盤),提供常駐程式快速存取入口。
  • 核心 API:Shell_NotifyIcon (shellapi.h)。
  • 關鍵結構:NOTIFYICONDATA (NID)。

NOTIFYICONDATA 關鍵欄位

typedef struct _NOTIFYICONDATA {
    DWORD cbSize;           // sizeof(NOTIFYICONDATA)
    HWND  hWnd;             // 接收回呼訊息的視窗
    UINT  uID;              // 圖示識別碼 (同一視窗多圖示時區分)
    UINT  uFlags;           // 指出哪些欄位有效
                            // NIF_MESSAGE: uCallbackMessage 有效
                            // NIF_ICON:    hIcon 有效
                            // NIF_TIP:     szTip 有效
                            // NIF_STATE:   dwState/dwStateMask 有效 (Win2000+)
                            // NIF_INFO:    szInfo/szInfoTitle/dwInfoFlags 有效 (氣球提示)
    UINT  uCallbackMessage; // 自訂訊息 (如 WM_USER+1),滑鼠事件透過此訊息通知
    HICON hIcon;            // 托盤圖示句柄
    TCHAR szTip[128];       // 滑鼠懸停提示文字
    // 以下為 NIF_INFO / NIF_STATE 擴充欄位...
} NOTIFYICONDATA;

核心操作流程

  1. 加入圖示:Shell_NotifyIcon(NIM_ADD, &nid)
  2. 修改圖示/提示:Shell_NotifyIcon(NIM_MODIFY, &nid) (更新 hIcon/szTip)。
  3. 刪除圖示:Shell_NotifyIcon(NIM_DELETE, &nid) (程式結束時必須呼叫)。

完整實作範例 (主視窗隱藏,雙擊圖示顯示/隱藏)

// Unit1.h
class TForm1 : public TForm {
private:
    UINT FIconMsg;          // 自訂訊息 ID
    NOTIFYICONDATA FNid;
    void __fastcall AddTrayIcon();
    void __fastcall RemoveTrayIcon();
protected:
    virtual void __fastcall WndProc(TMessage &Message);  // 重寫視窗程序
    void __fastcall TrayIconMsg(TMessage &Msg);          // 處理托盤訊息
public:
    __fastcall TForm1(TComponent* Owner);
    __fastcall ~TForm1();
};

// Unit1.cpp
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
    FIconMsg = RegisterWindowMessage("MyApp_TrayIconMsg");  // 唯一訊息 ID
    AddTrayIcon();
    ShowWindow(Handle, SW_HIDE);  // 啟動時隱藏主視窗
}

__fastcall TForm1::~TForm1() {
    RemoveTrayIcon();
}

void __fastcall TForm1::AddTrayIcon() {
    ZeroMemory(&FNid, sizeof(FNid));
    FNid.cbSize = sizeof(FNid);
    FNid.hWnd = Handle;
    FNid.uID = 1;
    FNid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    FNid.uCallbackMessage = FIconMsg;
    FNid.hIcon = Application->Icon->Handle;  // 使用應用程式圖示
    StrLCopy(FNid.szTip, "我的托盤程式", sizeof(FNid.szTip)/sizeof(TCHAR));
    Shell_NotifyIcon(NIM_ADD, &FNid);
}

void __fastcall TForm1::RemoveTrayIcon() {
    FNid.cbSize = sizeof(FNid);
    FNid.hWnd = Handle;
    FNid.uID = 1;
    Shell_NotifyIcon(NIM_DELETE, &FNid);
}

void __fastcall TForm1::WndProc(TMessage &Message) {
    if (Message.Msg == FIconMsg) {
        TrayIconMsg(Message);  // 處理托盤滑鼠事件
        return;
    }
    TForm::WndProc(Message);  // 繼承鏈
}

void __fastcall TForm1::TrayIconMsg(TMessage &Msg) {
    switch (Msg.LParam) {  // lParam 為滑鼠事件
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_MOUSEMOVE:
            // 可在這裡追蹤滑鼠位置顯示右鍵選單
            break;
        case WM_LBUTTONDBLCLK:  // 雙擊左鍵
            Visible = !Visible;  // 切換主視窗顯示/隱藏
            if (Visible) SetForegroundWindow(Handle);
            break;
        case WM_RBUTTONUP: {
            // 顯示右鍵選單
            POINT pt; GetCursorPos(&pt);
            SetForegroundWindow(Handle);  // 修正選單焦點問題
            PopupMenu1->Popup(pt.x, pt.y);
            break;
        }
    }
}

進階功能

  • 氣球提示 (Win2000+):設定 NIF_INFO,填寫 szInfo, szInfoTitle, dwInfoFlags (NIIF_INFO/WARNING/ERROR/USER/NONE),呼叫 NIM_MODIFY。
  • 動態圖示:定時器輪換 hIcon (如網速、CPU 使用率圖示)。
  • 高 DPI:提供 16x16, 32x32, 48x48 多尺寸圖示資源,或使用 LoadImage 載入 PNG 並轉 HICON (需 Comctl32.dll 6.0+)。
  • 多圖示:不同 uID 區分,分別 NIM_ADD。

常見坑點

  • 未在 FormDestroy 呼叫 NIM_DELETE → 托盤留下「殭屍圖示」,需重啟 Explorer 消除。
  • uCallbackMessage 用 WM_USER+1 易衝突,**務必用 RegisterWindowMessage 取得唯一 ID**。
  • 右鍵選單彈出後不消失:呼叫 SetForegroundWindow(Handle) 先讓視窗獲取焦點。
  • 視窗隱藏時 Application->Icon 可能無效,建議直接載入 .ico 資源 LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON))。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved