您的位置:首頁>正文

監聽剪貼板更新

針對 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 );

在託管代碼中調用它, 要先進行導入。

[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 += $" 資料格式:{string.Join("、", fs)}"; }

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

運行程式後, 隨便複製點東東到剪貼板中,

就會看到程式有反應了。 如下麵高清無碼截圖所示。

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

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示