0

WMSysCommand メッセージを使用して、キャプション バー ボタン (最大化/最小化) の動作と WMNCHitTest を使用するために必要な最近の更新を変更していますが、コードが長いため、これら 2 つの関連メッセージを複数の手順で分割したくありません。

他のメッセージからプライベート宣言 (メッセージ) にアクセスできますか? もし私ができるなら - どうやってそれをするのですか?

  procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest) ;
  begin
    SendMessage(Handle, HTCAPTION, WM_NCHitTest, 0); // or other wParam or lParam ???? 
  end;

  procedure TForm1.WMSysCommand;
  begin
    if (Msg.CmdType = SC_MAXIMIZE or 61488) or (Msg.Result = htCaption or 2) then // if command is Maximize or reciever message of Caption Bar click
    begin
      if CheckWin32Version(6, 0) then
        Constraints.MaxHeight := 507
      else
        Constraints.MaxHeight := 499;
      Constraints.MaxWidth := 0;
    end
    else if (Msg.CmdType = SC_MINIMIZE or 61472) or (Msg.Result = htCaption or 2) then // if command is Minimize
    begin
      if (EnsureRange(Width, 252, 510) >= (510 / 2)) then
        PreviewOpn.Caption := '<'
      else
        PreviewOpn.Caption := '>';
    end;
    DefaultHandler(Msg); // reset Message handler to default ( Application )
  end;

スー...私は正しく考えており、正しいコマンドをまったく知らないのか、それとも完全に強気な考えを持っているのでしょうか?

よろしく。助けてくれてありがとう...

4

1 に答える 1

4

あなたのコードとテキストは、メッセージ ハンドラーの動作についていくつかの誤解があることを示唆しています。まず、プライベート メッセージ ハンドラへのアクセスについて質問します。親クラスからプライベート メッセージ ハンドラーにアクセスする必要はありません。親クラスがそのメッセージを処理するかどうかに関係なく、任意のメッセージのハンドラーをオーバーライドできます。メッセージハンドラを書くだけです。親のハンドラーが非公開の場合でも、親のハンドラーを自動的にオーバーライドします。(実際、最初からメッセージ ハンドラをプライベートに宣言することが多いのはそのためです。子孫はいつでもメッセージ ハンドラをオーバーライドできます。また、直接呼び出す理由がないため、パブリックにする理由もありません。)

を呼び出して、基本クラスのメッセージ処理動作を取得しようとしているようですDefaultHandler。それは時々うまくいきますが、偶然です。基本クラスのメッセージ ハンドラーDefaultHandlerに移動します。基本クラスと子孫の間に他のクラスがある場合、 への呼び出しはそれらのハンドラをスキップします。その関数の代わりに、通常のメソッドをオーバーライドするときと同じように、ディレクティブを使用します。DefaultHandlerinherited

あたかもメッセージが送信されたかのようにオブジェクトを動作させたい場合、必ずしも を使用してメッセージを送信する必要はありませんSendMessagePerform代わりに、オブジェクトのメソッドを呼び出すことができます。同じメッセージ ディスパッチ操作がすべて発生しますが、Windows メッセージ キューをスキップできます。

多くの同様のタスクを実行する必要がある 2 つのメソッドがある場合、いくつかのオプションがあります。

  1. 両方の関数が似ているように、コードをコピーして貼り付けます。
  2. すべてのコードを 1 つの関数に入れ、2 番目の関数から呼び出します。
  3. すべてのコードを新しい 3 番目の関数に入れ、両方の関数から呼び出します。

通常、最初のオプションは適切ではありません。2 番目のオプションは、最初の関数が常に 2 番目の関数のサブセットであることが保証されている場合に適しています。ただし、2 番目の関数が常に必要としない何かを行う必要がある場合は、2 番目の関数から呼び出すのは適切ではありません。3 番目のオプションは、Robert の回答が示唆するものです。

水晶玉が正常に動作している場合は、2 番目のオプションが必要になる可能性があります。wm_NCHitTestwm_SysCommand ハンドラーでヒット テストを行いたいので、メッセージ ハンドラーを呼び出したいと思います。簡単だ。

procedure TForm1.WMSysCommand;
var
  Hit: DWord;
begin
  Hit := Perform(wm_NCHitTest, ...);
  if (Msg.CmdType = SC_MAXIMIZE) or (Hit = htCaption) then // if command is Maximize or reciever message of Caption Bar click
  begin
    if CheckWin32Version(6, 0) then
      Constraints.MaxHeight := 507
    else
      Constraints.MaxHeight := 499;
    Constraints.MaxWidth := 0;
  end
  else if (Msg.CmdType = SC_MINIMIZE) or (Hit = htCaption) then // if command is Minimize
  begin
    if (EnsureRange(Width, 252, 510) >= (510 / 2)) then
      PreviewOpn.Caption := '<'
    else
      PreviewOpn.Caption := '>';
  end;
  inherited;
end;

コードにいくつかの変更を加えたことに注目してください。まず、Performオブジェクトの wm_NCHitTest ハンドラーを呼び出し、結果を変数に格納します。その変数を次の条件で使用して、マウスがクリックされた場所を確認します。次に、or条件文からテストを削除しました。名前付き定数を同等の数値と組み合わせていましたが、これは無意味で混乱を招きます。DefaultHandler3 番目に、呼び出しを 1 つに置き換えましたinherited

ただし、注意してください: wm_SysCommand メッセージは、マウス メッセージだけでなくキーボードメッセージにも送信されます。常に有効なヒット テストがあるとは限りません。おそらく、この sys-command ハンドラについてはすべて間違っていると思いますが、実際に何を求めているのかを判断するのは困難です。

于 2010-06-14T14:31:44.200 に答える