1

我一直在通过我的应用程序添加OnHelpInfo消息处理程序。这不是因为我的应用程序将支持上下文帮助。相反,我想拦截 F1 键,然后简单地调用现有的“帮助”代码,当按下对话框按钮或菜单项时触发该代码。例子:

#pragma warning (suppress : 26434)
BOOL CBrotherExcludeDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
    OnButtonHelp();

    // return CResizingDialog::OnHelpInfo(pHelpInfo);
    return TRUE;
}

我的问题是属性页。他们使用不同的机制来处理帮助主题的显示。例子:

void CCalendarSettingsGooglePage::OnPsnHelp(NMHDR* hdr, LRESULT* res)
{
    theApp.DisplayHelpTopic(_T("msa-options-calendars.html"));
}

它使用PSN_HELP处理程序。当我添加OnHelpInfo到属性页面时,我现在不确定如何简单地运行该OnPsnHelp事件。我试图避免有两个我打电话的地方DisplayHelpTopic

我们如何直接调用OnPsnHelp(就像我调用帮助按钮单击处理函数)或通过消息调用它?


这是样板代码:

BOOL CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    ASSERT(pResult != NULL);
    NMHDR* pNMHDR = (NMHDR*)lParam;

    // allow message map to override
    if (CDialog::OnNotify(wParam, lParam, pResult))
        return TRUE;

    // don't handle messages not from the page/sheet itself
    if (pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
        return FALSE;

    // handle default
    switch (pNMHDR->code)
    {
    case PSN_SETACTIVE:
        {
            CPropertySheet* pSheet = GetParentSheet();
            if (pSheet != NULL && !(pSheet->m_nFlags & WF_CONTINUEMODAL) && !(pSheet->m_bModeless) && !(pSheet->m_psh.dwFlags & PSH_AEROWIZARD))
                *pResult = -1;
            else
                *pResult = OnSetActive() ? 0 : -1;
        }
        break;
    case PSN_KILLACTIVE:
        *pResult = !OnKillActive();
        break;
    case PSN_APPLY:
        *pResult = OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
        break;
    case PSN_RESET:
        OnReset();
        break;
    case PSN_QUERYCANCEL:
        *pResult = !OnQueryCancel();
        break;
    case PSN_WIZNEXT:
        *pResult = MapWizardResult(OnWizardNext());
        break;
    case PSN_WIZBACK:
        *pResult = MapWizardResult(OnWizardBack());
        break;
    case PSN_WIZFINISH:
        *pResult = reinterpret_cast<LRESULT>(OnWizardFinishEx());       
        break;
    case PSN_HELP:
        SendMessage(WM_COMMAND, ID_HELP);
        break;

    default:
        return FALSE;   // not handled
    }

    return TRUE;    // handled
}

所以我不明白。如果我使用SendMessage(WM_COMMAND, ID_HELP);软件中的响应是一个弹窗Failed to launch help

4

1 回答 1

1

正如您在评论中提到的,您可以OnPsnHelp只使用两个值调用您的函数nullptr,因为该函数实际上并不使用这些参数。但是,如果在您的软件的未来版本中修改了它以使其确实使用这些,则这是自找麻烦。OnPsnHelp

因此,您应该构造一个适当的PSHNOTIFY结构并在您的“代理”调用中传递该结构的地址以及有效的返回码变量的地址OnPsnHelp。该结构的PSHNOTIFY构造非常简单。它只是一个NMHDR结构,后面跟着一个未使用 lParam的项目。

这是一个可能的实现:

BOOL CCalendarSettingsGooglePage::OnHelpInfo(HELPINFO*)
{
    PSHNOTIFY psns;
    psns.lParam = 0; // The docs say this contains no information.
    psns.hdr.hwndFrom = GetParent()->GetSafeHwnd(); // The parent P/Sheet
    psns.hdr.idFrom = IDHELP; // Not sure what this should REALLY be?
    #pragma warning(suppress: 26454) // For: #define PSN_HELP (PSN_FIRST-5)
    psns.hdr.code = PSN_HELP; // One would assume this is the correct code!
    LRESULT result;
    OnPsnHelp(&psns.hdr, &result); // Make the call.
    return TRUE; // Or possibly: return static_cast<BOOL>(result);
}

来自M/S 文档

参数

指向PSHNOTIFY包含通知代码信息的结构的指针。此结构包含一个NMHDR结构作为其第一个成员hdr。此结构的hwndFrom成员NMHDR 包含属性表的句柄。结构的lParam 成员PSHNOTIFY不包含任何信息。


以下是PSHNOTIFYNMHDR结构的定义:

typedef struct _PSHNOTIFY
{
    NMHDR hdr;
    LPARAM lParam;
} PSHNOTIFY, *LPPSHNOTIFY;

typedef struct tagNMHDR
{
    HWND      hwndFrom;
    UINT_PTR  idFrom;
    UINT      code;         // NM_ code
}   NMHDR;
于 2021-11-25T23:02:12.240 回答