TN001:窗口类注册

此说明介绍了注册 Microsoft Windows 所需的特殊 WNDCLASS 的 MFC 例程。 讨论了 MFC 和 Windows 使用的特定 WNDCLASS 属性。

问题

CWnd 对象的属性(如 Windows 中的 HWND 句柄)存储在两个位置:窗口对象和 WNDCLASSWNDCLASS 的名称传递给常规窗口创建函数,例如 lpszClassName 参数中的 CWnd::CreateCFrameWnd::Create

WNDCLASS 必须通过以下四种方法之一进行注册:

WNDCLASS 字段

WNDCLASS 结构由描述窗口类的各种字段组成。 下表显示了这些字段,并指定如何在 MFC 应用程序中使用它们:

字段 说明
lpfnWndProc 窗口进程必须是 AfxWndProc
cbClsExtra 未使用(应为零)
cbWndExtra 未使用(应为零)
hInstance 使用 AfxGetInstanceHandle 自动填充
hIcon 框架窗口的图标,请参阅下文
hCursor 鼠标位于窗口上方时的光标,请参阅下文
hbrBackground 背景色,请参阅下文
lpszMenuName 未使用(应为 NULL)
lpszClassName 类名,请参阅下文

提供的 WNDCLASS

早期版本的 MFC(MFC 4.0 之前)提供了多个预定义的窗口类。 默认情况下,不再提供这些窗口类。 应用程序应使用带有相应参数的 AfxRegisterWndClass

如果应用程序提供具有指定资源 ID 的资源(例如,AFX_IDI_STD_FRAME),MFC 将使用该资源。 否则,它将使用默认资源。 对于图标,将使用标准应用程序图标,对于游标,将使用标准箭头光标。

两个图标支持具有单文档类型的 MDI 应用程序:一个图标用于主应用程序,另一个图标用于图标文档/MDIChild 窗口。 对于具有不同图标的多文档类型,必须注册其他 WNDCLASS 或使用 CFrameWnd::LoadFrame 函数。

CFrameWnd::LoadFrame 将使用指定为第一个参数和以下标准属性的图标 ID 注册 WNDCLASS

  • 类样式:CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

  • 图标 AFX_IDI_STD_FRAME

  • 箭头光标

  • COLOR_WINDOW 背景色

由于 MDICLIENT 窗口完全覆盖了 CMDIFrameWnd 的工作区,因此不使用 CMDIFrameWnd 的背景色和光标的值。 Microsoft 不建议创建 MDICLIENT 窗口的子类,因此尽可能使用标准颜色和光标类型。

创建控件的子类和超类

例如,如果创建 Windows 控件(例如,CButton)的子类或超类,则类会自动获取该控件的 Windows 实现中提供的 WNDCLASS 属性。

AfxRegisterWndClass 函数

MFC 提供用于注册窗口类的帮助程序函数。 假设有一组属性(窗口类样式、光标、背景画笔和图标),则将生成合成名称,并注册生成的窗口类。 例如,

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

此函数返回生成的已注册窗口类名的临时字符串。 有关此函数的详细信息,请参阅 AfxRegisterWndClass

返回的字符串是指向静态字符串缓冲区的临时指针。 它在下次调用 AfxRegisterWndClass 之前有效。 如果要保留此字符串,请将其存储在 CString 变量中,如以下示例所示:

CString strWndClass = AfxRegisterWndClass(CS_DBLCLK, ...);

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

...

如果窗口类无法注册(由于参数错误或 Windows 内存不足),则 AfxRegisterWndClass 会引发 CResourceException

RegisterClass 和 AfxRegisterClass 函数

如果要执行比 AfxRegisterWndClass 提供的操作更复杂的操作,则可以调用 Windows API RegisterClass 或 MFC 函数 AfxRegisterClassCWndCFrameWndCMDIChildWndCreate 函数将窗口类的 lpszClassName 字符串名称用作第一个参数。 可以使用任何已注册的窗口类名,而不管用于注册它的方法。

请务必在 Win32 上的 DLL 中使用 AfxRegisterClass(或 AfxRegisterWndClass)。 Win32 不会自动取消注册 DLL 注册的类,因此必须在 DLL 终止时显式取消注册类。 通过使用 AfxRegisterClass(而不是 RegisterClass),系统会自动为你处理。 AfxRegisterClass 维护 DLL 注册的唯一类的列表,并在 DLL 终止时自动取消注册它们。 在 DLL 中使用 RegisterClass 时,必须确保在 DLL 终止时取消注册所有类(在 DllMain 函数中)。 当另一个客户端应用程序尝试使用 DLL 时,执行此操作失败可能导致 RegisterClass 意外失败。

另请参阅

按编号列出的技术说明
按类别列出的技术说明