Реализация IDocHostUIHandler.FilterDataObject в C # - PullRequest
0 голосов
/ 07 декабря 2011

Я пытаюсь добавить редактор с поддержкой HTML в приложение WPF. Очевидным выбором является использование элемента управления WebBrowser по умолчанию и перевод его документа в «режим разработки». Пока все хорошо.

Теперь становится сложно, потому что мне нужно перехватывать контент, который вставляется в редактор из буфера обмена, чтобы убедиться, что он находится в удобном для использования формате. Например, при вставке фрагмента из документа Word, содержащего изображение, изображение представляется фрагментом Office XML, который элемент управления Browser не понимает, поэтому мне нужно заменить его простым тегом imageперед ним. вставляется в документ.

После осознания того, что на чистом уровне WPF этого добиться невозможно, мне пришлось перейти к компоненту ActiveX, для которого элемент управления WebBrowser является лишь оболочкой. Похоже, что моя проблема (и некоторые другие, с которыми я тоже сталкиваюсь, но которые не относятся к этому вопросу) может быть решена путем предоставления пользовательской реализации интерфейса IDocHostUIHandler.

Этот интерфейс содержит метод с именем FilterDataObject, который, очевидно, вызывается всякий раз, когда происходит операция вставки, что дает реализации возможность проверять и, при необходимости, изменять данные, полученные браузером из буфера обмена.

Для справки, вот определение метода в интерфейсе IDocHostUIHandler:

[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("bd3f23c0-d43e-11cf-893b-00aa00bdce1a")]
public interface IDocHostUIHandler {
    // ...
    [PreserveSig]
    int FilterDataObject(
        [In, MarshalAs(UnmanagedType.Interface)] object pDO,
        [Out, MarshalAs(UnmanagedType.Interface)] out object ppDORet
    );
}

Передаваемый COM-объект может быть приведен к System.Runtime.InteropServices.ComTypes.IDataObject, и он отлично работает для доступа к содержимому буфера обмена. Но когда я на самом деле пытаюсь вернуть замещающий IDataObject через параметр out, я получаю исключение нарушения прав доступа.

Например, наивная попытка просто вернуть новый экземпляр существующего класса System.Windows.DataObject (который также реализует ...ComTypes.IDataObject, поэтому я надеялся, что CLR сможет должным образом вывести его из-за пределов коробка) вот так ...

public class MyDocHostUIHandler : IDocHostUIHandler {
    // ...
    public int FilterDataObject(object pDO, out object ppDORet) {
        ppDORet = new System.Windows.DataObject("Text", "New Clipboard Content!");
        return S_OK; // S_OK means that the data object has been replaced
    }
}

... не работает (AccessViolationException, как только я пытаюсь вставить что-либо в редактор).

Кто-нибудь когда-нибудь делал что-то подобное? Что я могу делать не так? Испорчено ли определение моего интерфейса ComImport-ed (было довольно сложно найти версию в Интернете, которая действительно работает - по крайней мере, некоторое время - для начала)? Что я пытаюсь сделать, даже возможно из управляемого кода?

1 Ответ

1 голос
/ 12 декабря 2011

Попробуйте [return: MarshalAs (UnmanagedType.I4)] int FilterDataObject (System.Runtime.InteropServices.ComTypes.IDataObject pDO, из System.Runtime.InteropServices.ComTypes.IDataObject ppDORet); }

Если у вас есть проблемы с генерацией подписей для интерфейсов COM, часто вы можете генерировать из инструментов Windows SDK, используя midl и tlbimp .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...