15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Modal Dialog's PreTranslateMessage and MainFrame Accelerator

Jeff Bondono -- bondono@eaglequest.com
Tuesday, January 28, 1997

Environment: VC++ 4.2b, Win 95

Knowledge base article Q117500 says that to have my mainframe
accerators continue working while a modeless diaog is up, I need:

   BOOL CModeless::PreTranslateMessage(MSG* pMsg)
   {
      HACCEL hAccel =3D
             ((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetAccelTable();
      if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))
         return CDialog::PreTranslateMessage(pMsg);
      else
         return TRUE;
   }
=20
I find that I need to return FALSE in the last line or the
accelerators do not work.  Anybody have any idea what I'm doing wrong?

TIA,
Jeff



Jeff Bondono -- bondono@eaglequest.com
Tuesday, January 28, 1997

Environment: VC++ 4.2b, Win 95

Knowledge base article Q117500 says that to have my mainframe
accerators continue working while a modeless diaog is up, I need:

   BOOL CModeless::PreTranslateMessage(MSG* pMsg)
   {
      HACCEL hAccel =3D
             ((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetAccelTable();
      if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))
         return CDialog::PreTranslateMessage(pMsg);
      else
         return TRUE;
   }
=20
I find that I need to return FALSE in the last line or the
accelerators do not work.  Anybody have any idea what I'm doing wrong?

TIA,
Jeff



Yuriy Briklin -- ybriklin@juno.com
Wednesday, January 29, 1997

[Mini-digest: 2 responses]

Hi Jeff.

I think you are doing everything right. It is an error in the article.
You should return FALSE in the last line
to tell that the message was not translated and should be dispatched (see
help for CWnd::PreTranslateMessage).

BTW: I have another solution to your problem. It doesn't require
overriding of PreTranslateMessage in each modeless dialog.
Instead you should override this function in your WinApp class. I did it
like this:

BOOL CMyApp::PreTranslateMessage( MSG* pMsg )
{
   if(NULL == pMsg)
      return CWinApp::PreTranslateMessage(pMsg);
   
   if (  (pMsg->message == WM_SYSKEYDOWN) ||
         (pMsg->message == WM_SYSKEYUP)   ||
         (pMsg->message == WM_SYSCHAR)    )
   {
      CWnd* pMainWnd = AfxGetMainWnd();

      if((NULL == pMainWnd)||(!IsWindow(pMainWnd->m_hWnd)))
	return CWinApp::PreTranslateMessage(pMsg);

      //For System Keys pass control to the Main Window (mainframe
accelerators will get a chance to process this message first)
      pMsg->hwnd = AfxGetMainWnd()->m_hWnd;
   }

   return CMSSApp::PreTranslateMessage(pMsg);
}

This code works for me with modeless PropertySheets and I think it will
fork with modeless dialogs as well.

Yuriy Briklin


On Tue, 28 Jan 1997 07:02:30 -0500 bondono@eaglequest.com (Jeff Bondono)
writes:
> Environment: VC++ 4.2b, Win 95
> 
> Knowledge base article Q117500 says that to have my mainframe
> accerators continue working while a modeless diaog is up, I need:
> 
>    BOOL CModeless::PreTranslateMessage(MSG* pMsg)
>    {
>       HACCEL hAccel =3D
>              ((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetAccelTable();
>       if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))
>          return CDialog::PreTranslateMessage(pMsg);
>       else
>          return TRUE;
>    }
> =20
> I find that I need to return FALSE in the last line or the
> accelerators do not work.  Anybody have any idea what I'm doing 
> wrong?
> 
> TIA,
> Jeff
> 
-----From: Vijai Singh 


  if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))   

  in thie above line instead of m_hWnd(this windows handle) the handle
  should be of the mainFrame window

                                    @ @
    +===========================ooO-(_)-Ooo==============================+
    | Vijai Singh                                                        |
    |                                                                    |
    | E-Mail : vsingh@m-net.arbornet.org                                 |
    |          vsingh@grex.cyberspace.org                                |
    | Phone  :                                                           |
    | Res    : (916) 852-8717                                            |
    | Wrk    : (916) 939-6038                                            |
    +====================================================================+

On Tue, 28 Jan 1997, Jeff Bondono wrote:

> Environment: VC++ 4.2b, Win 95
> 
> Knowledge base article Q117500 says that to have my mainframe
> accerators continue working while a modeless diaog is up, I need:
> 
>    BOOL CModeless::PreTranslateMessage(MSG* pMsg)
>    {
>       HACCEL hAccel =
>              ((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetAccelTable();
>       if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))
>          return CDialog::PreTranslateMessage(pMsg);
>       else
>          return TRUE;
>    }
>  
> I find that I need to return FALSE in the last line or the
> accelerators do not work.  Anybody have any idea what I'm doing wrong?
> 
> TIA,
> Jeff
> 




Kostya Sebov -- sebov@is.kiev.ua
Saturday, February 01, 1997

>   Environment: VC++ 4.2b, Win 95
>
>   Knowledge base article Q117500 says that to have my mainframe
>   accerators continue working while a modeless diaog is up, I need:
>
>      BOOL CModeless::PreTranslateMessage(MSG* pMsg)
>      {
>         HACCEL hAccel =3D
>                ((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetAccelTable();
>         if(!(hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg)))
>            return CDialog::PreTranslateMessage(pMsg);
>         else
>            return TRUE;
>      }
>   =20
>   I find that I need to return FALSE in the last line or the
>   accelerators do not work.  Anybody have any idea what I'm doing wrong?
>
>
The PreTranslateMessage is just what its name implies -- it's "...used by class CWinApp to translate window messages before they are dispatched to the TranslateMessage and DispatchMessage Windows functions." (I quote from the VC documentation).

Paul DiLascia's article in the MSJ #7 1995 is an excellent description of its purpose in particular and overall MFC message routing architecture.

In short, PreTranslateMessage provides a means of "global processing" of the message stream. For instance,
modeless dialog's implementation calls IsDialogMessage to interpret particular WM_KEY*** messages that have special meaning to the dialogs (e.g. pressing a tab).

The very first time MFC gives a chance of such processing to the CWnd objects representing the window whom
a particular message is aimed at. The objects indicates if it has processed the message by the return value from the method. If it has not (FALSE) MFC tries its parent, then its "grandparent" and so on up to the top-level window
and finally the CWinThread object owning the message loop until someone in the chain returns TRUE, in which case the search is stopped and the message is considered processed. If all of them give up (return FALSE) the
::TranslateMessage/::DispatchMessage duet takes on their responsibilities.

In your case you're going to _augment_ the CDialog message stream  processing with the accelerator translation
that is watch for the keystrokes messages that correspond to the accelerator table and injecting extra WM_COMMANDs into the stream. So your code should look like:

BOOL CYourDialog::PreTranslateMessage(MSG* pMsg)
{
    if( CDialog::PreTranslateMessage(pMsg))
        return TRUE; // CDialog HAS recognized and processed the message --
                    //  we cannot do anything else
    if( m_hAccel    // The accelerator does exist
         && ::TranslateAccelerator( m_hWnd, m_hAccel, pMsg ) // ...and the message _is_ understood by the
                                // and has been processed accelerator
     )
        return TRUE; // Don't call ::Translate/::DispatchMessage -- we've already done everything with the pMsg
    return FALSE; // Give someone else a try or route the message normally
}

HTH,

--- 
Kostya Sebov. 
----------------------------------------------------------------------------
Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua




| Вернуться в корень Архива |