为什么在Windows API编程中需要RegisterClass ?

Why is it necessary to RegisterClass in Windows API programming?

本文关键字:RegisterClass 编程 Windows API 为什么      更新时间:2023-10-16

我想问为什么,在使用API开发Windows GUI时,有必要注册一个窗口类吗?它的概念是什么?

我已经读了Charles Petzold的Programming Windows的前三章,但是我仍然想知道显式注册一个类的目的是什么。我为什么要明确地这么做呢?为什么不在后台完成,例如在CreateWindow()(或CreateWindowEx())函数?我的意思是,为什么不是代码,RegisterClass()内CreateWindow()执行,或者为什么CreateWindow()不调用RegisterClass()本身?

我也一直在阅读MSDN上的文档,我知道RegisterClass()函数通过填充WNDCLASS结构将窗口过程与窗口类关联起来。我知道这是处理来自操作系统的消息的函数,但是为什么有必要将该函数(WinProc)注册到CreateWindow()单独函数内的类?

我可以理解CreateWindow()函数存在的原因,以及为什么它不自动显示创建的窗口。这意味着我也理解了ShowWindow()函数的目的。

我相信这种行为一定有很好的理由,让程序员在他想注册一个类的时候注册,我只是没有看到这些理由,这就是为什么我要求你们解释这个问题。

请记住,我是一个非常新的GUI开发与Windows API。我在MATLAB中做了一些GUI,这与Windows API不同,但仍然让我理解了一些Windows的哲学,特别是回调函数的目的。我不知道这个信息是否有用,但如果你需要做一些类比,请成为我的客人。

既然你用c++标记了你的问题,我就给你一个c++的类比…

RegisterClass基本上是定义一个类并将其包含在程序中(很像c++中的#include)。WNDPROC是你的处理程序的任何事情发生在窗口内,如果和当一个实例被创建。

CreateWindow在概念上与您在c++中执行new相同。你要求Windows创建一个新窗口,你必须告诉它窗口的类型。Windows包含一组预定义的窗口,如按钮或编辑,但如果你想创建一个自己的窗口的实例,那么这很好,你只需要告诉它你想要创建的"类"。您已经通过调用RegisterClass注册了这个类,因此Windows现在可以直接进入定义并创建窗口的实例。

另一种思考方式是,因为Windows是闭源的,所以API编写者不希望您了解API的太多内部信息。所以现在,他们会想:"如果用户想用自己的行为创建自己的窗口类怎么办?"这就是为什么要为用户创建WNDCLASS,通过在成员字段中赋值(如名称、过程)来声明他们需要的类的信息。就像填表格一样。因此,你可以看到API编写者实现了两件事:

(1)用户对API一无所知,因为他们没有显式地扩展API类来自定义,因为如果他们这样做,那么API作者必须提供类的头文件,用户可能会搞砸,使Windows不再关闭。

(2)用户仍然可以定义自己的窗口类

现在,在你定义了你自己的窗口类之后,你想要使用它,所以你必须注册这个类,这样Windows操作系统就知道这个类是什么,这样他们就可以维护关于它的信息以备将来需要,然后你可以创建它的实例

你需要RegisterClass来定义样式,窗口的过程,这是必要的编程线程拥有的窗口,以响应消息和事件,做什么或不为每个消息,窗口接收和每个事件发生,窗口的图标,光标用户看到当鼠标悬停在窗口,窗口的客户端背景和窗口的菜单。

你怎么能想象一个没有这些属性的窗口呢?

也许你会问为什么所有这些窗口属性不是CreateWindow函数的参数,所以我用CreateWindow函数设置它们,而不是用RegisterClass函数,对吧?

如果所有窗口属性都是CreateWindow函数的参数,则CreateWindow函数非常复杂,并且正确调用CreateWindow的行非常长

这使得代码非常大,可读性差,效率低。

RegisterClass大大简化了CreateWindow。

这是Microsoft希望Win32开发人员在CreateWindow之前先调用RegisterClass的原因之一。

还假设您希望至少两个窗口具有相同的属性。

你只分配一个WNDCLASS结构的实例,设置他的字段来设置你的窗口的公共属性,你只调用RegisterClass函数一次,但是你调用CreateWindow的次数需要创建所有的窗口,但是每个人都有相同的类名。

RegisterClass不仅大大简化和缩短了代码,而且还可以防止在CreateWindow中重复相同的代码。

RegisterClass也使代码更高效。

这是一个很好的设计,首先分配一个WNDCLASS实例,设置它的字段,调用RegisterClass函数,然后调用CreateWindow函数,你想调用多少次就调用多少次。

虽然你需要调用RegisterClass多次,如果你想要的窗口与不同的属性,当然

您还必须在每次调用RegisterClass函数之前修改WNDCLASS实例。

我认为实际原因是由于系统窗口类:

"许多系统类可供所有进程使用,而其他系统类仅在系统内部使用。因为系统注册了这些类,所以进程不能销毁它们。来源:https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes

请注意,win32中的许多东西都被认为是"小部件"。(如按钮、工具栏、组合框等)实际上是窗口,因为它们有一个窗口类。它们是由系统提供的,并且可以重写行为,但是它们的默认源代码对应用程序程序员是隐藏的。

每个注册的窗口都部分由操作系统管理,为了减少CPU和内存资源的消耗,最好保持注册窗口列表尽可能小。因此,将注册窗口和创建窗口分开是比合并这两个任务更好的设计,因为用户可以只用一个系统注册的窗口类创建本地管理的窗口。