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

.NET Compact Framework 實作智慧型裝置上的 NotifyIcon 類別

     編輯:關於C語言

前言

.NET Compact Framework (NET CF) 並未內建 NotifyIcon 控制項,這讓許多開發者在智慧型裝置上實作系統托盤圖示時感到棘手。本文將示範如何利用 Microsoft.WindowsCE.Forms.MessageWindow 類別搭配 Windows CE 平台 API Shell_NotifyIcon,自行打造一個功能完整的 NotifyIcon 類別。

核心原理

1. MessageWindow:訊息處理的橋樑

Microsoft.WindowsCE.Forms 命名空間提供了 MessageWindow 類別,它擁有虛擬方法 WndProc 可攔截視窗訊息,並暴露原生視窗控制代碼 Hwnd。我們繼承此類別並覆寫 WndProc,即可捕捉托盤圖示的點擊事件(WM_LBUTTONDOWN)。

2. Shell_NotifyIcon:底層 API 呼叫

Windows CE SDK 包含 coredll.dll 中的 Shell_NotifyIcon 函式,簽名如下:

[DllImport("coredll.dll")]
internal static extern int Shell_NotifyIcon(int dwMessage, ref NOTIFYICONDATA pnid);

關鍵結構 NOTIFYICONDATA 定義包含圖示控制代碼、接收訊息的視窗控制代碼、回呼訊息 ID 等欄位。注意 pnid 必須以 ref 方式傳遞(指標語意)。

完整實作程式碼

以下為 NotifyIcon 類別完整原始碼,支援多種圖示來源(檔案控制代碼、資源 ID、System.Drawing.Icon 物件)並提供新增、移除、修改圖示的方法。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace NotifyClient
{
    /// 
    /// 智慧型裝置托盤圖示類別
    /// 
    public class NotifyIcon
    {
        // 點擊事件
        public event EventHandler Click;

        private MyMessageWindow messageWindow;
        private int uID = 5000;
        private Icon _icon;

        public NotifyIcon()
        {
            messageWindow = new MyMessageWindow(this);
            messageWindow.uID = uID;
        }

        public Icon Icon
        {
            set { _icon = value; }
        }

        ~NotifyIcon()
        {
            Remove();
        }

        #region 公開方法:新增、移除、修改圖示

        /// 使用圖示控制代碼新增托盤圖示
        public void Add(IntPtr hIcon)
        {
            NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, hIcon);
        }

        /// 使用編譯後資源名稱(如 "#201547")新增
        public void Add(string iconRes)
        {
            IntPtr hIcon = LoadIcon(GetModuleHandle(null), iconRes);
            NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, hIcon);
        }

        /// 使用 Icon 物件新增
        public void Add(Icon icon)
        {
            NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, icon.Handle);
        }

        /// 使用屬性 Icon 新增
        public void Add()
        {
            if (_icon != null)
                NotifyMessage(messageWindow.Hwnd, NIM_ADD, (uint)uID, _icon.Handle);
        }

        /// 移除托盤圖示
        public void Remove()
        {
            NotifyMessage(messageWindow.Hwnd, NIM_DELETE, (uint)uID, IntPtr.Zero);
        }

        /// 修改現有托盤圖示
        public void Modify(IntPtr hIcon)
        {
            NotifyMessage(messageWindow.Hwnd, NIM_MODIFY, (uint)uID, hIcon);
        }

        #endregion

        #region 核心私有方法與 P/Invoke 定義

        private void NotifyMessage(IntPtr hwnd, int dwMessage, uint uID, IntPtr hIcon)
        {
            NOTIFYICONDATA notdata = new NOTIFYICONDATA();
            notdata.cbSize = 152; // 結構大小
            notdata.hIcon = hIcon;
            notdata.hWnd = hwnd;
            notdata.uCallbackMessage = WM_NOTIFY_TRAY;
            notdata.uFlags = NIF_MESSAGE | NIF_ICON;
            notdata.uID = uID;
            Shell_NotifyIcon(dwMessage, ref notdata);
        }

        // API 常數
        private const int NIF_MESSAGE = 0x00000001;
        private const int NIF_ICON = 0x00000002;
        private const int WM_LBUTTONDOWN = 0x0201;
        private const int NIM_ADD = 0x00000000;
        private const int NIM_MODIFY = 0x00000001;
        private const int NIM_DELETE = 0x00000002;
        private const int WM_NOTIFY_TRAY = 0x0400 + 2001; // 自訂訊息

        [StructLayout(LayoutKind.Sequential)]
        private struct NOTIFYICONDATA
        {
            public int cbSize;
            public IntPtr hWnd;
            public uint uID;
            public uint uFlags;
            public uint uCallbackMessage;
            public IntPtr hIcon;
        }

        [DllImport("coredll.dll")]
        private static extern int Shell_NotifyIcon(int dwMessage, ref NOTIFYICONDATA pnid);

        [DllImport("coredll.dll")]
        private static extern IntPtr LoadIcon(IntPtr hInst, string iconName);

        [DllImport("coredll.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        #endregion

        #region 內部訊息視窗類別

        private class MyMessageWindow : Microsoft.WindowsCE.Forms.MessageWindow
        {
            private int _uID;
            private NotifyIcon _notifyIcon;

            public MyMessageWindow(NotifyIcon notifyIcon)
            {
                _notifyIcon = notifyIcon;
            }

            public int uID
            {
                set { _uID = value; }
            }

            protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message msg)
            {
                if (msg.Msg == WM_NOTIFY_TRAY)
                {
                    if ((int)msg.LParam == WM_LBUTTONDOWN && (int)msg.WParam == _uID)
                    {
                        _notifyIcon.Click?.Invoke(_notifyIcon, EventArgs.Empty);
                    }
                }
            }
        }

        #endregion
    }
}

使用範例

// 在 Form 建構式中初始化
NotifyIcon trayIcon = new NotifyIcon();
trayIcon.Icon = new Icon("app.ico"); // 或從資源載入
trayIcon.Click += (s, e) => MessageBox.Show("托盤圖示被點擊!");
trayIcon.Add(); // 顯示到托盤

注意事項

  • 執行時若表單最大化遮擋工作列,請最小化視窗以觀察托盤圖示。
  • 專案需參考 Microsoft.WindowsCE.Forms.dll。
  • 原始碼下載:NotifyIconCf.rar
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved