9

私は最近TFrameを多用し始めました(OK、はい、私は岩の下に住んでいます...)。フレームはメッセージハンダーメソッド宣言をサポートしていると思いました-そして私はその多くの例を見てきました。では、なぜ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のみが含まれ、フレームはフレームと閉じるボタンのみを含む単純なメインフォームで使用されます。

私は何が欠けていますか?

4

2 に答える 2

9

2つの可能性があります。

  1. プログラムはまだメッセージの処理を開始していません。GetMessage投稿されたメッセージは、プログラムがまたはPeekMessageを呼び出したときにのみ処理されますDispatchMessage。これは内部Application.Runで発生するため、プログラムがまだそこに到達していない場合、投稿されたメッセージは処理されません。

  2. フレームのウィンドウハンドルが破棄され、再作成されました。プロパティにアクセスするとHandle、フレームのウィンドウハンドルが強制的に作成されますが、フレームの親がまだ完全に安定していない場合は、フレーム自体のウィンドウハンドルが破棄され、再作成される可能性があります。これにより、すべての子が同じことを強制されるため、プログラムがメッセージの処理を開始するまでに、メッセージを投稿したハンドルは存在しません。

最初の問題を解決するには、ただ待ってください。プログラムは最終的にメッセージの処理を開始します。2番目の問題を修正するには、フレームのCreateWndメソッドをオーバーライドして、そこにメッセージを投稿します。このメソッドは、ウィンドウハンドルが作成された後に呼び出されるため、ハンドルが時期尚早に作成されることを回避できます。ただし、ハンドルが破棄されて再作成される可能性はあり、そのたびCreateWndに呼び出されるため、初期化メッセージが複数回投稿される可能性があるため、注意が必要です(ただし、同じウィンドウに投稿されることはありません)。複数回処理する)。それが正しいかどうかは、実行する必要のある初期化の種類によって異なります。

于 2011-04-22T13:16:51.590 に答える
3

私が思いつくことができるこれについての唯一の説明は、メッセージを投稿した後、メッセージキューがポンプされる前に、フレームのハンドルが再作成されるということです。OnShowに投稿してみてください。

于 2011-04-22T13:16:09.137 に答える