随笔 - 14  文章 - 1 评论 - 13 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(1)

随笔分类

随笔档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜

 

TN001: 窗口类注册

                                                                                       translated by zhkza99c
这个笔记描述了MFC如何在Microsoft Windows注册一个特定的WNDCLASSes的规则。并且讨论了如何在MFC和WINDOWS里面定制WNDCLASS 的属性。

问题

CWnd对象的属性和Windows里面的HWND是类似的,都存在两个地方:窗口对象和WNDCLASS中。WNDCLASS是与C++类不同的一个类。WNDCLASS的名字是通过普通窗口构造函数的lpszClassName参数传入的,例如CWnd::Create 函数和 CFrameWnd::Create函数

WNDCLASS必须通过一下四种之一的方式来注册:

  • 隐式的通过mfc提供的WNDCLASSes
  • 隐式的通过子类化窗口的控件(或者其他一些控件)
  • 显式的通过MFC的AfxRegisterWndClass 或者 AfxRegisterClass函数
  • 显式的通过调用Windows的RegisterClass函数。

WNDCLASSes 和 MFC

WNDCLASS结构是由各种各样的区域值来描述一个窗口类的,下面是这些域和他们在MFC程序里的使用方法

Style 窗口的风格: 看下面
LpfnWndProc 窗口函数, 必须是AfxWndProc
CbClsExtra 不被使用(应该置0)
CbWndExtra 不被使用 (应该是0)
HInstance 自动由AfxGetInstanceHandle填充
HIcon 框架窗口的图标,具体下详
HCursor 当鼠标进入窗口内时的样式,下详
HbrBackground 背景颜色,下详
LpszMenuName 不被使用 (应该置 NULL)
LpszClassName 类的名字,下详

所提供的 WNDCLASSes

在之前的MFC版本中(MFC4.0之前),提供了一些预定义的窗口类,由于多版本引发的技术问题,这些窗口类不再默认提供(多版本的MFC加载在同一个地址空间)如涉及到的一个实际情况就是MFC应用程序和OLE控件都使用到MFC的DLL。
以下的参考是用来帮助解决之前版本的WNDCLASS的移植问题。应用程序要通过AfxRegisterWndClass(通过适当的参数)来代替这些窗口类。


下面展示了这些类和他们的属性:

  • "AfxWnd"被所有由CWnd::Create创建的子窗口使用
  •  类的样式:CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW
  • 无图标
  • 箭头鼠标
  • 没有背景颜色
    • "AfxFrameOrView" 用来定制窗口的框架和视图(包括被孤立的CFrameWnds 和 CMDIChildWnds)
      • 类的样式:CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
      • 图标为AFX_IDI_STD_FRAME
      • 箭头鼠标
      • 背景颜色为COLOR_WINDOW
    • "AfxMDIFrame" 使用CMDIFrameWnd::Create. 来创建MDI框架的窗口(即父窗口)
      • 类的样式 : CS_DBLCLKS [ 改变大小时减小闪烁]
      • 图标为AFX_IDI_STD_MDIFRAME
      • 箭头鼠标
      • 无背景颜色
    • "AfxControlBar" 被用来定义标准的控件栏
      • 类的样式 : 0 [ 改变大小时减少闪烁并且没有双击]
      • 无图标
      • 箭头鼠标
      • 灰背景色 (COLOR_BTNFACE)

    如果应用程序提供了一个由特殊的资源ID表示的资源(例如,AFX_IDI_STD_FRAME)ID,MFC将会使用这些资源,其他情况下会使用默认资源。例如图标,标准的应用程序图标将被使用,或者鼠标,标准的箭头鼠标将被使用。
    就单文档类型提供了两个图标来支持MDI应用程序(一个图标用来给主程序,另一个图标用来标示文档/MDIChild窗口)。例如文档类型又多个图标,你必须在WNDCLASSes注册图标或者使用CFrameWnd::LoadFrame 函数。
    CFrameWnd::LoadFrame 会通过标准的"AfxFrameOrView"自动注册一个WNDCLASS,但是图标的ID你必须通过LoadFrame第一个参数来标示。
    当MDIFrameWnd 的客户区域被"MDICLIENT"窗口完全覆盖时,MDIFrameWnd里背景颜色和鼠标类型的值不被使用。微软不鼓励子类化"MDICLIENT"窗口,所以尽可能的使用标准的颜色和鼠标类型。

    子类化控件
    如果你子类化或者超类化窗口控件(例如,CButton),你的类的WNDCLASS的属性会自动由你所继承的窗口所提供。

    AfxRegisterWndClass函数
    MFC提供了一个帮助规则来注册一个窗口类,只要给出一系列的属性(窗口类风格,鼠标,背景刷和图标)就会生成一个窗口的名字并且注册这个窗口。
    例如,

    const char* AfxRegisterWndClass(UINT nClassStyle,HCURSOR hCursor,
                                                          HBRUSH hbrBackground,HICON hIcon);

     

    这个函数返回一个临时的字符串来生成注册的窗口类的名字,请看Class Library Reference 来获得更多的细节。
    这个返回的字符串是一个指向静态字符串缓冲区的临时指针,它在下一个AfxRegisterWndClass调用之前都会有效。如果你想要保存这个字符串,将它存储在一个CString变量中。
    例如,

    CString strWndClass = AfxRegisterWndClass(CS_DBLCLK, ...);
    ...
    CWnd* pWnd = new CWnd;
    pWnd->Create(strWndClass, ...);
    ...
    

     

    如果窗口类注册失败的时候AfxRegisterWndClass会抛出一个CResourceException 异常(不论是给出了错误的参数还是Windows的内存不足)

    RegisterClass函数和AfxRegisterClass函数

    如果你想要做一些AfxRegisterWndClass所没有提供的更多的事情,你可以调用Windows API RegisterClass 或者 MFC的函数 AfxRegisterClass. CWnd, CFrameWnd 和 CMDIChildWnd Create函数都使用lpszClassName作为第一个参数来确定窗口类的名字。任何窗口类的名字都可以被使用,不论它是怎么被注册的。
    在DLL和Win32中使用AfxRegisterClass (或者AfxRegisterWndClass)是非常重要的。Win32并不自动反注册由Dll注册的类,因此必须在DLL被中止的时候显式的做这些工作。
    通过使用AfxRegisterClass来代替RegisterClass可以自动为你做到这些,AfxRegisterClass包括了一个列表,这个列表是由你的DLL注册的独一无二的并且可以在DLL中止的时候进行自动反注册。
    当在DLL中使用RegisterClass的时候,你必须确定在DLL终止的时候所有的类都要进行反注册(在你的DllMain函数中)。没有做这些可能会造成在你的DLL被其他客户应用程序所使用时,RegisterClass抛出失败的异常,


  • posted on 2008-03-12 16:15 田园的拾荒者 阅读(1462) 评论(1)  编辑 收藏 引用 所属分类: 翻译

    FeedBack:
    # re: TN001: 窗口类注册 2008-03-12 23:00 完美世界私服
    只有注册用户登录后才能发表评论。