简体   繁体   English

CreateWnd 和 CreateWindowHandle 有什么区别?

[英]What's the difference between CreateWnd and CreateWindowHandle?

Delphi components have CreateWnd and CreateWindowHandle (and DestroyWnd and DestroyWindowHandle ). Delphi 组件具有CreateWndCreateWindowHandle (以及DestroyWndDestroyWindowHandle )。 They're both intended to be overridden by descendants, right?他们都打算被后代覆盖,对吧? And not intended to be called except by the underlying VCL implementation?并且不打算被底层 VCL 实现调用?

What's the difference between them;它们之间有什么区别; when should either of them be overridden?什么时候应该覆盖它们中的任何一个?

So far most of the answers here are pretty much on the mark and you would do well to heed their advice.到目前为止,这里的大多数答案都差不多,你最好听从他们的建议。 However, there is a little more to this story.但是,这个故事还有更多内容。 To your specific question about when you would override one or the other, I'll try and nutshell things a little bit.对于您何时会覆盖其中一个或另一个的具体问题,我将尝试简要介绍一下。

CreateParams();创建参数();

In general, most of the time all you really need to do is to override CreateParams().一般来说,大多数时候你真正需要做的就是重写 CreateParams()。 If all you want to do is to subclass (remember Windows style "subclassing?" See Petzold's seminal work on Windows programming) an existing control class and wrap it up in a VCL control, you do this from CreateParams.如果您只想对现有控件进行子类化(还记得 Windows 样式“子类化吗?”请参阅 Petzold 关于 Windows 编程的开创性工作)现有控件 class 并在 VCLParam 控件中执行此操作You can also control what style bits are set and other various parameters.您还可以控制设置的样式位和其他各种参数。 We've made the process of creating a "subclass" very easy.我们使创建“子类”的过程变得非常简单。 Just call CreateSubClass() from your CreateParams() method.只需从您的 CreateParams() 方法调用 CreateSubClass()。 See the core VCL controls for an example such as TCheckBox or TButton.有关 TCheckBox 或 TButton 等示例,请参阅核心 VCL 控件。

CreateWnd(); CreateWnd();

You would override this one if you need to do a little bit more with the window handle once it is created.如果您需要在创建 window 句柄后对其进行更多操作,则可以覆盖该句柄。 For instance, if you have a control that is some kind of list, tree, or otherwise requires post-creation configuration, you'd do that here.例如,如果您的控件是某种列表、树或其他需要创建后配置的控件,您可以在此处执行此操作。 Call the inherited CreateWnd, and when it returns (you know you have a valid handle if you return from CreateWnd because it will raise an exception if something went awry), just apply your extra magic.调用继承的 CreateWnd,当它返回时(如果您从 CreateWnd 返回,您知道您有一个有效的句柄,因为如果出现问题,它将引发异常),只需应用您的额外魔法。 A common scenario is to take the data that is cached in an instance TStrings list and actually move it into the underlying window control.一个常见的场景是获取缓存在实例 TStrings 列表中的数据,并将其实际移动到底层 window 控件中。 The TListBox is a classic example of this. TListBox 就是一个典型的例子。

CreateWindowHandle();创建窗口句柄();

I had to go refresh my memory on this one, but it seems this is one is rarely, if ever, overridden.我不得不 go 在这个上刷新我的 memory,但似乎这是一个很少(如果有的话)被覆盖的。 In the few cases inside VCL itself, it appears that it is used to work around specific Windows version and locale oddities with some controls, such as the TEdit and TMemo.在 VCL 本身内部的少数情况下,它似乎用于解决特定的 Windows 版本和带有一些控件(例如 TEdit 和 TMemo)的区域设置异常。 The other more clear-cut case is in TCustomForm itself.另一个更明确的案例是 TCustomForm 本身。 In this case it is there to support the old MDI (mutli-document interface) model.在这种情况下,它支持旧的 MDI(多文档接口)model。 In this case MDI children cannot be created using the normal CreateWindowEx() API, you have to send a message to the MDI parent frame to actually create the handle.在这种情况下,无法使用普通的 CreateWindowEx() API 创建 MDI 子框架,您必须向 MDI 父框架发送消息才能实际创建句柄。 So the only reason to overide this method is if the actual process of creating the handle is done via a means completely different than the old tried-and-true CreateWindowEx().因此,覆盖此方法的唯一原因是,如果创建句柄的实际过程是通过与旧的久经考验的 CreateWindowEx() 完全不同的方式完成的。

I did notice that your question was merely asking about the creation process, but there are corresponding methods that are overridden in some cases for both handle destruction and the "voodoo" that sometimes surrounds handle recreation.我确实注意到您的问题只是询问创建过程,但在某些情况下,对于句柄破坏和有时围绕句柄重新创建的“巫毒”,有相应的方法被覆盖。 But these are other topics that should be covered separately:-).但这些是应该单独讨论的其他主题:-)。

CreateWnd first calls CreateParams, then calls CreateWindowHandle using the created Params. CreateWnd 首先调用 CreateParams,然后使用创建的 Params 调用 CreateWindowHandle。 Generally, you'll override CreateWnd and CreateParams rather than CreateWindowHandle.通常,您将覆盖 CreateWnd 和 CreateParams 而不是 CreateWindowHandle。

I hope this helps!我希望这有帮助!

Who does what:谁做了什么:
CreateWnd is the general contractor that creates the fully formed window for a WinControl. CreateWnd 是为 WinControl 创建完整的window的总承包商。
First, it has to set the required attributes for the WindowClass by calling CreateParams and making sure it is correctly registered.首先,它必须通过调用CreateParams为 WindowClass 设置所需的属性,并确保它已正确注册。
Then it gets the window actually created, by calling CreateWindowHandle which returns the resulting Handle from the OS.然后它通过调用从操作系统返回结果句柄的CreateWindowHandle来获取实际创建的 window。
After that, we have a valid window able to process messages, and CreateWnd does the final grooming, adjusting different visual aspects like size, font, etc.之后,我们有一个有效的 window 能够处理消息, CreateWnd进行最后的修饰,调整不同的视觉方面,如大小、字体等。

There is also later step done by CreateHandle , after CreateWnd is finished, to help the VCL in managing its windows (identification, parentage,...). CreateWnd 完成后CreateHandle还完成了稍后的步骤,以帮助 VCL 管理其 windows (标识,亲子关系,...)。

I'm sure that the final answer can only come from the people involved in the creation of the VCL (Allen?), but IMHO the virtual method with the least responsibility / which is lowest in the chain of calls should be overridden.我敢肯定,最终答案只能来自参与创建 VCL 的人员(Allen?),但恕我直言,应该覆盖调用链中责任最小/最低的虚拟方法。 That's why I have always overridden CreateParams() and CreateWindowHandle() .这就是为什么我总是覆盖CreateParams()CreateWindowHandle() This looks like a good fit since they are both called by CreateWnd() , and both do only one special thing.这看起来很合适,因为它们都由CreateWnd()调用,并且都只做一件特殊的事情。

In the end it's probably a matter of preference.最后,这可能是一个偏好问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM