WPF的方法和WinForm略有不同,具体步骤如下:
(1)首先定义消息钩子 #region 消息钩子预定义参数
private const int WM_DRAWCLIPBOARD = 0x308;
private const int WM_CHANGECBCHAIN = 0x30D;
private IntPtr mNextClipBoardViewerHWnd;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern bool ChangeClipboardChain(IntPtr HWnd, IntPtr HWndNext);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static public extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
#endregion
(2)重写OnSourceInitialized
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//挂消息钩子
mNextClipBoardViewerHWnd = SetClipboardViewer(source.Handle);
source.AddHook(WndProc);
}
(3)处理消息WM_DRAWCLIPBOARD 和WM_CHANGECBCHAIN
///(4)退出程序时注意移除钓子/// 参考:https://blog.csdn.net/xlm289348/article/details/8050957 /// MSG=0x308无法收到消息,原因是0x308是在剪贴板发生变化时将消息发送到监听列表中的第一个窗口 /// 所有这里要收到0x308必须将窗口放到监听列表里 /// 即在OnSourceInitialized(EventArgs e) 中调用SetClipboardView /// /// /// /// /// /// ///IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case WM_DRAWCLIPBOARD: { SendMessage(mNextClipBoardViewerHWnd, msg, wParam.ToInt32(), lParam.ToInt32()); //文本内容检测 if (System.Windows.Clipboard.ContainsText()) { //System.Windows.Clipboard.GetText()此处有Bug //String ct = System.Windows.Clipboard.GetText(); String ct = getClipboardText(); //做进一步操作 } } break; case WM_CHANGECBCHAIN: { if (wParam == (IntPtr)mNextClipBoardViewerHWnd) { mNextClipBoardViewerHWnd = lParam; } else { SendMessage(mNextClipBoardViewerHWnd, msg, wParam.ToInt32(), lParam.ToInt32()); } } break; default: break; } return IntPtr.Zero; }
private void ModernWindow_Closing(object sender, EventArgs e)
{
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//移除消息钩子
ChangeClipboardChain(source.Handle, mNextClipBoardViewerHWnd);
source.RemoveHook(WndProc);
}
2.WPF在读取剪贴板内容时报OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))错误
如果直接通过Clipboard.GetText()获取剪贴板上的文本时,如果剪贴板被占用(每次只能一个程序读取),则会报OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))错误,这是个随机错误,所以比较隐蔽,而且在WinForm中没有这个问题。
网上搜到有三种方法,这里我就只把我的解决方法贴在这里,因为剪贴板被其它程序占用是个小概率事件且占用时间通常很短,每次读取时多试几次就可以了。
private String getClipboardText()
{
for (int i = 0; i < 200; i++)
{
try
{
return System.Windows.Clipboard.GetText();
}
catch
{
System.Threading.Thread.Sleep(10);//这句加不加都没关系
}
}
return String.Empty;
}



