Как отключить VML в MSHTML - PullRequest
6 голосов
/ 22 июля 2011

Я использую элемент управления MSHTML в режиме редактирования. Когда я копирую и вставляю текст из слова в свой элемент управления, элементы управления MSHTML убирают стандартный HTML и сохраняют разметку VML, которая там не очень хорошо поддерживается.

Если я отменяю регистрацию VML Dll (regsvr32 -u "% ProgramFiles% \ Common Files \ Microsoft Shared \ VGX \ vgx.dll), то элемент управления ведет себя так, как я хочу, и удаляет VML и сохраняет HTML.

Я не смог программным способом сказать MSHTML, что мне нужен не VML, а HTML. Есть идеи?

Ответы [ 2 ]

1 голос
/ 27 августа 2014

Извините, если этот ответ не идеален, но с учетом возраста вопроса и количества интересующихся людей, я подумал, что смогу сделать снимок и, надеюсь, помочь кому-нибудь, если не ОП.

Я не уверен, как VML / Word обрабатывает данные буфера обмена. Если он помещает несколько форматов в буфер обмена Windows, один с нужным HTML, другой с форматом VML, то вам повезло, и это должно сработать. Если нет, то, возможно, вы могли бы использовать это для очистки кода на вставке, по крайней мере.

Вы захотите просмотреть IDocHostUIHandler :: TranslateAccelerator . Вам нужно реализовать IDocHostUIHandler, если вы этого еще не сделали. Вы используете ICustomDoc :: SetUIHandler для его регистрации после загрузки HTML-документа (может быть пустой страницей, если вы его используете).

Внутри TranslateAccelerator вам нужно следить за nCmdID == IDM_PASTE. Это срабатывает до того, как пользователь вставляет что-то в элемент управления HTML, и вы можете изменить содержимое буфера обмена до того, как произойдет вставка.

Вы можете использовать что-то вроде GetClipboardData (RegisterClipboardFormat ("HTML Format")), чтобы получить формат HTML из буфера обмена. Вы можете использовать SetClipboardData для замены данных буфера обмена.

Для вашего использования, если вы видите, что после копирования из Word существует несколько форматов буфера обмена, вы можете просто удалить один из форматов, который вам не нужен. Таким образом, когда HTML-элемент управления завершит вставку, он будет использовать только нужный вам формат.

У меня есть примеры кода, если это необходимо, но они являются частью большого проекта и используют библиотеку VCL Borland для некоторых частей. Мой код проверяет формат CF_BITMAP в буфере обмена и преобразовывает его в формат HTML, используя вместо этого файл PNG. Таким образом, пользователи, которые вставляют снимок экрана в элемент управления, получают изображение PNG меньшего размера вместо огромного файла BMP. Концепция примерно такая же, как вы хотите.

0 голосов
/ 27 декабря 2014

Комплексное решение: вызов ключа Hook Reigster возвращает ложное значение для HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version Vector VML значения.

Пример кода:

typedef DWORD(__stdcall *NtQueryKeyType)(
    HANDLE  KeyHandle,
    int KeyInformationClass,
    PVOID  KeyInformation,
    ULONG  Length,
    PULONG  ResultLength);
NtQueryKeyType sNtQueryKeyPtr = NULL;

std::wstring GetKeyPathFromKKEY(HKEY key)
{
    std::wstring keyPath;
    if (sNtQueryKeyPtr != NULL) {
        DWORD size = 0;
        DWORD result = 0;
        result = sNtQueryKeyPtr(key, 3, 0, 0, &size);
        if (result == STATUS_BUFFER_TOO_SMALL) {
            size = size + 2;
            wchar_t* buffer = new (std::nothrow) wchar_t[size / sizeof(wchar_t)]; // size is in bytes
            if (buffer != NULL)
            {
                result = sNtQueryKeyPtr(key, 3, buffer, size, &size);
                if (result == STATUS_SUCCESS)
                {
                    buffer[size / sizeof(wchar_t)] = L'\0';
                    keyPath = std::wstring(buffer + 2);
                }
                delete[] buffer;
            }
        }
    }
    return keyPath;
}

DWORD __stdcall VWMLNtQueryKey(
    HANDLE  KeyHandle,
    int KeyInformationClass,
    PVOID  KeyInformation,
    ULONG  Length,
    PULONG  ResultLength) {
    auto str = GetKeyPathFromKKEY((HKEY)KeyHandle);
    if (!str.empty() && base::StringProcess::endsWith(str, L"Internet Explorer\\Version Vector"))
        return STATUS_INVALID_PARAMETER;
    return sNtQueryKeyPtr(KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
}

base::WindowsDllInterceptor ntHook;
ntHook.Init("ntdll.dll");
if (!ntHook.AddHook("NtQueryKey", reinterpret_cast<intptr_t>(&VWMLNtQueryKey),
    (void**)&sNtQueryKeyPtr)) {
    removeVMLTags(&html);
}

Пройдите тестирование Windows 8.1 + WORD 2007, но лучше убрать теги VML.

Путь к ключу из дескриптора ключа из: Определение пути к ключу реестра из дескриптора HKEY в C ++

...