【发布时间】:2017-02-11 10:11:39
【问题描述】:
我正在维护一个 WPF .NET 应用程序,并且用户在尝试从 DataGrid 控件复制时遇到了崩溃。我google了一下,发现原因是他正在使用的其他一些应用程序可能没有调用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。我会尝试并尝试一下。
【问题讨论】:
-
您是否使用 WinForms 剪贴板类 (msdn.microsoft.com/en-us/library/…) 进行了测试并查看它们的行为是否有所不同?不知道会不会,只是一个想法。
-
@Yushatak 是的,WinForms 剪贴板方法使用“尝试几次”循环,而 WPF 剪贴板方法没有,只是立即抛出异常。据我所知,没有其他区别。
-
看起来 CloseClipboard 没有参数,所以也许你在处理该异常的地方尝试调用 CloseClipboard 并重试?
-
@Yushatak 这是我的第一个希望,但据我所知,它没有做任何事情。另外,请参阅我的更新。
标签: c# wpf google-chrome clipboard