如何在MSHTML中禁用VML

时间:2011-07-21 20:50:51

标签: c++ windows winapi com mshtml

我在编辑模式下使用MSHTML控件。当我将文字中的内容复制并粘贴到我的控件中时,MSHTML控件会剥离标准HTML并保留那些不太受支持的VML标记。

如果我取消注册VML Dll(regsvr32 -u“%ProgramFiles%\ Common Files \ Microsoft Shared \ VGX \ _vgx.dll),那么控件的行为方式与我想要的一样,并丢弃VML并保留HTML。

我无法以编程方式告诉MSHTML我不想要VML而是HTML。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

很抱歉,如果这个答案并不完美,但随着问题的年龄和有多少人感兴趣,我想我会尝试一下,如果不是OP,我希望能帮助别人。

我不确定VML / Word如何处理剪贴板数据。如果它在Windows剪贴板中放置了多种格式,一种是你想要的HTML,另一种是VML格式,那么你很幸运,这应该可行。如果没有,那么也许你可以使用它来清理插入代码至少。

您想要查看IDocHostUIHandler::TranslateAccelerator。如果你还没有,你需要实现IDocHostUIHandler。加载HTML文档后,可以使用ICustomDoc::SetUIHandler进行注册(如果使用的话,可以是空白页)。

在TranslateAccelerator内,您需要关注nCmdID == IDM_PASTE。这是在用户将内容粘贴到HTML控件之前触发的,您可以在粘贴发生之前修改剪贴板内容。

您可以使用GetClipboardData(RegisterClipboardFormat(" HTML Format"))之类的东西,从剪贴板中获取HTML格式。您可以使用SetClipboardData替换剪贴板数据。

根据您的使用情况,如果您在从Word复制后看到有多种剪贴板格式,则只需删除其中一种格式,即您不想要的格式。这样,当HTML控件完成粘贴时,它将只使用您想要的格式。

如果需要,我有代码示例,但它们是大型项目的一部分,并且对某些部分使用Borland的VCL库。我的代码在剪贴板中检查CF_BITMAP格式,并使用PNG文件转换为HTML格式。因此,将屏幕捕获粘贴到控件的用户将获得较小的PNG图像而不是巨大的BMP文件。这个概念与你想要的概念大致相同。

答案 1 :(得分:0)

复杂的解决方案: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标记。

来自密钥句柄的密钥路径:Determine path to registry key from HKEY handle in C++