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

 

 

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

#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

 if (hWnd == NULL)
  return FALSE;
 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,
 LPCTSTR lpszWindowName, DWORD dwStyle,
 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(pParentWnd != NULL);
 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())
  PostNcDestroy();        // cleanup if CreateWindowEx fails too soon

处设置了m_hWnd的值。

时间: 2024-11-13 06:36:43

Create和CreateEx 区别的相关文章

vc++窗口的创建过程(MFC消息机制的经典文章)

一.什么是窗口类  在Windows中运行的程序,大多数都有一个或几个可以看得见的窗口,而在这些窗口被创建起来之前,操作系统怎么知道该怎样创建该窗口,以及用户操作该窗口的各种消息交给谁处理呢?所以VC在调用Windows的API(CreateWindow或者CreateWindowEx)创建窗口之前,要求程序员必须定义一个窗口类(不是传统C++意义上的类)来规定所创建该窗口所需要的各种信息,主要包括:窗口的消息处理函数.窗口的风格.图标. 鼠标.菜单等.其定义如下:  typedef struc

《Windows 程序设计(第3版)》——6.3 创建窗口

6.3 创建窗口 6.3.1 窗口函数 Windows为每个窗口都提供了默认的消息处理函数,自定义类的窗口的默认消息处理函数是DefWindowProc,各子窗口控件(见7.1节)的类名是Windows预定义的,其窗口函数自然由Windows提供. 我们的框架也提供了一个通用的消息处理函数AfxWndProc.为了响应窗口消息,必须让Windows把窗口的消息处理函数的地址全设为AfxWndProc,在处理消息时由我们自己决定是否调用默认的消息处理函数.改变窗口消息处理函数地址最简单的办法是使用

MFC常见问题解惑

MFC类的分类 1 Root: CObject : CObject2 Application Architecture Classes: CWinApp/CFrameWnd/... 3 Window, Dialog, and Control Classes:CWnd/CDialog/...4 Drawing and Printing Classes : CGdiObject/CPrintInfo/...5 Simple Data Type Classes :CString/CRect/...6 

Attach()函数和Detach()函数的作用

基本就是把一个句柄绑定和解绑定于一个类对象上,是其可以使用MFC的函数而不是API 首先,你要明白Windows对象和MFC对象的区别.MFC对象实际上并没有把整个Windows对象都包装在其中,它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口对象,也就是WNDCLASS,是一个Windows对象),那么这个MFC对象就是有效的,否则这个MFC对象是空的.如果你还不明白,请回忆一下,当我们使用MFC创建一个窗口时,是分两步进行的,第一步,new一个CWnd对象,这一步是

MFC Attach()函数和Detach()函数

一.Windows对象和MFC对象的区别?MFC对象实际上并没有把整个Windows对象都包装在其中.对于窗口:MFC对象它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口对象,也就是WNDCLASS,是一个Windows对象),那么这个MFC对象就是有效的,否则这个MFC对象是空的.如果你还不明白,请回忆一下,当我们使用MFC创建一个窗口时,是分两步进行的:第一步,new一个CWnd对象,这一步是创建MFC对象,但是其中的HWND还是非法的,因为对应的Windows对象

关于MFC内部结构实用的一点看法

我们在编写程序或是在看MFC类的书籍的时候,总会看到书上让我们在某个地方添加某某 函数,响应什么消息.那么,到底为什么要在这地方加呢?为什么不能在其他地方添加消息 响应函数呢? 接下来,我们就共同来讨论一下吧. 1.MFC的运行步骤:(这 是对于文档视图结构的应用程序的) theApp(theApp())->//应用程序全局对象 的构造和内存分配 WinMain()->//进入主函数 AfxWinMain()->//调用 API InitAplacation()(应用程序的内部管理)-&

SQLServer中的存储过程

  SQL Server的存储过程 Alter Procedure与Create Procedure的区别: 1. Alter Proc期望找到一个已有的存储过程,而Create则不是. 2. Alter Proc保留了存储过程上已建立的任何权限.它在系统对象中保留了相同的对象ID并允许保留依赖关系. 3. Alter Proc在可能调用被修改的存储过程的其他对象上保留了任何依赖信息. 对于存储过程本身以及调用脚本对它使用,需要注意的几点: 1. 对于存储过程声明中的输出参数,需要使用OUTPU

进入MFC讲坛的前言(三)

MFC中的窗口创建及窗口消息映射 我经常碰到有人问我有关窗口创建的问题,他们经常把用HWND描述的系统窗口对象和用CWnd描述的MFC的窗口对象混淆不清.这两者之间是紧密联系在一起的,但是MFC为了自身的管理,在CWnd中加了一些额外的内容,包括如何从HWND生成CWnd. 在MFC中,有几种典型的窗口对象,CWnd描述的一般窗口对象,CView描述的视图对象,CFrameWnd描述的SDI框窗对象,CMDIFrameWnd描述的MDI框窗对象等等.在这一章中,主要讨论下述内容: MFC中窗口的

MFC SDI单文档 状态栏 进度条 启动画面编程技巧 ...

      状态栏的编程离不开  CStatusBar类     CProgressCtrl  进 度条相关的控件      下面我们介绍状态栏 编程技巧  以及在状态栏添加进度条   应用程序的启动界面    状态栏的添加步骤     SDI 单文档中      下面是MFC给的 状态栏的创建步骤      Construct the CStatusBar object.    构造一个 CStatusBar对象    Call the Create (or CreateEx) functio