关闭

PreCreateWindow

标签: stylesmfcwindowsclasscolorsnull
1957人阅读 评论(1) 收藏 举报
分类:

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


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:48493次
    • 积分:647
    • 等级:
    • 排名:千里之外
    • 原创:25篇
    • 转载:14篇
    • 译文:0篇
    • 评论:8条
    最新评论