我要投稿

MFC中自定义窗口类名

时间:2010-03-04 22:02 作者:ceshi123 阅读:3037

扫描二维码关注公众号,可以查询淘宝、京东商品优惠券
  MFC中封装很多常用的控件,把类名也给封装了,没有提供明显的接口出来,用win api写窗口程序,第一步就是注册窗口类

  此时类名和标题名是一起注册的,所以能把标题很好地让用户来设定,类名也应该是很简单的,可惜的是MFC没有这样做,原因也许是window name可以不停的改,而类名不能。窗口的类名是有Create来确定的,要在Create前,给窗口选择一个已经注册的窗口类名,作为参数窗口Create就ok了,CWnd的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)(UINT_PTR)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)

  {

  ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName) ||

  AfxIsValidAtom(lpszClassName));

  ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName));

  // 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 = ::AfxCtxCreateWindowEx(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)

  {

  TRACE(traceAppMsg, 0, "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;

  }

  可以看到最后到了::AfxCtxCreateWindowEx,可以很容易地知道这里调用了CreateWindowEx来创建一个窗口

  在前面有一个PreCreateWindow(cs),而cs经过PreCreateWindow处理后,交给::AfxCtxCreateWindowEx处理

  ::AfxCtxCreateWindowEx在中转给CreateWindowEx,cs.lpszClass就是类名,可以清楚了AfxCtxCreateWindowEx的用心良苦


最新评论

ceshi1232010-03-04 22:03
  我们可以重载的PreCreateWindow,来修改类名,如下的代码:

  // TODO: 在此添加专用代码和/或调用基类

  //VERIFY(AfxDeferRegisterClass(AFX_WND_REG));

  //AfxEndDeferRegisterClass(AFX_WND_REG);

  //cs.lpszClass = AfxRegisterWndClass(NULL);

  WNDCLASS wndcls;

  memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL

  // defaults

  wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

  //you can specify your own window procedure

  wndcls.lpfnWndProc = ::DefWindowProc;

  wndcls.hInstance = AfxGetInstanceHandle();

  wndcls.hIcon =  NULL; // or load a different icon

  wndcls.hCursor =NULL;

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

  wndcls.lpszMenuName = NULL;

  // Specify your own class name for using FindWindow later

  wndcls.lpszClassName = _T("MyNewClass");

  // Register the new class and exit if it fails

  if(!AfxRegisterClass(&wndcls))

  {

  TRACE("Class Registration Failed\n");

  return FALSE;

  }

  cs.lpszClass = wndcls.lpszClassName;

  return TRUE;

  //return CWnd::PreCreateWindow(cs);

  其实就是为了把一个已经注册的类名字符串传给CreateWindowEx,从上面代码中的注释中来看,我还用了一种让系统来生成className的方法AfxRegisterWndClass。CWnd::PreCreateWindow不符合我的心意,注释掉了,其实里面也没什么就是判断而已。而在MFC中CWnd其他派生类就不这么简单了,不过单纯的修改类名,就重载这个方法大多就ok了。

  是的,只是大多数可以的,可惜的是这个方法,对于Dialog来说并不行,因为它不用CWnd::Create,也就绕不到

  PreCreateWindow上来了,你可以重载对话框的这个方法,断点,是断不下来的。因为CDialog的创建可以直接用系统的api来搞,不用再劳驾CWnd来中转到CReateWindowEx了,所以就不能够用上述方法来改对话框的类名了。

  看下它的创建代码了:

  BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)

  {

  ASSERT(IS_INTRESOURCE(lpszTemplateName) ||

  AfxIsValidString(lpszTemplateName));

  m_lpszTemplateName = lpszTemplateName;  // used for help

  if (IS_INTRESOURCE(m_lpszTemplateName) && m_nIDHelp == 0)

  m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);

  #ifdef _DEBUG

  if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE))

  {

  ASSERT(FALSE);          // invalid dialog template name

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

  return FALSE;

  }

  #endif //_DEBUG

  HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);

  HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);

  HGLOBAL hTemplate = LoadResource(hInst, hResource);

  BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst);

  FreeResource(hTemplate);

  return bResult;

  }

  可以看出来CDialog是靠资源来创建的,可以这样来来搞的,在资源脚本中定义Class “对话框类名”在对话框domodal或者Create前注册这个类名,然后等着modal和Create后就可以了。
我要投稿 我要评论
插入url链接 添加表情
限 100000 字节
响应相关主管单位规定,关闭回帖发帖功能
[VB毕业设计] [ASP毕业设计] [JAVA毕业设计] [JSP毕业设计] [PHP毕业设计] [asp.net毕业设计] [.net毕业设计] [网络毕业设计] [Delphi毕业设计] [VC毕业设计] [VF毕业设计] [机械毕业设计] [工艺毕业设计] [模具毕业设计] [其他毕业设计]
站长联系 cccbbsnet#163.com 本站系公益性质网站,站内广告维系本站运作。欢迎赞助本站。
大学生计算机相关方向|软件编程|网络工程|web开发|数据库技术|学习资料等
本社区仅供学习计算机相关技术所使用,访客发言不得违反国家法律法规
Time now is:01-23 06:01, Gzip enabled 蜀ICP备07004838号Powered by cccbbs.net v7.5 SP3 Code © 2003-06 cccbbs
计算机毕业设计