MFC: зачем нужен OnCommandHelp и как он работает?

У меня есть простое приложение MFC: диалог с кнопкой. Для них обоих я позвонил SetWindowContextHelpId() и установите их идентификаторы контекста в ненулевые значения.

Также я могу реализовать два обработчика для команд помощи: OnCommandHelp(WPARAM wParam, LPARAM lParam) а также OnHelpInfo(HELPINFO* pHelpInfo),

MSDN пишет следующее о OnCommandHelp:

lParam содержит текущий доступный контекст справки. lParam равен нулю, если контекст справки не был определен

Но в моем случае lParam всегда равен нулю, хотя pHelpInfo от OnHelpInfo(HELPINFO* pHelpInfo) обработчик содержит правильную ненулевую информацию о Context ID элемента управления (он был установлен путем вызова SetWindowContextHelpId).

Теперь у меня есть два вопроса:

1) Почему lParam всегда ноль? Что означает замечание MSDN об "определении контекста справки"? Что такое "доступный в настоящее время контекст справки"?

2) Зачем нам нужно OnCommandHelpесли мы можем использовать OnHelpInfo?

Любое объяснение будет оценено.

ОБНОВИТЬ:

#include <afxwin.h>
#include <afxpriv.h>

#define ID_BUTTON 125

#define FRAME_HELP 4000
#define BUTTON_HELP 5000

class CMainWnd : public CFrameWnd
{
public:
    CMainWnd();
protected:
    afx_msg LRESULT OnCommandHelp(WPARAM wParam, LPARAM lParam);
    afx_msg int OnCreate(LPCREATESTRUCT lpcs);
    DECLARE_MESSAGE_MAP()
private:
    CButton btn;
};

BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
    ON_WM_CREATE()
    ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
END_MESSAGE_MAP()

int CMainWnd::OnCreate(LPCREATESTRUCT lpcs)
{
    int res = CFrameWnd::OnCreate(lpcs);

    m_nIDHelp = FRAME_HELP;
    SetWindowContextHelpId(FRAME_HELP);

    CRect rc(0, 0, 100, 100);

    btn.Create(_T("Button"), WS_CHILD | WS_VISIBLE, rc, this, ID_BUTTON);

    btn.SetWindowContextHelpId(BUTTON_HELP);

    return res;
}

LRESULT CMainWnd::OnCommandHelp(WPARAM wParam, LPARAM lParam)
{
    wchar_t arr[20];
    _itow_s(lParam, arr, 10);
    MessageBox(arr);
    return TRUE;
}

CMainWnd::CMainWnd()
{
    Create(NULL, _T("Just a frame"));
}

class CApp : public CWinApp
{
public:
    virtual BOOL InitInstance() override;
    DECLARE_MESSAGE_MAP()
};

BEGIN_MESSAGE_MAP(CApp, CWinApp)
    ON_COMMAND(ID_HELP, OnHelp)
    ON_COMMAND(ID_HELP_FINDER, OnHelpFinder)
    ON_COMMAND(ID_HELP_INDEX, OnHelpIndex)
    ON_COMMAND(ID_HELP_USING, OnHelpUsing)
END_MESSAGE_MAP()

BOOL CApp::InitInstance()
{
    m_pMainWnd = new CMainWnd();
    m_pMainWnd->ShowWindow(m_nCmdShow);
    m_pMainWnd->UpdateWindow();

    return TRUE;
}

CApp App;

1 ответ

Самый простой способ понять вложение функций - это установить точки останова для CDialog::OnCommandHelp и CWnd::OnHelpInfo.

Сначала WM_HELPINFO отправляется в окно. Реализация по умолчанию в CWnd:: OnHelpInfo может обрабатывать это, и в дальнейшем вызывается OnCommandHelp. Здесь используется m_nIDHelp и запускается экран справки.

Если вы обрабатываете все вещи в обработчике OnHelpInfo самостоятельно, вызов OnCommandHelp не вызывается...

Фактически эта сложная структура является пережитком тех времен, когда у нас не было SetWindowContextHelpId.

Когда у меня нормальный диалог и я нажимаю, F1 я получаю вызов OnCoammandHelp, а lParam никогда не равен 0! Может быть потому, что я не работаю с OnHelpInfo. Если вы используете OnHelpInfo, контекст уже определен... причины, по которой вы это сделали, обработав OnHelpInfo.

Другие вопросы по тегам