【.net 深呼吸】監聽剪貼簿更新(針對Vista之後系統)

來源:互聯網
上載者:User

標籤:cte   das   nbsp   技術分享   封裝   rdl   use   void   .com   

針對 XP 及以前的監視剪貼簿更改的方法就不講了,因為 XP 已嚴重過時。本篇老周介紹的方法面向 Vista 以上的系統。

在託管應用程式中監聽剪貼簿更新行為必須用到 Win 32 API ,具體做法,我先簡單說一下。

首先,調用 AddClipboardFormatListener 函數來向視窗註冊監聽行為,它需要一個視窗控制代碼作為傳入參數,該控制代碼所指的視窗即是監聽剪貼簿更新的視窗。

然後,當剪貼簿的內容被更新,處理常式會收到一條 WM_CLIPBOARDUPDATE 訊息。我們在應用程式中,只要收到這條訊息,就說明剪貼簿的內容已被更新。

 

WM_CLIPBOARDUPDATE 訊息的宏定義如下:

#define WM_CLIPBOARDUPDATE              0x031D

這個訊息的 wParam 和 lParam 參數都不曾使用,所以我們不必理會這兩個參數值。如果使用者已處理該訊息,應當返回 0。

 

AddClipboardFormatListener 函數的原型如下:

BOOL WINAPI AddClipboardFormatListener(  _In_ HWND hwnd);

在Managed 程式碼中調用它,要先進行匯入。

        [DllImport("User32.dll")]        static extern bool AddClipboardFormatListener(IntPtr hwnd);

 

好,基本理論說完了,下面我們來看看如何在WPF程式中監聽剪貼簿更新。

由於此功能實為WPF與 Win32 的互動操作,因此,要用到 HwndSource 類,這個類公開了一個 AddHook 方法,調用這個方法可以添加一個 HwndSourceHook 委託執行個體,當視窗接收到訊息時,就會調用這個委託。

該委託的定義如下。

delegate IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled);

你一定會猛然發現,這個委託很像 WinProc 函數指標。msg 參數就是被攔截到的訊息。在與該委託綁定的方法中,我們可以對收到的訊息進行篩選,因為我們這裡只關心 WM_CLIPBOARDUPDATE 訊息,其他的咱們不管。

        private IntPtr OnHooked(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)        {            if (msg == WM_CLIPBOARDUPDATE)            {                ClipboardUpdated?.Invoke(this, EventArgs.Empty);                return IntPtr.Zero;            }            return IntPtr.Zero;        }

ClipboardUpdated 事件是我封裝時定義的,這是為了方便引發。

  public event EventHandler ClipboardUpdated;

 

還有一件事,各位會發現,HwndSource 執行個體建立時需要與一個視窗的控制代碼綁定,那麼,如何擷取到 Window 執行個體的控制代碼呢,這就要用到一個協助類—— WindowInteropHelper。有了它,想得到視窗的控制代碼就很簡單了。

            WindowInteropHelper helper = new WindowInteropHelper(window);            _hwndSource = HwndSource.FromHwnd(helper.Handle);

 

在添加 hook 處理之前,一定要記得調用 AddClipboardFormatListener 函數為視窗註冊監聽行為。

bool r = AddClipboardFormatListener(_hwndSource.Handle);

要是監聽行為註冊成功,就可以添加 hook 了。

            if (r)            {                _hwndSource.AddHook(new HwndSourceHook(OnHooked));            }

 

那麼,咱們封裝的這些代碼如何用到視窗代碼中呢。Window 有一個 SourceInitialized 事件,當控制代碼初始化完成就會發生。我們可以重寫 OnSourceInitialized 方法,然後在方法中使用我們上面封裝的代碼。

        ClipboardHooker m_clipboardHooker;        protected override void OnSourceInitialized(EventArgs e)        {            base.OnSourceInitialized(e);            m_clipboardHooker = new ClipboardHooker(this);            m_clipboardHooker.ClipboardUpdated += OnClipboardUpdated;        }        private void OnClipboardUpdated(object sender, EventArgs e)        {            tb.Text = "老闆,有人修改了剪貼簿。";            IDataObject data = Clipboard.GetDataObject();            string[] fs = data.GetFormats();            tb.Text += $"\n資料格式:{string.Join("、", fs)}";        }

 

只要監聽到剪貼簿被更新,那麼要擷取剪貼簿上的資料就很容易了,因為System.Windows下面已經有一個 Clipboard 類,它有一堆靜態方法,可以直接讀寫剪貼簿上的內容。

 

運行程式後,隨便複製點東東到剪貼簿中,就會看到程式有反應了。如下面高清無碼所示。

 

好了,本文就扯到這裡了。

本文樣本原始碼下載

 

【.net 深呼吸】監聽剪貼簿更新(針對Vista之後系統)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.