visual-c++mfcdialogacceleratorkeymodeless-dialog

Accelerator keys not working when modeless popup has the focus


My main CDialog sometimes displays a child modeless dialog like this:

enter image description here

It is only displayed if the user has configured it to automatically display.


It gets displayed via the main dialogs OnInitDialog where this function is called:

void CChristianLifeMinistryEditorDlg::DisplayAssignHistoryDialog()
{
    BOOL    bShowAssignHistoryDialog;
    bShowAssignHistoryDialog = theApp.GetNumberSetting(_T("Options"), _T("SM_ShowAssignHist"), TRUE);
    if (bShowAssignHistoryDialog)
    {
        m_pAssignHistoryDlg = std::make_unique<CAssignHistoryDlg>(); // .release();
        if (m_pAssignHistoryDlg != nullptr)
        {
            m_pAssignHistoryDlg->SetAssignHistMap(&m_mapSPtrHist, &m_HistoryOriginal);
            m_pAssignHistoryDlg->Create(IDD_DIALOG_ASSIGN_HISTORY, this);
            m_pAssignHistoryDlg->ShowWindow(SW_SHOWNORMAL);
            m_pAssignHistoryDlg->UpdateWindow();
            m_pAssignHistoryDlg->EnableTree(false);
        }
    }
}

WhatI have noticed is that some of my main windows ACCELERATOR hotkey keys don't always work. I then realised that this is because the popup window has the focus. If i single click anywhere on the main dialog to give it focus, then my accelerator hotkeys function.


Is there any way that we can easily still allow the main editor to process it's hotkeys even though the modeless window might have focus? A standard way to cater for this?


The main window handles the accelerators like this:

BOOL CChristianLifeMinistryEditorDlg::PreTranslateMessage(MSG * pMsg)
{
    if (m_hAccelTable)
    {
        if (::TranslateAccelerator(GetSafeHwnd(), m_hAccelTable, pMsg))
            return TRUE;
    }
}

And the popup modeless window also makes use of PreTranslateMessage (incase it is relevant):

BOOL CAssignHistoryDlg::PreTranslateMessage(MSG* pMsg)
{
    BOOL    bNoDispatch{}, bDealtWith = bDealtWith = FALSE ;

    if ( (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP || 
        pMsg->message == WM_CHAR) 
        && pMsg->wParam == VK_RETURN)
    {
        // Eat it.
        bNoDispatch = TRUE ;
        bDealtWith = TRUE ;
    }

    if (!bDealtWith)
        bNoDispatch = CResizingDialog::PreTranslateMessage(pMsg);

    return bNoDispatch ;
}

Solution

  • I would pass your m_hAccelTable from CChristianLifeMinistryEditorDlg to CAssignHistoryDlg and add this to the beginning of CAssignHistoryDlg::PreTranslateMessage:

    if (m_hAccelTable)
    {
        if (::TranslateAccelerator(GetParent()->GetSafeHwnd(), m_hAccelTable, pMsg))
            return TRUE;
    }