Accelerators for Dialog Buttons?
Ivo Rothschild -- ivo@amber.hasc.ca Wednesday, January 31, 1996 Hello All: I've looked in the books, the kb, and even asked Microsoft tech support and I've been unable to come up with a satisfactory answer. I have a button in a modeless dialog that I want to be pressed when the key F3 is pressed. (In fact I don't care if the button is actually pressed - I just need a message sent to my CDialog subclass.) I can have multiple instances of these dialogs around. I tried: 1. adding an entry in the accelerator table which didn't work. 2. Making a menu item with accelerator F3 and mapping it to my dialog. 3. Making a menu item with accelerator F3 and mapping it to my MainFrame. Then mapping the message OnSetFocus() and OnKillFocus() in my dialog, and from there telling the MainFrame which dialog has focus. This was suggested by Microsoft tech support and it doesn't work because the Dialog doesn't get the OnSetFocus and OnKillFocus messages. 4. Similar to 2 but mapping OnActivate() in the dialog. This doesn't work either because when the user clicks on the menu, my dialog loses activation. Is there a simple way to do this? Is there any nice way to do this? Do I have to keep an ordered list of all my dialog instances so I can dispatch the F3 key message to the right one? Thanks, -ivo ivo@hasc.ca
John Simmons -- jms@connectnet.com Thursday, February 01, 1996 [Mini-digest: 2 responses] At 07:51 PM 1/31/96 -0500, you wrote: > >Hello All: > >I've looked in the books, the kb, and even asked Microsoft tech >support and I've been unable to come up with a satisfactory answer. > >I have a button in a modeless dialog that I want to be pressed when >the key F3 is pressed. (In fact I don't care if the button is >actually pressed - I just need a message sent to my CDialog >subclass.) I can have multiple instances of these dialogs around. > >I tried: > >1. adding an entry in the accelerator table which didn't work. > >2. Making a menu item with accelerator F3 and mapping it to my dialog. > >3. Making a menu item with accelerator F3 and mapping it to my >MainFrame. Then mapping the message OnSetFocus() and OnKillFocus() >in my dialog, and from there telling the MainFrame which dialog has >focus. This was suggested by Microsoft tech support and it doesn't >work because the Dialog doesn't get the OnSetFocus and OnKillFocus >messages. > >4. Similar to 2 but mapping OnActivate() in the dialog. This >doesn't work either because when the user clicks on the menu, my >dialog loses activation. > >Is there a simple way to do this? Is there any nice way to do this? >Do I have to keep an ordered list of all my dialog instances so I >can dispatch the F3 key message to the right one? > I had to pre-capture keypressed PGUP, PGDN, and F1 in an app I did, and this is the code I used to do it (whittled down to accomodate your needs). Hope it helps. put this in the header file where the dialog box class is defined: const UINT KEY_F3 = 250; // arbitrary number, any value will do... class CMyDialog { private: FARPROC lpfnFilterProc; static HHOOK HookID; HINSTANCE hInst; static DWORD CALLBACK KeystrokeHook(int nCode, WORD wParam, LONG lParam); ... }; put this in the cpp file where the class is implemented: BEGIN_MESSAGE_MAP(CFamilyDlg, CDialog) //{{AFX_MSG_MAP(CFamilyDlg) ON_MESSAGE(WM_KEYSTROKE,OnKeystroke) ... ... ... other message map functions here ... ... //}}AFX_MSG_MAP END_MESSAGE_MAP() HHOOK CMyDialog::HookID=0; //-----------------------------------------------------------------------------/ BOOL CMyDialog::OnInitDialog() { CDialog::OnInitDialog(); LPDWORD processid = 0; HookID = SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)CMyDialog::KeystrokeHook, theApp.m_hInstance, GetWindowThreadProcessId(m_hWnd, processid)); ... ... ... other dialog box initialization here (if needed) ... ... return TRUE; } LONG CMyDialog::OnKeystroke(UINT wParam, LONG lParam) { switch (toupper(wParam)) { case KEY_F3 : OnPressedF3(); return 1L; default : break; } return 1L; } DWORD CALLBACK CMyDialog::KeystrokeHook(int nCode, WORD wParam, LONG lParam) { if (nCode < 0) return CallNextHookEx((HHOOK) HookID, nCode, wParam, lParam); if (nCode == MSGF_DIALOGBOX) { MSG FAR *ptrMsg = (MSG FAR *)lParam; if (WM_KEYDOWN == ptrMsg->message) { switch (ptrMsg->wParam) { case VK_F3: ::PostMessage(::GetParent(ptrMsg->hwnd), WM_KEYSTROKE,KEY_F3,lParam); return 1L; } } } return 0L; } void CMyDialog::OnPressedKeyF3() { ... ... ... code to handle F3 key being pressed ... ... } /=========================================================\ | John Simmons (Redneck Techno-Biker) | | jms@connectnet.com | | Home Page | | www2.connectnet.com/users/jms/ | |---------------------------------------------------------| | ViewPlan, Inc. home page (my employer) | | www.viewplan.com/index.html | |---------------------------------------------------------| | IGN #3 American Eagle Motorsports Zerex Ford | | Teammates - Steve Stevens (#13 Hooters Ford and | | 1995 IGN Points Champ) | | Pat Campbell (#95 Dr. Pepper Ford) | | American Eagle Motorsports Team Page | | www2.connectnet.com/users/jms/ignteam | |---------------------------------------------------------| | Competitor - Longest Signature File On The Net | \=========================================================/ -----From: "Nick Gall"On 31 Jan 96 at 19:51, Ivo Rothschild wrote: > > Hello All: > > I've looked in the books, the kb, and even asked Microsoft tech > support and I've been unable to come up with a satisfactory answer. > > I have a button in a modeless dialog that I want to be pressed when > the key F3 is pressed. (In fact I don't care if the button is > actually pressed - I just need a message sent to my CDialog > subclass.) I can have multiple instances of these dialogs around. Is the following KB article what you are looking for? I found it by doing a search for "Accelerators and Modeless" with the VC++ 4.0 Infoviewer. -- Nick Using Accelerators with an MFC Modeless Dialog Box PSS ID Number: Q117500 Article last modified on 05-25-1995 1.00 1.50 1.51 1.52 | 1.00 2.00 2.10 WINDOWS | WINDOWS NT ---------------------------------------------------------------------- The information in this article applies to: - The Microsoft Foundation Classes (MFC) included with: - Microsoft Visual C++ for Windows, versions 1.0, 1.5, 1.51, and 1.52 - Microsoft Visual C++ 32-bit Edition, version 1.0, 2.0, and 2.1 ---------------------------------------------------------------------- SUMMARY ======= To use accelerators with a modeless dialog box, override the function "PreTranslateMessage()" in your derived CDialog class. MORE INFORMATION ================ To use accelerators with your modeless dialog box, perform the following steps: 1. Create a modeless dialog box. For additional information, please see the following article in the Microsoft Knowledge Base: ARTICLE-ID: Q103788 TITLE : Creating a Modeless Dialog Box with MFC Libraries 2. Insert this sample code into the files listed above the code: // .H file with your derived CDialog class class CModeless : public CDialog { . public: virtual BOOL PreTranslateMessage(MSG*); . }; //.CPP file 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; } // MAINFRM.H file, where CMainFrame is the main window class HACCEL CMainFrame::GetAccelTable() { return m_hAccelTable; } 3. Create the accelerators with App Studio. The accelerators should be in the IDR_MAINFRAME accelerator table. They should also have the same ID as the controls or menu items with which they are associated. Additional reference words: kbinf 1.00 1.50 1.51 1.52 2.00 2.10 2.50 2.51 2.52 3.00 3.10 KBCategory: kbprg KBSubcategory: MfcUI ====================================================================== Copyright Microsoft Corporation 1995.
David W. Gillett -- DGILLETT@expertedge.com Friday, February 02, 1996 > I've looked in the books, the kb, and even asked Microsoft tech > support and I've been unable to come up with a satisfactory answer. > > I have a button in a modeless dialog that I want to be pressed when > the key F3 is pressed. (In fact I don't care if the button is > actually pressed - I just need a message sent to my CDialog > subclass.) I can have multiple instances of these dialogs around. Things may have changed since MFC 2.x, but in that version there were four or maybe five implementations of PreTranslateMessage() in the source (which you have...). The version supplied by CDialog for modeless dialogs was the only one that did not implement accelerators. So what I did when I ran into a version of this problem was overide that function in my CDialog-derived class, stealing the code from the source and adding the one or two lines needed, stolen from one of the other versions in the source. [I don't *think* there was any private implementation-only detail in the code I borrowed, but this sort of thing needs documenting as a possible issue in porting to future versions....] Dave
| Вернуться в корень Архива |