Presubclasswindow
Presubclasswindow is a good place to customize the controls. If we use overloaded CWnd::P Recreatewindow Custom controls, and the user uses the controls in a dialog box. Because the control window in the dialog box is created by Createdlgindirect, the PreCreateWindow function is not invoked without the Cwnd::createex function.
In fact, to use a custom control in a dialog box, you must use the DDX or SubclassDlgItem function to subclass the control, and then Presubclasswindow will be called.
If the user creates a custom control window directly, the Cwnd::createex function will be called, and the control window must be quilt-class to install the MFC message pump. So in MFC, Presubclasswindow is the only way to create a window.
CWnd::P Resubclasswindow
virtual void Presubclasswindow ();
Description
The framework calls this member function to allow other necessary subclasses before the window quilt is instantiated. Overload this function to allow dynamic subclasses of the control. This is an advanced, overloaded function.
The VC6.0 and its subclasses of PreCreateWindow, Presubclasswindow, Subclasswin MFC (CWnd) in CWnd have the following three functions: Class Cwnd:public CCmdTarget
{
Public
Virtual BOOL PreCreateWindow (createstruct& CS);
virtual void Presubclasswindow ();
BOOL SubclassWindow (HWND hwnd);
}; It's not easy to tell the difference between what exactly they are doing, and in what circumstances to rewrite which function.
Want to know the rewrite function. Let me first tell you which one can not rewrite, that is SubclassWindow. Scott Meyers's masterpiece <<effective c++>> 36th is this differentiate between inheritance of interface and inheritance of implementation. You'll know right away that the non-virtual functions in the parent class are designed to be rewritten without the quilt class. According to have no virtual keyword, we have excluded the SubclassWindow, also knew that PreCreateWindow and Presubclasswindow are designed to be rewritten. The next question is when it should be written. To know when to write, you must know when the function is invoked, and what you want to do to perform the function. Let's take a look at the explanations for the three functions that MSDN gives:
PreCreateWindow:
Called by the framework before the creation of the Windows window
Attached to this CWnd object.
(to be called by the framework before the window is created and attach to the CWnd object that the this pointer refers to)
Presubclasswindow:
This member function is called by the framework to allow other necessary
Subclassing to occur before the Windows is subclassed.
(to be called by the framework before window is subclassed to allow other necessary subclassing to occur)
Although I already have the translation, but let me have a simple explanation to CWnd's attach and the window subclass. To understand attach, we have to know the difference between a C + + CWnd object and a window (Windows): Windows is a real window, and CWnd is MFC uses classes to encapsulate windows in C + +. Attach, is to attach the window to the CWnd object operation. After the attach (attach) is finished, the CWnd object is contacted with the window. The subclass of a window is an action that modifies a window's procedure, not a derived subclass in an object-oriented class.
Well, PreCreateWindow is invoked by the framework before the window is created, and the function name illustrates this, and the pre should be the abbreviation for previous, Presubclasswindow by the framework before the subclass window. The phrase is not said, you may still not know when to rewrite which function. RR the author of the paper, or use the code to speak it. Before the source code, no secret (Hou Jie language). Let's take a look at the MFC three functions are implemented this way. BOOL Cwnd::createex (DWORD dwexstyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwstyle,
int x, int y, int nwidth, int nheight,
HWND hwndparent, Hmenu nidorhmenu, LPVOID lpparam)
{
Allow modification of several common create parameters
CREATESTRUCT cs;
Cs.dwexstyle = dwExStyle;
Cs.lpszclass = lpszClassName;
Cs.lpszname = lpszWindowName;
Cs.style = dwstyle;
cs.x = x;
Cs.y = y;
cs.cx = nwidth;
Cs.cy = nheight;
Cs.hwndparent = hwndparent;
Cs.hmenu = Nidorhmenu;
Cs.hinstance = AfxGetInstanceHandle ();
Cs.lpcreateparams = Lpparam;
if (! PreCreateWindow (CS))
{
PostNcDestroy ();
return FALSE;
}
Afxhookwindowcreate (this);
HWND hwnd =:: CreateWindowEx (Cs.dwexstyle, Cs.lpszclass,
Cs.lpszname, Cs.style, Cs.x, Cs.y, cs.cx, Cs.cy,
Cs.hwndparent, Cs.hmenu, Cs.hinstance, cs.lpcreateparams);
return TRUE;
}
For child windows
BOOL CWnd::P Recreatewindow (createstruct& CS)
{
if (Cs.lpszclass = NULL)
{
Make sure the default window class is registered
VERIFY (Afxdeferregisterclass (Afx_wnd_reg));
No WNDCLASS provided-use child window default
ASSERT (Cs.style & Ws_child);
Cs.lpszclass = _afxwnd;
}
return TRUE;
}
Cwnd::createex first set CS (createstruct), after calling the real window to create a function:: CreateWindowEx, called CWnd::P the Recreatewindow function, and the parameter CS passed in a reference way. and the PreCreateWindow function of CWnd is just assigning value to Cs.lpszclass. After all, in many of the parameters of the window creation function Cwnd::createex, none of them specifies the window class to create the window, which is indispensable (refer to <<windows programming >> Chapter III). So when you need to change the size of the window, style, window to the window class and other CS member variables, to overwrite the PreCreateWindow function. From VS Install PathVC98MFCSRCWINCORE.CPP
BOOL Cwnd::subclasswindow (HWND hwnd)
{
if (! Attach (HWND))
return FALSE;
Allow any other subclassing to occur
Presubclasswindow ();
Now hook into the AFX WndProc
wndproc* LPLPFN = Getsuperwndprocaddr ();
WNDPROC Oldwndproc = (WNDPROC):: SetWindowLong (HWnd, GWL_WNDPROC,
(DWORD) Afxgetafxwndproc ());
ASSERT (Oldwndproc!= (WNDPROC) Afxgetafxwndproc ());
if (*LPLPFN = NULL)
*LPLPFN = Oldwndproc; The ' control ' of that type created
#ifdef _DEBUG
else if (*LPLPFN!= oldwndproc)
{
:: SetWindowLong (HWnd, GWL_WNDPROC, (DWORD) oldwndproc);
}
#endif
return TRUE;
}
void CWnd::P Resubclasswindow ()
{
No default processing
Cwnd::subclasswindow first calls the function attach (HWND) to associate the CWnd object with the window that the HWND refers to. The Presubclasswindow is then invoked before modifying the window process (subclass) with: SetWindowLong. CWnd::P Resubclasswindow didn't do anything.
In the implementation of CWnd, there is another place in addition to Cwnd::subclasswindow calling Presubclasswindow. The functions listed above CreateEx the code that calls a Afxhookwindowcreate function, see the following code://From VS Install PathVC98MFCSRCWINCORE.CPP
BOOL Cwnd::createex ()
{
Allow modification of several common create parameters
if (! PreCreateWindow (CS))
{
PostNcDestroy ();
return FALSE;
}
Afxhookwindowcreate (this);
HWND hwnd =:: CreateWindowEx (Cs.dwexstyle, Cs.lpszclass,
Cs.lpszname, Cs.style, Cs.x, Cs.y, cs.cx, Cs.cy,
Cs.hwndparent, Cs.hmenu, Cs.hinstance, cs.lpcreateparams);
return TRUE;
Then look at the code for Afxhookwindowcreate:
From VS Install PathVC98MFCSRCWINCORE.CPP
void Afxapi afxhookwindowcreate (cwnd* pwnd)
{
if (Pthreadstate->m_hhookoldcbtfilter = NULL)
{
Pthreadstate->m_hhookoldcbtfilter =:: SetWindowsHookEx (WH_CBT,
_afxcbtfilterhook, NULL,:: GetCurrentThreadID ());
if (Pthreadstate->m_hhookoldcbtfilter = NULL)
AfxThrowMemoryException ();
}
}
Its main role:: SetWindowsHookEx function to set up a hook function (hook function) _afxcbtfilterhook, whenever Windows produces a window (there are many other similar, please refer to << simple mfc> > 9th, page 563, the hook function you set will be invoked.
After this setup completes, returns to the Cwnd::createex function, executes:: CreateWindowEx carries on the window creation, the window one produces, will call the above set hook function _afxcbtfilterhook. And it is in _afxcbtfilterhook that the function Presubclasswindow is invoked for the second time. See the following code:
From VS Install PathVC98MFCSRCWINCORE.CPP
/**//**//**//////////////////////////////////////////////////////////////////////////////
Window Creation Hooks
LRESULT CALLBACK
_afxcbtfilterhook (int code, WPARAM WPARAM, LPARAM LPARAM)
{
Connect the HWND to Pwndinit
Pwndinit->attach (HWND);
Allow subclassing to occur
Pwndinit->presubclasswindow ();
{
Subclass the window with standard AfxWndProc
Oldwndproc = (WNDPROC) SetWindowLong (HWnd, GWL_WNDPROC, (DWORD) afxwndproc);
ASSERT (Oldwndproc!= NULL);
*poldwndproc = Oldwndproc;
}
The Presubclasswindow is also called before the subclass of the function setwindowlong the window.
Typically the window is created by the user cwnd::create (..)
In this process, MFC provides an opportunity "PreCreateWindow () for users to do something before they create
And for dialog boxes, and so on, the window is subclass way to the user
The system reads the dialog template, creating each of the child windows
The message handler function of each child window is then replaced with the message handler function of the corresponding C + + object (subclass: Subclass, or "take over"), and then the child window moves in the way defined in the class.
In this process, the Cwnd:subclasswindow (HWND hwnd) is invoked;
In this process, MFC provides an opportunity "Presubclasswindow" for users to do their bit before associating
Specifically, if you define a window (such as a CButton derived class Cmybutton) and then associate a button with its own derived class object using dialog data interchange, some "before" processing should be written in "Presubclasswindow".
If you are not using the dialog Data Association, you create the m_mybtn yourself in Oninitdialg. Create (...)
At this point, some "pre-establishment" processing should be written in "PreCreateWindow"