PreCreateWindow

转载 2012年03月27日 14:56:00

MFC9.0中

wincore.cpp中实现的函数AfxEndDeferRegisterClass自动预注册3个窗口类,分别为_afxWnd,_afxWndOleControl和_afxWndControlBar。自MFC 4.0起,类AfxWnd, AfxFrameOrView, AfxMDIFrame和AfxControlBar不再预注册,见KB 140596

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

...

      // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

      if (fToRegister & AFX_WND_REG)

      {

           // Child windows - no brush, no icon, safest default class styles

           wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

           wndcls.lpszClassName = _afxWnd;

           if (AfxRegisterClass(&wndcls))

                 fRegisteredClasses |= AFX_WND_REG;

      }

      if (fToRegister & AFX_WNDOLECONTROL_REG)

      {

           // OLE Control windows - use parent DC for speed

           wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

           wndcls.lpszClassName = _afxWndOleControl;

           if (AfxRegisterClass(&wndcls))

                 fRegisteredClasses |= AFX_WNDOLECONTROL_REG;

      }

      if (fToRegister & AFX_WNDCONTROLBAR_REG)

      {

           // Control bar windows

           wndcls.style = 0;   // control bars don't handle double click

           wndcls.lpszClassName = _afxWndControlBar;

           wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

           if (AfxRegisterClass(&wndcls))

                 fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;

      }

      if (fToRegister & AFX_WNDMDIFRAME_REG)

      {

           // MDI Frame window (also used for splitter window)

           wndcls.style = CS_DBLCLKS;

           wndcls.hbrBackground = NULL;

           if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))

                 fRegisteredClasses |= AFX_WNDMDIFRAME_REG;

      }

      if (fToRegister & AFX_WNDFRAMEORVIEW_REG)

      {

           // SDI Frame or MDI Child windows or views - normal colors

           wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

           wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

           if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))

                 fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;

      }

      if (fToRegister & AFX_WNDCOMMCTLS_REG)

      {

           // this flag is compatible with the old InitCommonControls() API

           init.dwICC = ICC_WIN95_CLASSES;

           fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_MASK);

           fToRegister &= ~AFX_WIN95CTLS_MASK;

      }

      if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)

      {

           init.dwICC = ICC_UPDOWN_CLASS;

           fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_UPDOWN_REG);

      }

      if (fToRegister & AFX_WNDCOMMCTL_PAGER_REG)

      {

           init.dwICC = ICC_PAGESCROLLER_CLASS;

           fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_PAGER_REG);

      }

...

}

 

之后进入AfxDeferRegisterClass,再进入实现在MainFrm.cpp中(这是由于CMainFrame中重写了PreCreateWindow)的函数CMainFrame::PreCreateWindow

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

      if( !CFrameWnd::PreCreateWindow(cs) ① )

           return FALSE;

      // TODO: Modify the Window class or styles here by modifying

      //  the CREATESTRUCT cs

 

      return TRUE;

}

①处调用winfrm.cpp中的函数PreCreateWindow

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

      if (cs.lpszClass == NULL)

      {

           VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

           cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background

      }

 

      if (cs.style & FWS_ADDTOTITLE)

           cs.style |= FWS_PREFIXTITLE;

 

      cs.dwExStyle |= WS_EX_CLIENTEDGE;

 

      return TRUE;

}

其中函数AfxDeferRegisterClass定义在afximpl.h中

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

以上完成了注册窗口过程。

 

再转入实现在winfrm.cpp中的函数CFrameWnd::Create

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,

      LPCTSTR lpszWindowName,

      DWORD dwStyle,

      const RECT& rect,

      CWnd* pParentWnd,

      LPCTSTR lpszMenuName,

      DWORD dwExStyle,

      CCreateContext* pContext)

{

      HMENU hMenu = NULL;

      if (lpszMenuName != NULL)

      {

           // load in a menu that will get destroyed when window gets destroyed

      if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,

           rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,

           pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))

      {…}

 

      return TRUE;

}

