PRB: Controls in Toolbars Refuse to Give the Focus to ViewsLast reviewed: July 22, 1997Article ID: Q134763 |
1.50 1.51 1.52
WINDOWS
kbprg kbui kbprb kbcode
The information in this article applies to:
SYMPTOMSIn an MFC application, controls added to a toolbar may prevent the input focus from returning to the active view. For example, when a user clicks a combo box or edit control in a toolbar and then clicks a view, the control retains the input focus. This happens for any CControlBar-derived class containing a control that can accept the input focus. This behavior does not exist for views derived from CFormView or CEditView.
CAUSEWhen MFC reactivates an already active view, it does not set the input focus to the view. As a result, any control in the toolbar which has the input focus retains the focus.
RESOLUTION
For Single Document Interface (SDI) applicationsTo overcome this behavior when you are writing a Single Document Interface (SDI) application, you must handle the case of a mouse click in the client area (the view itself) of the main window. You need to override OnMouseActivate() in your CView-derived class. To do this, be sure to add an ON_WM_MOUSEACTIVATE() entry to your message map. ClassWizard displays WM_MOUSEACTIVATE in the Messages list if you first choose the Class Info tab and change your Message Filter to "Window." In the code for OnMouseActivate(), call the base class implementation first, and save the result. If the result is MA_ACTIVATE or MA_ACTIVATEANDEAT, then call OnActivateView(). Return the result you saved from your call to the base class. The following code demonstrates this:
int CMyView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) { // Call the base class to get a return value int nResult = CView::OnMouseActivate(pDesktopWnd, nHitTest, message); if (nResult == MA_ACTIVATE || nResult == MA_ACTIVATEANDEAT) { OnActivateView(TRUE, this, this); } return nResult;}
For Multiple Document Interface (MDI) ApplicationsIf you are writing a Multiple Document Interface (MDI) application, there are two ways a view might be reactivated. You must handle both to overcome the focus behavior. To handle the case of a mouse click in a non-client part of the MDI child window, override OnMouseActivate() in your CMDIChildWnd-derived class. To do this, be sure to add an ON_WM_MOUSEACTIVATE() entry to your message map. ClassWizard will display WM_MOUSEACTIVATE in the Messages list if you first choose the Class Info tab and change your Message Filter to "Window." In the code for OnMouseActivate(), call the base class implementation first, and save the result. Then call SetFocus(), and return the result you saved from your call to the base class. The following code demonstrates this:
int CMyMDIChildWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) { // Call the base class FIRST to get a return value for later int nResult = CMDIChildWnd::OnMouseActivate(pDesktopWnd, nHitTest, message); // Correct for focus not being set in // CMDIChildWnd::OnMouseActivate() SetFocus(); return nResult;} To handle the case of choosing the already-checked item for the MDI child window from the application's Window menu, override OnCommand() for your CMainFrame class. Call the base class implementation first, and save the result. Then determine that the menu item ID you are passed is for an MDI child window, that it is your own MDI child, which should be active, and that you are of the runtime class CView. If all of that is true, then call SetFocus, and return the value you saved from your call to the base class. The following code, adapted from the MFC source for CMDIFrameWnd::OnCommand(), demonstrates how to do this: BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) { // Call the base class FIRST to get a return value for later BOOL bRet = CMDIFrameWnd::OnCommand(wParam, lParam); ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00); // If the correct part of lParam is NULL, this message was sent // because a menu item was chosen with the mouse or the keyboard if (LOWORD(lParam) == NULL && (LOWORD(wParam) & 0xf000) == 0xf000) { ASSERT_VALID(MDIGetActive(NULL)); // Do this ONLY for a CView-derived class if ((GetFocus()->GetParentFrame() != MDIGetActive(NULL)) && (MDIGetActive(NULL)->GetActiveView()-> IsKindOf(RUNTIME_CLASS(CView)))) { SetFocus(); } } return bRet;}
STATUSThis behavior is by design.
REFERENCESFor information on how to add a control, such as an edit or combo box, to a toolbar, please see the CTRLBARS sample application shipped with Microsoft Visual C++.
|
Additional reference words: 1.50 1.51 1.52 2.50 2.51 2.52
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |