代码之家  ›  专栏  ›  技术社区  ›  D Thr.

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

  •  -1
  • D Thr.  · 技术社区  · 7 年前

    我已经设置了一个查看器,它是当前进程并希望接收消息 WM_DRAWCLIPBOARD .

    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
    
    var result = WinapiClipboard.SetClipboardViewer(Process.GetCurrentProcess().Handle);
    

    上面写着 right here 我应该使用应用程序定义的函数来解析该消息。但它从未触及函数/方法。

        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);
        }
    

    我应该如何获得此消息?我的订阅是否正确?

    更新:

    我没有使用WinForms/WPF或任何这些。NET经典框架功能。我所拥有的只是。净标准2.0或。净核心。

    2 回复  |  直到 7 年前
        1
  •  0
  •   TheGeneral    7 年前

    这都是winforms应用程序的直接内容

    笔记 :您无法从控制台应用程序轻松完成此操作

    声明此

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

    在窗体构造函数中

    // this.handle is your forms handle
    _ClipboardViewerNext = SetClipboardViewer(this.Handle); 
    

    然后您将收到 WM_DRAWCLIPBOARD 通过重写WndProc在表单中显示消息

    以您的形式

    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);
    }
    

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

    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);
        }
    }
    

    笔记 :这些都没有经过测试,但应该可以让您开始


    更新1

    SetClipboardViewer 需要窗口句柄,而不是进程句柄。如果 如果没有窗口句柄,请为 接收剪贴板消息的唯一目的-感谢 II不可检测

    更新2

    这将只适用于也始终具有 可用的完整框架。-幸亏 汉斯·帕桑特

        2
  •  0
  •   SoronelHaetir    7 年前

    由于您正在执行winforms项目,请重写现有控件。WndProc而不是提供静态。

    protected override void WndProc(ref Message m)
    {
    if(WM_DRAWCLIPBOARD == msg.Msg)
    { ... }
    else
      base.WndProc(ref msg);
    }