4

HtmlHelpAPI 升级这些 c 样式转换的 c++ 方法是什么?

void CMeetingScheduleAssistantApp::DisplayHelpTopic(CString strTopic)
{
    CString strURL = _T("https://help-msa.publictalksoftware.co.uk/") + strTopic;

    if (theApp.UseDownloadedHelpDocumentation())
    {
        // CHM files use 3 letter suffix
        strTopic.Replace(_T(".html"), _T(".htm"));
        HtmlHelp((DWORD_PTR)(LPCTSTR)strTopic, HH_DISPLAY_TOPIC);
    }
    else
        ShellExecute(nullptr, nullptr, strURL, nullptr, nullptr, SW_SHOWDEFAULT);
}

具体来说:

HtmlHelp((DWORD_PTR)(LPCTSTR)strTopic, HH_DISPLAY_TOPIC);


回答评论中的问题:

在此处输入图像描述

这很奇怪,因为 x86 HtmlHelpA/的官方文档HtmlHelpW确实指出了不同的调用。

它似乎没有被列为CWinApp文档中类的一部分。

4

2 回答 2

4

reinterpret_cast将始终触发代码分析警告

在这种情况下,您可以发明自己的指针转换函数。一个聪明的编译器很可能会优化这个:

#include <cstring>

template<class D, class T>
D ptr_cast(T* x) {
    D rv;
    static_assert(sizeof rv == sizeof x);
    std::memcpy(&rv, &x, sizeof rv);
    return rv;
}

然后

HtmlHelp( ptr_cast<DWORD_PTR>(strTopic.GetString()),
          HH_DISPLAY_TOPIC);

在 g++ 和 clang++ 中,显式实例化函数

template DWORD_PTR ptr_cast<DWORD_PTR,char>(char*);

使其成为汇编代码

unsigned long ptr_cast<unsigned long, char>(char*):
        mov     rax, rdi
        ret

当内联和优化时(就像它在你的代码中一样),函数调用消失了,只剩下mov对目标的(赋值)DWORD_PTR,这正是 areinterpret_cast会留下的痕迹。在 MSVC 中,内联它会产生类似的结果:

lea     rdx, OFFSET FLAT:`string'
于 2021-11-25T18:41:20.623 回答
1

(LPCTSTR)strTopic来电CString::operator LPCTSTR()。然后(DWORD_PTR)将指针 LPCTSTR 转换为 DWORD_PTR。由于源和目标大小不同,无法从 CString 对象直接转换为 DWORD_PTR。

C++ 类型转换可以与 C 类型转换具有相同的短长度

HtmlHelp(DWORD_PTR(LPCTSTR(strTopic)), HH_DISPLAY_TOPIC);

MFC CWnd 和 CWinApp 类具有获取 DWORD_PTR 类型的第一个参数的方法

virtual void HtmlHelp(
    DWORD_PTR dwData,
    UINT nCmd = 0x000F);
于 2021-11-25T17:14:19.413 回答