剪贴板打开失败。

3

我遇到了与剪贴板相关的问题,每次尝试从Excel文件进行复制/粘贴操作时都会收到此错误消息。

代码在Clipboard.GetDataObject()处中断,错误消息如下:

OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))

当我打开Excel,写一些文本并尝试复制/粘贴时,我的WPF应用程序已经在运行。

我使用的代码如下:

private void SetClipboardData()
{
    IDataObject data = Clipboard.GetDataObject();
    IList result = GetDataForFileDropFormat( data );

    if ( ( result != null ) && ( result.Count > 0 ) )
    {
        this._elementsClipboard = result;
        this._sourceDrag = null;
        this._sourceClipboard = null;
    }
}

上述函数在此处理程序方法中被调用:
public void Handle_WM_DRAWCLIPBOARD( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
{
    SendMessage( this._nextClipboardViewer, msg, wParam, lParam );

    // get data from clipboard
    SetClipboardData();

    handled = true;
}

我在 MSDN 和 .NET 论坛上搜寻了很久,但没有找到解决这个问题的方法。

有人可以帮忙或者给我一些尝试的思路吗?

谢谢!

2个回答

3
这里有几个问题。首先,虽然你确实需要将 WM_DrawClipboard 发送到链中的下一个应用程序,但是你不需要先这样做。你可以在运行自己的程序之后再通过该消息传递。其次,不要期望 Excel 会在一个操作中完成所有剪贴板更新。当复制复杂对象时,我见过 Excel 进行多达 24 次更新(特别是图表 - 它们会在添加每个单独格式后打开/关闭剪贴板)。此外,除了纯文本以外,Excel 几乎对所有内容都采用了延迟渲染。因此,当你的应用程序请求数据时,Excel 必须先进行渲染。这可能需要使用“while not success or 3-strikes loop”来实现延迟。不过,你需要仔细注意是否在处理过程之前或之后将 WM_DrawClipboard 下发到链中,因为你可能会与其他对 Excel 数据感兴趣的剪贴板查看器发生冲突,他们也不得不采用这些技巧。你还以为这很简单吗...

嗨,Chris!谢谢你的答案。最终我做了类似于你说的事情,现在它运行良好 :) - Costinel Dumitru

0

你不需要检查一下Clipboard对象是否包含正确类型的数据并请求该类型的对象吗?它可以容纳多个不同类型的对象,也许你正在获取一个意外类型的项目。我使用类似以下的代码,尽管在你的情况下,你不会从Clipboard请求我的自定义Address对象。

if (System.Windows.Clipboard.ContainsData("Address"))
{
    try
    {
        return (SerializableAddress)System.Windows.Clipboard.GetData("Address");
    }
    catch (COMException)
    {
        return null; 
    }
}
return null;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接