PRB: Focus/Activation Problems with MFC Control on VB Forms (192347)
The information in this article applies to:
- Microsoft Visual Basic Learning Edition for Windows 5.0
- Microsoft Visual Basic Learning Edition for Windows 6.0
- Microsoft Visual Basic Professional Edition for Windows 5.0
- Microsoft Visual Basic Professional Edition for Windows 6.0
- Microsoft Visual Basic Enterprise Edition for Windows 5.0
- Microsoft Visual Basic Enterprise Edition for Windows 6.0
- Microsoft Visual C++, 32-bit Enterprise Edition 5.0
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 5.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
This article was previously published under Q192347 SYMPTOMS
You have an ActiveX control created in Visual C++ using the Microsoft
Foundation Classes (MFC). When two of these controls reside on different
Visual Basic MDI child forms, and you attempt to switch from one form to
another by clicking on the controls, focus shifts to the control, but the
expected Activate/Deactivate form events do not occur. Code in the events
does not run, and the Active Title Bar does not switch as expected. Under Windows 2000, the Activate/Deativate form events do fire as expected, but the Active Title Bar still does not switch as expected.
CAUSE
Windows MDI child activation is based on the MDI client window getting the
WM_PARENTNOTIFY message. A control created in MFC has a window style of
WS_EX_NOPARENTNOTIFY by default. This suppresses the parent notification
message, causing the problem described above.
RESOLUTION
To resolve this problem, change the window style of the control. There are
two ways to accomplish this. Resolution #1 requires alteration of the
control's source code. It is the recommended solution, but does require
source code access. Resolution #2 presents a way to resolve this situation
in the Visual Basic client application. Resolution #2 has one requirement:
The control must expose an hWnd property.
NOTE: The hWnd property is a stock property of an MFC control, but by
default it is private to the control.
If you do not have access to the control's source code, and the hWnd
property has not been exposed, then neither of these solutions works.
Resolution #1
Change the window style of the control in PreCreateWindow. This example
uses a hypothetical control named CPushCtrl, derived from the button class.
Sample Code
BOOL CPushCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = _T("BUTTON");
cs.style |= BS_PUSHBUTTON | BS_OWNERDRAW;
// The next statement allows the Visual Basic Child forms to get
// focus correctly.
if (cs.dwExStyle & WS_EX_NOPARENTNOTIFY)
cs.dwExStyle -= WS_EX_NOPARENTNOTIFY;
return COleControl::PreCreateWindow(cs);
}
Resolution #2
If it is not possible to change the code for the control, you can use the
Win32 API from the Visual Basic client to change this value.
- Add the following code to a BAS module, and add the module to any
project that uses the ActiveX control:
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Sub fixWindowStyle(handle As Long)
Dim ret As Long
Dim b As Boolean
ret = GetWindowLong(handle, -20)
ret = ret - 4
b = SetWindowLong(handle, -20, ret)
End Sub
- Add the following code to the Load Event for any form hosting the
ActiveX control. (The control name is Push1 in this example):
fixWindowStyle (Push1.hwnd)
STATUS
This behavior is by design.
Modification Type: | Major | Last Reviewed: | 5/12/2003 |
---|
Keywords: | kbcode kbprb KB192347 |
---|
|