程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> VC++ >> 窗口類的誕生(注冊自己的窗口類)2

窗口類的誕生(注冊自己的窗口類)2

編輯:VC++

    我們現在再來看看AfxDeferRegisterClass是什麼樣子的:

  #define AfxDeferRegisterClass(fClass) \

  ((afxRegisteredClasses & fClass) ? TRUE:AfxEndDeferRegisterClass(fClass)
 
  #define afxRegisteredClasses AfxGetModuleState()->m_fRegisteredClasses

  BOOL AFXAPI AfxEndDeferRegisterClass(short fClass)

  {

  WNDCLASS wndCls;

  wndCls.lpfnWndProc = DefWindowProc;

  if(fClass & AFX_WND_REG)

  {

  wndCls.lpszClassName=_afxWnd;

  AfxRegisterClass(&wndCls);

  }else if(fClass & AFX_WNDOLECONTROL_REG)
 
  {

  wndCls.lpszClassName=_afxWndOleControl;

  AfxRegisterClass(&wndCls);

  }else if(fClass & AFX_WNDCONTROLBAR_REG)

{

  wndCls.lpszClassName=_afxWndControlBar;

  AfxRegisterClass(&wndCls);

  }else if(fClass & AFX_WNDMDIFRAME_REG)

  {

  RegisterWithIcon(&wndCls,_afxWndMDIFrame,AFX_IDI_MDIFRAME);

  }else if(fClass & AFX_WNDFRAMEORVIEW_REG)

  {

  RegisterWithIcon(&wndCls,_afxWndFrameOrView,AFX_IDI_STD_FRAME);

  }else if(fClass & AFX_WNDCOMMCTLS_REG)

  {

  InitCommonControls();

  }

  }

  從上面的代碼可以看出,AfxDeferRegisterClass函數首先判斷該窗口類是否注冊,如已注冊則直接返回,否則調用AfxEndDeferRegisterClass進行注冊,即注冊要求的默認窗口類。其中RegisterWithIcon和InitCommonControls最終也是轉化為調用AfxRegisterClass,而AfxRegisterClass函數調用RegisterClass進行注冊,啊,終於看到SDK中的RegisterClass了,看到它總有一種親切感!

  有了上面的知識,我們就可以很容易摸清MFC是怎樣注冊窗口類的了!我們知道Windows上所有看得見的東西,在MFC中都是繼承於CWnd類的,而CWnd類創建窗口的成員函數是Create和CreateEx,由於Create最終是調用CreateEx,所以我們只需要看CreateEx函數就行了:

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCSTSTR lpszClassName,

  …… LPVOID lpParam)

  {
 
  CREATESTRUCT cs;

  cs.dwExStyle = dwExStyle;

  … …

  cs.lpCreateParams = lpParam;

  PreCreateWindow(cs);

  AfxHookWindowCreate(this);

  HWND hWnd=::CreateWindowEx(cs.dwStyle,cs.lpszClass,…,cs.lpCreateParams);

  ……

  }

  啊,一看到CreateWindowEx,親切感又來了,這不是和SDK中的CreateWindow一樣嘛,是創建窗口!既然這樣,那麼注冊窗口肯定在該函數之前,會是誰呢?如果你做過一點MFC程序,你就會對將眼光停留PreCreateWindow上。對!就是它了。

  PreCreateWindow函數是CWnd類的一個虛擬函數,提供程序設置待創建窗口的屬性(包括窗口類),這樣繼承於CWnd的類都可以按照自己的要求在PreCreateWindow中設置自己的屬性了,而且我們看到MFC也是這樣做的:

  BOOL CWnd::PreCreateWindow(CREATESTRUCT &cs)

  {

  if(cs.lpszClass = = NULL)
  {

  AfxDeferRegisterClass(AFX_WND_REG);

  cs.lpszClass = _afxWnd;

  }

  return TRUE;

  }

  BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT &cs)

  {

  if(cs.lpszClass = = NULL)

  {

  AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);

  cs.lpszClass = _afxWndFrameOrView;

  }

  return TRUE;

  }

  BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT &cs)

  {

  if(cs.lpszClass = = NULL)
{

  AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG);

  cs.lpszClass = _afxWndMDIFrame;

  }

  }

  BOOL CMDIChildWnd::PreCreateWindow(CREATESTRUCT &cs)

  {

  return CFrameWnd::PreCreateWindow(cs);

  }

  BOOL CView::PreCreateWindow(CREATESTRUCT &cs)

  {

  if(cs.lpszClass = = NULL)

  {

  AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG);

  cs.lpszClass = _afxWndFrameOrView;

  }
 
  }

  就是通過繼承的方法,MFC實現常用類的窗口注冊(代碼並不完全,是從MFC中抽取對我們有意義的一部分代碼)。

  四.在MFC中注冊自己的窗口類

  在MFC中創建一個窗口,就必須是繼承於CWnd類的,這樣你的CMyWnd類自然就有了PreCreateWindow方法。你想注冊有自己個性的窗口類,那麼就在該函數中進行吧。也就是在PreCreateWindow函數中注冊自己的窗口類,然後將窗口類的類名以及待創建窗口的其它屬性(見CREATESTRUCT結構)填寫cs,然後返回系統,供系統創建你的窗口。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved