PRB: CTL3D Cannot Be Used with Shared MFC DLLID: Q126719
|
The CTL3D documentation "Adding 3-D Effects to Controls" indicates that you
should not use CTL3D with the DLL version of the Microsoft Foundation
Classes (MFC). If you try to use CTL3D with the MFC DLL, one of the
following symptoms may occur:
MFC versions 2.x rely on every control of a certain type having the same
window procedure, which is not the case with CTL3D. The window procedure
changes depending on whether the control has been subclassed or not.
The problem is that MFC uses a static variable per class to remember the
previous window procedure when it subclasses a window that is newly created
or one that is being subclassed with CWnd::SubclassWindow. This static
variable is returned by the virtual function CWnd::GetSuperWndProcAddr().
If the static is already non-zero and is different from the window
procedure that the new window had before subclassing occurred,
GetSuperWndProcAddr() will assert.
In release builds, the MFC DLL is shared by multiple applications, so every
control of a certain type used by all the MFC applications that use the MFC
DLL use the same window procedure. However, if the control is subclassed,
the window procedure being used may belong to one of the applications. If
this application terminates, controls in other applications will suddenly
have an invalid window procedure. Also, if one application uses CTL3D but
others do not, the applications that do not use CTL3D may reference the
CTL3D window procedure anyway.
To work around this behavior, you must override GetSuperWndProcAddr for any
windows you intend to subclass that may also be subclassed by CTL3D. In
your override, return a pointer to a class member variable that holds the
subclassed window procedure for the object's associated window.
For example, if you want to subclass a ComboBox that may also be subclassed
by CTL3D, perform these steps:
// combo3d.h
class C3dComboBox : public CComboBox
{
public:
virtual WNDPROC* GetSuperWndProcAddr();
WNDPROC m_lpfnSuper;
};
The source file for the class will look like this:
// combo3d.cpp
#include "combo3d.h"
WNDPROC* C3dComboBox::GetSuperWndProcAddr()
{
return &m_lpfnSuper;
}
Now it is safe to subclass and create from this new class, even if CTL3D
subclasses the control.This behavior is by design.
MFC 3.0, included with Visual C++ version 2.0, is designed differently. It corrects this problem by adding the member variable m_pfnSuper to the CWnd class. CWnd::GetSuperWndProcAddr() returns the address of this member variable, instead of returning the address of a static member variable. With this change to MFC, it is no longer necessary to override GetSuperWndProcAddr() for every CWnd-derived class.
Additional query words: 1.00 1.50 1.51 2.00 2.50 2.51
Keywords : kbcode kb16bitonly
Version : 1.00 1.50 1.51
Platform : WINDOWS
Issue type :
Last Reviewed: July 29, 1999