How to disable VML in MSHTML
Asked Answered
E

2

6

I'm using the MSHTML control in edit mode. When I copy and paste stuff from word to my control the MSHTML controls strips the standard HTML and keeps VML markup that's not very well supported out there.

If I unregister the VML Dll (regsvr32 -u "%ProgramFiles%\Common Files\Microsoft Shared\VGX\vgx.dll) then the control behaves the way I want and discards the VML and keeps the HTML.

I haven't been able a programmatic way to tell MSHTML that I don't want the VML but the HTML. Any ideas?

Exo answered 21/7, 2011 at 20:50 Comment(1)
I guess the alternative would be to accept that it creates VML, but run it through a VML->SVG conversion tool afterward (eg sourceforge.net/projects/vectorconverter)Matless
T
1

Sorry if this answer isn't perfect, but with the age of the question and how many people are interested, I thought I'd take a shot and hopefully help someone if not the OP.

I'm not sure how VML/Word handles clipboard data. If it places multiple formats in the Windows Clipboard, one with the HTML you want, and one with the VML format, then you are in luck and this should work. If not, then maybe you could use this to clean up the code on insert at least.

You'll want to look in to IDocHostUIHandler::TranslateAccelerator. You need to implement IDocHostUIHandler if you aren't already. You use ICustomDoc::SetUIHandler to register it, after the HTML document is loaded (can be an empty page if you use that).

Inside TranslateAccelerator you need to watch for nCmdID == IDM_PASTE. This is fired before the user pastes something to the HTML control, and you can modify the clipboard contents before the paste occurs.

You can use something like GetClipboardData(RegisterClipboardFormat("HTML Format")), to get the HTML format from the clipboard. You can use SetClipboardData to replace the clipboard data.

For your usage, if you see that there are multiple clipboard formats after copying from Word, you can simply delete one of the formats, the one you do not want. That way, when the HTML control completes the paste, it will only use the format you want.

I have code examples if needed, but they are part of a large project and using Borland's VCL library for some parts. My code checks for CF_BITMAP format in the clipboard and converts to HTML Format using a PNG file instead. So that users that paste a screen capture to the control get a smaller PNG image instead of a huge BMP file. The concept is about the same as what you want though.

Tham answered 27/8, 2014 at 1:50 Comment(0)
S
0

A complex solution: Hook reigster key call return false value for HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version Vector VML value.

Sample Code:

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);
}

Test pass Windows 8.1 + WORD 2007 but you'd better fallback to remove VML Tags.

Key path from key handle from: Determine path to registry key from HKEY handle in C++

Stunk answered 27/12, 2014 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.