天天看點

Create和CreateEx 差別

先來看CreateEx函數:

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

  LPCTSTR lpszWindowName, DWORD dwStyle,

  const RECT& rect, CWnd* pParentWnd, UINT nID,

  LPVOID lpParam /* = NULL */)

{

 return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,

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

  pParentWnd->GetSafeHwnd(), (HMENU)nID, lpParam);

}

 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);

#ifdef _DEBUG

 if (hWnd == NULL)

  TRACE1("Warning: Window creation failed: GetLastError returns 0x%8.8X/n",

   GetLastError());

#endif

 if (!AfxUnhookWindowCreate())

  PostNcDestroy();        // cleanup if CreateWindowEx fails too soon

 ASSERT(hWnd == m_hWnd); // should have been set in send msg hook

 return TRUE;

可以看到,這兩個重載函數的實作原理是讓第一個函數調用了第二個函數。在第二個CreateEx中實際是通過調用Win32 SDK平台的ateWindowEx(CWnd沒有此函數)來建立視窗的。

再來看Create函數:

BOOL CWnd::Create(LPCTSTR lpszClassName,

 const RECT& rect,

 CWnd* pParentWnd, UINT nID,

 CCreateContext* pContext)

 // can't use for desktop or pop-up windows (use CreateEx instead)

 ASSERT(pParentWnd != NULL);

 ASSERT((dwStyle & WS_POPUP) == 0);

 return CreateEx(0, lpszClassName, lpszWindowName,

  dwStyle | WS_CHILD,

  rect.left, rect.top,

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

  pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);

注意這兩行:

 ASSERT((dwStyle & WS_POPUP) == 0);  // 該行說明Create函數不允許視窗風格為WS_POPUP

可以看到,在Create函數之中又調用了CreateEx的第二個重載版本。

總結:

歸根到底,MFC是通過CreateEx函數調用CreateWindowEx函數來建立視窗的。

注意一點:這個新建立的視窗是如何與我們的視窗對象進行綁定的呢?看第二個CreateEx的return上面的那一行:

ASSERT(hWnd == m_hWnd); // should have been set in send msg hook

在這裡這隻是進行判斷。看它的注釋:// should have been set in send msg hook

奧,它說在

if (!AfxUnhookWindowCreate())

處設定了m_hWnd的值。