如何在WinApi C#中订阅剪贴板事件?

问题描述 投票:-1回答:2

我已经设置了一个查看器,这是当前进程,并希望收到消息qazxsw poi。

WM_DRAWCLIPBOARD

它说[DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer); var result = WinapiClipboard.SetClipboardViewer(Process.GetCurrentProcess().Handle); 我应该使用应用程序定义的函数来解析该消息。但它永远不会碰到功能/方法。

right here

我该怎么收到这条消息?我甚至订阅正确吗?

更新:

我没有使用WinForms / WPF或任何.NET经典框架功能。我只有.net标准2.0或.net核心。

c# winapi pinvoke clipboard
2个回答
0
投票

从winforms应用程序来看,这一切都非常简单

注意:您无法通过控制台应用程序执行此操作(轻松)

声明这个

    private static IntPtr WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
    {
        var hdc = Process.GetCurrentProcess().Handle;
        var clipboard = new WinClipboard();

        switch (message)
        {
            case WinapiClipboard.WM_DRAWCLIPBOARD:
                var result = clipboard.GetUnicodeTextAsync().Result;


                return IntPtr.Zero;
            default:
                break;
        }
        return WinapiClipboard.DefWindowProc(hWnd, message, wParam, lParam);
    }

在您的表单构造函数中

[DllImport("User32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

然后,您将通过覆盖WndProc接收表单中的// this.handle is your forms handle _ClipboardViewerNext = SetClipboardViewer(this.Handle); 消息

在你的形式

WM_DRAWCLIPBOARD


另一种方法是做到这一点,也许是一种更现代的方法

声明这个

protected override void WndProc(ref Message m)
{
    switch ((Win32.Msgs)m.Msg)
    {
        case Win32.Msgs.WM_DRAWCLIPBOARD:
        // Handle clipboard changed
        break;
        // ... 
   }

   // we call this so we to pass the message along
   base.WndProc(ref m);
}

在您的表单构造函数中

public const int WM_CLIPBOARDUPDATE = 0x031D;
public static IntPtr HWND_MESSAGE = new IntPtr(-3);

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddClipboardFormatListener(IntPtr hwnd);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

在你的形式

SetParent(Handle, HWND_MESSAGE);
AddClipboardFormatListener(Handle);

如果您使用的是类库,则必须创建一个隐藏的并传回一个动作或事件

protected override void WndProc(ref Message m)
{
     if (m.Msg == WM_CLIPBOARDUPDATE)
     {
        // handle message
     }
     base.WndProc(ref m);
}

注意:这些都没有经过测试,但应该让您入门


更新1

private class HiddenForm : Form { public HiddenForm() { SetParent(Handle, HWND_MESSAGE); AddClipboardFormatListener(Handle); } protected override void WndProc(ref Message m) { if (m.Msg == WM_CLIPBOARDUPDATE) { // do stuff here like call event } base.WndProc(ref m); } } 需要一个窗口句柄,而不是一个进程句柄。如果您没有窗口句柄,请创建仅用于接收剪贴板消息的仅消息窗口 - 感谢IInspectable

更新2

这只适用于那种始终具有完整框架的机器。 - 感谢Hans Passant


0
投票

由于您正在执行winforms项目,因此覆盖现有的Control.WndProc而不是提供静态。

SetClipboardViewer
© www.soinside.com 2019 - 2024. All rights reserved.