Не удалось открыть буфер обмена

У меня проблема с буфером обмена, и я получаю это сообщение об ошибке каждый раз, когда пытаюсь выполнить операцию копирования/вставки из файла Excel.

Код прерывается на Clipboard.GetDataObject(), и сообщение об ошибке таково:

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

Мое приложение WPF уже запущено, когда я открываю Excel, пишу какой-то текст, а затем пытаюсь скопировать/вставить.

Код, который я использую, таков:

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, но не нашел обходного пути для этой проблемы.

Может ли кто-нибудь помочь мне с этим или дать мне представление о том, что я должен попробовать?

Спасибо!


person Costinel Dumitru    schedule 01.02.2012    source источник


Ответы (2)


Пара вопросов здесь. Во-первых, хотя вам определенно нужно отправить WM_DrawClipboard следующему приложению в цепочке, вам не нужно делать это ПЕРВЫМ. Вы можете сделать это после того, как запустите свой собственный материал, ТОГДА передайте сообщение.

Далее, не ожидайте, что Excel выполнит все обновления буфера обмена за одну операцию. Я видел, как Excel выполнял до 24 обновлений подряд при копировании сложных объектов. (особенно графики - они открывали/закрывали буфер обмена после добавления каждого отдельного формата).

Кроме того, Excel использует преимущества отложенного рендеринга почти для всего, кроме обычного текста. Таким образом, пока ваше приложение запрашивает данные, Excel их отображает. Это может занять время.

Возможно, вам придется реализовать задержку с циклом «пока не успех или 3 удара». Вам нужно будет обратить пристальное внимание на то, отправляете ли вы WM_DrawClipboard по цепочке до или после обработки, так как вы можете настроить еще одно столкновение с другими зрителями буфера обмена, которые также заинтересованы в данных Excel, и должны прибегать к таким сами трюки.

А вы думали, что это будет легко.....

person Chris Thornton    schedule 03.02.2012
comment
Привет Крис! Спасибо за Ваш ответ. Наконец-то я сделал что-то похожее на то, что вы сказали, и теперь все работает нормально :) - person Costinel Dumitru; 04.02.2012

Разве вам не нужно проверять, содержит ли объект Clipboard правильные данные, и запрашивать объект этого типа? Он может содержать несколько объектов разных типов, и, возможно, вы получаете элемент неожиданного типа. Я использую что-то вроде следующего, хотя ясно, что в вашем случае вы не будете запрашивать мой пользовательский объект Address из файла Clipboard.

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