C# 通过WinApi32监视剪贴板中的更改

C# 通过WinApi32监视剪贴板中的更改,c#,winapi,clipboard,C#,Winapi,Clipboard,我想监视剪贴板更改(仅文本)。我试图找到一些解决方案,在StackOverflow上发现了以下问题: 但我的问题/要求是,我不想向Windows.Forms或WPF(我的应用程序是一个控制台应用程序)添加依赖项。我尝试查看user32.dll中的可用方法。我写了一个代码,创建一个窗口和窗口样式。将WNDPC方法重写为自定义方法,然后将侦听器添加到剪贴板更改。WndProcFunction已为以下消息调用4次: WM_GETMINMAXINFO 创建 WM_NCCALCSIZE 创建

我想监视剪贴板更改(仅文本)。我试图找到一些解决方案,在StackOverflow上发现了以下问题:

但我的问题/要求是,我不想向Windows.Forms或WPF(我的应用程序是一个控制台应用程序)添加依赖项。我尝试查看user32.dll中的可用方法。我写了一个代码,创建一个窗口和窗口样式。将WNDPC方法重写为自定义方法,然后将侦听器添加到剪贴板更改。WndProcFunction已为以下消息调用4次:

  • WM_GETMINMAXINFO
  • 创建
  • WM_NCCALCSIZE
  • 创建
但当我更改剪贴板的内容时,会发送WM_CLIPBOARDUPDATE类型的消息,也不会发送任何适合WndProcFunction的消息。我尝试使用一个“旧API”(
SetDashboardViewer
),但它没有任何改变。代码如下所示:

使用PInvoke;
...
内部静态类User32Ext
{
[DllImport(“user32.dll”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
内部静态外部bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport(“user32.dll”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
内部静态外部布尔RemoveClipboardFormatListener(IntPtr hwnd);
[DllImport(“kernel32.dll”)]
内部静态外部uint GetLastError();
}
班级计划
{
私有静态IntPtr _nextInChain=IntPtr.Zero;
内部静态不安全IntPtr WndProcFunction(IntPtr hwnd,User32.WindowMessage WindowMessage,void*wParam1,void*lParam1)
{
if(windowMessage==User32.windowMessage.WM\u创建)
{
var listener=User32Ext.AddClipboardFormatListener(hwnd);
var result=User32.OpenClipboard(窗口);
//_nextInChain=User32Ext.SetClipboardViewer(hwnd);
}
if(windowMessage==User32.windowMessage.WM_剪贴簿更新)
{
var pointerToText=User32.GetClipboardData_IntPtr(1);
var text=Marshal.PtrToStringAnsi(pointerToText);
控制台写入线(文本);
}
if(windowMessage==User32.windowMessage.WM\u剪贴板)
{
如果(_nextInChain!=IntPtr.Zero)
{
User32.SendMessage(_nextInChain,windowMessage,wParam1,lParam1);
}
}
if(windowMessage==User32.windowMessage.WM_CHANGECBCHAIN)
{
_nextInChain=hwnd;
//发送消息。。。
}
if(windowMessage==User32.WM\u)
{
//链味精
User32Ext.RemoveClipboardFormatListener(hwnd);
}
return hwnd;//成功
}
静态void Main(字符串[]参数)
{
不安全的
{
var hInstance=Marshal.GetHINSTANCE(typeof(Program).Module);
string name=“Test”;
User32.WNDCLASSEX WNDCLASSEX=新User32.WNDCLASSEX
{
cbSize=Marshal.SizeOf(typeof(User32.WNDCLASSEX)),
style=User32.ClassStyles.CS\u GLOBALCLASS,
cbClsExtra=0,
cbWndExtra=0,
hbrBackground=IntPtr.Zero,
hCursor=IntPtr.Zero,
hIcon=IntPtr.Zero,
hIconSm=IntPtr.Zero,
lpszMenuName=null,
hInstance=hInstance,
lpfnWndProc=newuser32.WndProc(WndProc函数)
};
var stringPtr=Marshal.StringToHGlobalAuto(名称);
wndClassEx.lpszClassName_IntPtr=stringPtr;
var register=User32.RegisterClassEx(参考wndClassEx);
var window=User32.CreateWindowEx(
User32.WindowStylesEx.WS_EX_透明,
名称
“测试窗口”,
0,
0, 0, 0, 0,
IntPtr.Zero,
IntPtr.Zero,
wndClassEx.hInstance,
IntPtr.Zero
);
User32.SetClipboardData(13,stringPtr);
...
}
}
}
代码中是否还有我遗漏的东西,一些额外的侦听器?每次从user32.dll调用方法后,我都会查看错误代码。但是,所有这些都成功了,没有任何失败。

A是接收消息所必需的。如果您不需要窗口,可以创建一个允许您发送和接收消息的窗口

它不可见、没有z顺序、无法枚举且不存在 接收广播信息。窗口只是发送消息

在C#中,在
main
函数的末尾,它将如下所示:

    MSG msg;  
    while (User32.GetMessage(out msg, IntPtr.Zero, 0, 0) != 0)  
    {  
        User32.TranslateMessage(ref msg);  
        User32.DispatchMessage(ref msg);  
    }  

请参阅,.

是否已检查是否调用了
AddClipboardFormatListener
?如果是,请检查是否成功执行?如果没有,请通过检查返回值和窗口句柄来确保您的窗口创建成功。@RitaHan MSFT“每次从user32.dll调用方法后,我都会查看错误代码。但所有操作都成功,没有任何失败。”。此外,所有侦听器函数都返回
true
。一切似乎都很好。谢谢!我发现我未能在MSDN上“谷歌”搜索该信息:(