Menu

Q: why PreTranslateMessage result is ignored in CDialog::StaticMsgHook?

Help
2015-01-10
2015-01-13
  • Daniel Pantea

    Daniel Pantea - 2015-01-10

    Hi David,
    thank you for still maintaining this framework. Really lite and cool.

    I have small problem in a modal dialog which uses an accelerator table to process some user-inputs (ex: Ctrl+O, Ctrl+P, Ctrl+F and Ctrl+I). The same dialog has some static labels with ampersand letters so Alt+O, Alt+P, Alt+F and Alt+I would jump to their associated controls.

    The problem is that after I press Ctrl+<Letter> it's correctly parsed by PreTranslateMessage which translates into the associated command:

    BOOL CEditorDlg::PreTranslateMessage(MSG* pMsg)
    {
    // This functions is called by the MessageLoop. It processes the
    // keyboard accelerator keys and calls CWnd::PreTranslateMessage for
    // keyboard and mouse events.
    
    // only pre-translate mouse and keyboard input events
    if ((pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) ||
        (pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST))
    {
        // Process keyboard accelerators
        int t = ::TranslateAccelerator(GetHwnd(), m_hAccelTable, pMsg);
        if (t)
        {
            return TRUE; // I did check that it returns TRUE here as expected
        }
    }
    
    return CDialog::PreTranslateMessage(pMsg);
    }
    

    However after the command is handled the code returns into CDialog::StaticMsgHook where the result of pDialog->PreTranslateMessage(lpMsg) is ignored. Is this intended?
    In my case because of this the key pressing is translated later in WM_CHAR messages which gets sent to the dialog and interpreted as the ampersand key presses (as Alt+<Letter> would do) therefore the focus jumps and if somehow an edit control gets the focus then its content will be later overwritten with the pressed <Letter>.

    I managed to fix the "misbehavior" by changing the mentioned CDialog::StaticMsgHook as follow:

    CDialog* pDialog = static_cast<CDialog*>(FromHandlePermanent(hWnd));
    if (pDialog && (lstrcmp(pDialog->GetClassName(), _T("#32770")) == 0))   // only for dialogs
    {
        if(pDialog->PreTranslateMessage(lpMsg)) return 1;
        break;
    }
    

    Is this patch correct? I didn't see any side-effects till now.
    Also I saw that in CWinThread::MessageLoop() there is a similar approach that if PreTranslateMessage did the job then DispatchMessage is not made anymore.
    Also in MFC the CWnd::PreTranslateMessage the return value has similar description "Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.".
    Please let me know if you think I should use other approach or if I can avoid other way the handled accelerators being also processed as WM_CHARs messages. I'm using the latest Win32++ SVN revision 1908, with VC++ 2010 on Win7 x64.

    Thank you,
    Daniel

     
  • David

    David - 2015-01-13

    Hi Daniel,

    Thanks for your suggested patch to CDialog::StaticMsgHook.

    I believe the approach you've suggested is correct, and I've updated the code accordingly. The updated code was submitted in SVN Revision 1909.

    Best regards,
    David

     

Log in to post a comment.