我正在维护WPF .NET应用程序,并且用户在尝试从DataGrid控件进行复制时遇到了崩溃。我搜索了一下,发现原因是他正在使用的其他应用程序可能未调用CloseClipboard()
。在相同情况下,Excel也会显示错误消息,消息为“我们无法释放剪贴板上的空间。另一个程序可能正在使用它。”
然后,我编写了另一个具有打开/关闭剪贴板按钮的程序,然后可以重现此行为,并且仅通过一条错误消息实现了相同的“修复”。
但是,出于好奇,我想看看Google Chrome浏览器是如何处理此问题的。我使用程序锁定了剪贴板,并确认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";
}
}
}
}
[更新]
经过更多实验后,Chrome似乎能够以某种方式解锁剪贴板。在Chrome中完成复制/粘贴后,它也可以在其他应用程序中使用。Chromw如何从我的储物柜程序中“窃取”剪贴板?MSDN指导思想ChangeClipboardChain
。我将尝试和尝试。
要接管剪贴板,我首先调用OpenClipboard
一个NULL
参数。这将从当前保存剪贴板的任何窗口“窃取”剪贴板。然后,我通过致电将其关闭CloseClipboard
。现在这将起作用,因为剪贴板将是MSDN所说的“打开的剪贴板与当前任务相关联”。
现在剪贴板已正确关闭,可以调用WPF或Windows Forms的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;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句