它调用了实现在wincore.cpp中的函数CWnd::CreateEx创建窗口

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)

{

      if (!PreCreateWindow(cs) ②)

      {

           PostNcDestroy();

           return FALSE;

      }

 

      AfxHookWindowCreate(this);

}

②处为函数CMainFrame::PreCreateWindow。

 

综上流程,CMainFrame::PreCreateWindow分别在注册和创建窗口时被2次调用。搜寻MFC调用顺序可以调试(Debug)应用程序,把Step Into(F11),Step Over(F10)和断点(Breakpoint)结合使用,效果最佳!

 

由于定义在afxwin.h中的函数是虚函数

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

因而可以在自己程序定义的CMainFrame中重写(Override)它,在该函数的第一行加入调试(Debug)中的事件纪录,TRACE/TRACE0/TRACE1/TRACE2/TRACE3,非MFC程序则需要用Win32格式化调试输出

TRACE(L"CMainFrame::PreCreateWindow \n");

这样就能在调试(Debug)中看到此输出(output)信息,可以看到它输出了两次,这从另一方面再次验证了上述结论,由于C++多态性,派生类中重写虚函数,若对象是派生类则调用派生类的函数。若再在程序的View类(如类CxxxView,xxx为项目名)中重写此方法,在该函数的第一行加上

TRACE(L"CtestView::PreCreateWindow \n");

可以看到,此输出接在CMainFrame的两次输出后仅输出一次。

 

最后,类CFormView和CRecordView不调用函数PreCreateWindow。



来源:http://fafeng.blogbus.com/logs/22802679.html


相关文章推荐

关于框架类和视图类的PreCreateWindow函数的重载!!

框架类: static LPCSTR classname=NULL; if( !CFrameWnd::PreCreateWindow(cs) )  return FALSE; // TODO: Mod...

PreCreateWindow改窗口类型无效原因

由于 BOOL CView::PreCreateWindow(CREATESTRUCT & cs)  {  ...  cs.dwExStyle |= WS_EX_CLIENTEDGE;...

MFC程序框架的剖析

//AfxWinMain()函数在WINMAIN.CPP文件中,它主要调用以下函数AfxWinInit();pApp->InitApplication();    //pThread->InitIns...

2017.5.8MFC学习笔记

在MFC中寻找窗口创建过程的每一步,通过设置断点的方式,弄清楚每一步是如何进行的,先到哪后到哪。这里面封装性好,不容易看明白,看的头疼。。。。1.AfxEndDeferRegisterClass 用来...

PreCreateWindow函数, PreSubClassWindow函数

这两个函数是MFC的基类CWnd两个很重要的虚函数,万恶的MFC总是让人很烦恼。 class CWnd : public CCmdTarget {      public:      ...

precreatewindow & presubclasswindow

MFC(VC6.0)的CWnd及其子类中,有如下三个函数:     // From VS Install PathVC98MFCIncludeAFXWIN.H     class CWnd :...
  • wx163
  • wx163
  • 2014年12月22日 14:40
  • 107

【转】CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow的区别

http://blog.csdn.net/swimmer2000/archive/2007/10/30/1856213.aspx MFC(VC6.0)的CWnd及其子类中,有如下三个函数:  ...

OnCreate PreCreateWindow PreSubclassWindow !

OnCreate PreCreateWindow PreSubclassWindow !简介:这是OnCreate PreCreateWindow PreSubclassWindow的详细页面,介绍了...

PreCreateWindow、PreSubclassWindow、SubclassWindow

PreSubclassWindow PreSubclassWindow是一个很好的定制控件的位置。如果我们通过重载CWnd::PreCreateWindow定制控件,而用户在对话框中使用控件。由于对...
  • oldmtn
  • oldmtn
  • 2011年09月29日 15:29
  • 763

CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow的区别

MFC(VC6.0)的CWnd及其子类中,有如下三个函数:   Cpp代码  class CWnd : public CCmdTarget   {   publ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:PreCreateWindow
举报原因:
原因补充:

(最多只允许输入30个字)