Вызов TrackPopupMenu () после нажатия клавиши пробела на CLinkCtrl вызывает звуковой сигнал предупреждения.Зачем? - PullRequest
0 голосов
/ 20 декабря 2018

Потерпи меня.Я должен дать вам мои настройки.

У меня есть диалоговое окно с элементом управления syslink ( CLinkCtrl ):

enter image description here

, который можно щелкнуть для отображения контекстного меню.

Сейчас я пытаюсь настроить опцию доступности, чтобы пользователь нажимал пробел или нажимал клавишу ввода на клавиатуре, чтобыотобразить это контекстное меню:

enter image description here

Я использую уведомление NM_RETURN для этого:

LRESULT CTestMfcLinkCtrlDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // TODO: Add your specialized code here and/or call the base class

    if(message == WM_NOTIFY)
    {
        NMHDR* pNmhdr = (NMHDR*)lParam;
        if(pNmhdr->code == NM_RETURN)
        {
            showMenu();
        }
    }

    return CDialogEx::WindowProc(message, wParam, lParam);
}

и менюСамо это выглядит следующим образом:

void CTestMfcLinkCtrlDlg::showMenu()
{
    HMENU hMMenu = LoadMenu(GetModuleHandle(NULL),
        MAKEINTRESOURCE(IDR_MENU1));
    HMENU hMenu = GetSubMenu(hMMenu, 0);

    if(hMenu)
    {
        HWND hParentWnd = this->GetSafeHwnd();

        CWnd* pW = this->GetDlgItem(IDC_SYSLINK1);
        CRect rcW;
        pW->GetWindowRect(&rcW);

        UINT iCmdRes = ::TrackPopupMenu(hMenu, 
            TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON | 
            TPM_VERPOSANIMATION | TPM_HORPOSANIMATION | TPM_RETURNCMD, 
            rcW.left, rcW.bottom, 
            0, hParentWnd, NULL);

        switch(iCmdRes)
        {
            //...
        }

    }

    DestroyMenu(hMMenu);
}

IDR_MENU1 взято из ресурсов:

enter image description here

Так что же происходит: если элемент управления system-link имеет фокус клавиатуры, нажмите клавишу пробела или клавишу ввода (возврата) на клавиатуре.Будет отображено мое контекстное меню, но в то же время вы услышите звуковой сигнал, похожий на параметр MB_ICONWARNING.Я выполнил некоторую отладку, и этот сигнал звучит из звонка TrackPopupMenu.

Есть идеи, как он это делает и как предотвратить этот предупреждающий сигнал?

Вот ссылка *Решение MFC от 1044 * до VS2017, на котором я его тестировал.

1 Ответ

0 голосов
/ 20 декабря 2018

Всплывающее меню открывается в ответ на сообщение WM_CHAR.Кажется, меню открывается до полной обработки WM_CHAR.Таким образом, всплывающее меню получает то же самое сообщение WM_CHAR.Меню не знает, что делать с этой клавишей, и жалуется на раздражающий звуковой сигнал.

Если вы нажмете пробел, когда меню открыто, вы услышите тот же звуковой сигнал.

Решение, сначала запустите функцию по умолчанию:

LRESULT CMyDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT lres = CDialogEx::WindowProc(message, wParam, lParam);

    if(message == WM_NOTIFY)
    {
        NMHDR* pNmhdr = (NMHDR*)lParam;
        if(pNmhdr->code == NM_RETURN)
        {
            showMenu();
        }
    }

    return lres;
}

Или, сделайте это в ответ на ON_NOTIFY, но обязательно удалите сообщение из цепочки, используя

PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_REMOVE);

Пример:

void CMyDialog::showMenu()
{
    CMenu menu;
    menu.LoadMenu(IDR_MENU1);
    ASSERT(menu.GetSafeHmenu());
    CMenu *popup = menu.GetSubMenu(0);
    ASSERT(popup);

    CRect rc;
    CWnd *syslink = GetDlgItem(IDC_SYSLINK1);
    ASSERT(syslink);
    syslink->GetWindowRect(&rc);

    MSG msg;
    if (::PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE))
        AfxGetThread()->PumpMessage();

    UINT iCmdRes = popup->TrackPopupMenu(
            TPM_TOPALIGN | TPM_LEFTALIGN | TPM_LEFTBUTTON |
            TPM_VERPOSANIMATION | TPM_HORPOSANIMATION | TPM_RETURNCMD,
            rc.left, rc.bottom, this);

    switch(iCmdRes)
    {
        //...
    }
}
...