FIX: CSplitterWnd Class Does Not Handle All Focus CasesLast reviewed: September 16, 1997Article ID: Q108434 |
1.00 | 1.00WINDOWS | WINDOWS NT kbprg kbfixlist kbbuglist The information in this article applies to:
SYMPTOMSA view displayed in a splitter window (CSplitterWnd) loses focus when the splitter bar is clicked. A user would expect the focus to be returned to the active view when the user stops dragging the splitter bar and releases the mouse button.
CAUSECSplitterWnd::StopTracking() attempts to restore the active view's keyboard focus by calling SetActiveView(pOldActiveView), where pOldActiveView was set to the currently active view on entry to the StopTracking() function. This is supposed to set the keyboard focus to the previously active view. The problem is that SetActiveView() fails to set the keyboard focus in the case where the view passed as a parameter is the same as m_pViewActive--the currently active view. In this case, it is assumed that the keyboard focus is already on the active view, and therefore the SetActiveView() function simply returns. This assumption is incorrect because the splitter bar gains focus, doesn't save and restore it, and yet leaves the frame's active view pointer the same.
RESOLUTIONMicrosoft has confirmed this to be a problem in the Microsoft Foundation Class (MFC) Libraries version 2.0. This problem has been fixed in the MFC Libraries version 2.5, which is included in Visual C++ version 1.5 for Windows. In the fixed code, CSplitterWnd::StopTracking() (in WINSPLIT.CPP) is modified to explicitly set the focus even after calling SetActiveView(). The code is:
if (pOldActiveView == pParent->GetActiveView()) { pParent->SetActiveView(pOldActiveView); // Re-activate. if (pOldActiveView != NULL) pOldActiveView->SetFocus(); // Make sure focus is restored. }You can include this fix into WINSPLIT.CPP and then rebuild the MFC library by following the directions in Appendix B of the "Class Libraries User's Guide" as well as the README.TXT file located in the \MSVC\MFC\SRC directory. Another workaround for the bug is to save and restore the keyboard focus throughout the splitter window's tracking process. This can be done by handling the WM_LBUTTONDOWN and WM_LBUTTONUP messages in the CSplitterWnd class. The following code demonstrates how to accomplish this:
class CMySplit:public CSplitterWnd // derive from it. { public: // This is the pointer to the window that // has focus when the splitter starts resizing. HWND hWndFocus; // ...rest of your declaration. } void CMySplit::OnLButtonDown(UINT nFlags, CPoint point) { //Get CWnd with current focus hWndFocus = ::GetFocus(); // Remember to call the base class handler. CSplitterWnd::OnLButtonDown(nFlags,point); } void CMySplit::OnLButtonUp(UINT nFlags, CPoint point) { //restore focus ::SetFocus(hWndFocus); // Remember to call the base class handler. CSplitterWnd::OnLButtonUp(nFlags,point); }The code above assumes that the focus is being set to one of the windows in the splitter window panes before the OnLButtonDown() handler is called. That is, you probably wouldn't want to set the focus back to some other window outside of the splitter window when the mouse button is released. You could write additional code to check to see if the focus is set to a window in one of the panes by checking the splitter's frame window's m_pActiveView variable.
STATUSThis problem has been reported in Visual C++ version 1.0 for Windows. This problem has been fixed in Visual C++ version 1.5 for Windows and Visual C++ 2.0 32-bit Edition.
MORE INFORMATIONTo demonstrate the problem, perform the following steps:
|
Additional reference words: 1.00 2.00 2.10 splitter focus
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |