我最近才开始大量使用 TFrame(好吧,是的,我一直生活在岩石下......)。我认为框架支持消息处理方法声明——而且我见过很多这样的例子。那么为什么这个简单的 TFrame 测试单元永远看不到它发送给自身的消息呢? (当我发现我的大型应用程序中没有调用消息处理程序时,我创建了测试。)
unit JunkFrame;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
const
DO_FORM_INITS = WM_USER + 99;
type
TFrame1 = class(TFrame)
Panel1: TPanel;
private
procedure DoFormInits(var Msg: TMessage); message DO_FORM_INITS;
public
constructor Create(AOwner: TComponent); override;
end;
implementation
{$R *.dfm}
constructor TFrame1.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
PostMessage(self.Handle, DO_FORM_INITS, 0, 0);
end;
procedure TFrame1.DoFormInits(var Msg: TMessage);
begin
ShowMessage('In DoFormInits!');
end;
end.
该框架仅包含一个TPanel,该框架用于一个简单的主窗体,该主窗体仅包含该框架和一个关闭按钮。
我错过了什么?
最佳答案
我看到两种可能性:
您的程序尚未开始处理消息。仅当您的程序调用
GetMessage
或PeekMessage
,然后调用DispatchMessage
时,才会处理已发布的消息。这发生在Application.Run
内部,因此如果您的程序尚未到达那里,那么它将不会处理任何已发布的消息。您的框架的窗口句柄已被销毁并重新创建。访问
Handle
属性会强制创建框架的窗口句柄,但如果框架的父级尚未完全稳定,则它可能会销毁自己的窗口句柄并重新创建它。这会强制其所有子级执行相同的操作,因此当您的程序开始处理消息时,您发布消息的句柄并不存在。
要解决第一个问题,只需等待。您的程序最终将开始处理消息。要解决第二个问题,请重写框架的 CreateWnd
方法并在其中发布消息。该方法在创建窗口句柄后被调用,因此您可以避免强制过早创建句柄。不过,句柄仍然有可能被销毁并重新创建,每次发生这种情况时都会调用 CreateWnd
,因此您需要小心,因为您的初始化消息可能会多次发布(但绝不会多次发布到同一窗口句柄)。这是否正确取决于您需要执行哪种初始化。
关于delphi - 为什么我的 TFrame "seeing"不是已发布的消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5755747/