我正在维护一个WPF .NET应用程序,并且用户在尝试从DataGrid控件进行复制时遇到了崩溃。我用谷歌搜索,发现其原因是他使用的其他一些应用程序可能没有调用CloseClipboard()
。 Excel也在相同的情况下给出了一条错误消息,消息“我们无法释放剪贴板上的空间”。另一个程序现在可能正在使用它。'
然而,出于好奇,我想看看谷歌浏览器如何处理这个问题。我使用我的程序锁定了剪贴板,并确认Excel正在抱怨。但是,Chrome仍然可以优雅地处理复制/粘贴。我可以从Chrome复制到记事本,但不能从记事本和Excel复制。而且很有趣,我实际上可以从记事本复制到Chrome。
我一直在浏览Chromium的源代码,但我无法找到复制/粘贴逻辑的实现。有谁知道Chrome如何处理这个问题?
我怎样才能在记事本中复制/粘贴,但从记事本到Chrome工作正常?
在我可以在网上找到的所有实现中,解决方案似乎与我现在的解决方案相同:在放弃之前尝试几次,大约一秒钟。
作为参考,这是我的剪贴板储物柜背后的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ClipboardLocker
{
public partial class MainWindow : Window
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool OpenClipboard(IntPtr hWndNewOwner);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool CloseClipboard();
bool clipboardLocked = false;
public MainWindow()
{
InitializeComponent();
double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
double windowWidth = this.Width;
double windowHeight = this.Height;
this.Left = (screenWidth / 2) - (windowWidth / 2);
this.Top = (screenHeight / 2) - (windowHeight / 2);
}
private void LockButton_Click(object sender, RoutedEventArgs e)
{
if (!clipboardLocked)
{
IntPtr handle = GetOpenClipboardWindow();
OpenClipboard(handle);
clipboardLocked = true;
LockButton.Content = "Unlock";
}
else
{
CloseClipboard();
clipboardLocked = false;
LockButton.Content = "Lock";
}
}
}
}
[UPDATE]
经过一些实验,似乎Chrome能够以某种方式解锁剪贴板。在Chrome中完成复制/粘贴后,它也适用于其他应用程序。 Chromw如何偷窃'来自我的储物柜程序的剪贴板?
MSDN mentioins ChangeClipboardChain
。我会试着尝试一下。
答案 0 :(得分:1)
要接管剪贴板,我首先使用OpenClipboard
参数调用NULL
。这会从当前持有它的任何窗口“窃取”剪贴板。然后我通过拨打CloseClipboard
来关闭它。这将是有效的,因为剪贴板将是“打开的剪贴板与当前任务相关联”,如MSDN所示。
现在剪贴板已正确关闭,调用WPF或Windows窗体'Clipboard.SetText()
可以正常工作。
这当然不是一个很好的解决方案,但我相信这是Windows在这种情况下给我们的最佳选择。
如果其他人遇到此问题,请点击此处ClipboardHelper
。
static class ClipboardHelper
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool OpenClipboard(IntPtr hWndNewOwner);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool CloseClipboard();
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
public static bool SetText(string text)
{
IntPtr hWnd = GetOpenClipboardWindow(); // Gets the HWND of the window that currently owns the clipboard
if (hWnd == null) // If no window currently owns the clipboard, just go ahead and set the text.
{
System.Windows.Forms.Clipboard.SetText(text);
}
else
{
OpenClipboard(IntPtr.Zero);
CloseClipboard();
System.Windows.Forms.Clipboard.SetText(text);
}
return true;
}
}
答案 1 :(得分:0)
将数据写入JSON文件而不是剪贴板。因此,即使程序将被关闭,您也可以访问值。