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 Singhif(!(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
| Вернуться в корень Архива |