7

アクションを使用してコントロールの可視性を制御しようとしています。私のコードは次のようになります。

パスカルファイル

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActnList, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ActionList1: TActionList;
    Action1: TAction;
    CheckBox1: TCheckBox;
    procedure Action1Update(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Action1Update(Sender: TObject);
begin
  (Sender as TAction).Visible := CheckBox1.Checked;
end;

end.

フォームファイル

object Form1: TForm1
  object Button1: TButton
    Left = 8
    Top = 31
    Action = Action1
  end
  object CheckBox1: TCheckBox
    Left = 8
    Top = 8
    Caption = 'CheckBox1'
    Checked = True
    State = cbChecked
  end
  object ActionList1: TActionList
    Left = 128
    Top = 8
    object Action1: TAction
      Caption = 'Action1'
      OnUpdate = Action1Update
    end
  end
end

フォームが最初に実行されると、ボタンが表示され、チェック ボックスがオンになります。次に、チェックボックスのチェックを外すと、ボタンが消えます。チェックボックスを再度オンにすると、ボタンが再表示されません。

この理由は、次のローカル関数内にあると思いますTCustomForm.UpdateActions

procedure TraverseClients(Container: TWinControl);
var
  I: Integer;
  Control: TControl;
begin
  if Container.Showing and not (csDesigning in Container.ComponentState) then
    for I := 0 to Container.ControlCount - 1 do
    begin
      Control := Container.Controls[I];
      if (csActionClient in Control.ControlStyle) and Control.Visible then
          Control.InitiateAction;
      if (Control is TWinControl) and (TWinControl(Control).ControlCount > 0) then
        TraverseClients(TWinControl(Control));
    end;
end;

のチェックはControl.Visible、自分のアクションが再び更新される機会をブロックしているようです。

問題を正しく診断しましたか? これは仕様によるものですか、それとも QC レポートを提出する必要がありますか? 誰かが回避策を知っていますか?

4

3 に答える 3

4

はい、ロブがすでに言って説明したように、あなたの診断は正しいです。回避策は、個々の TAction の OnUpdate イベント ハンドラを使用するのではなく、TActionList の OnUpdate イベント ハンドラを使用することです。

procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
begin
  Handled := True;
  Action1.Visible := CheckBox1.Checked;
end;

これが機能するには、リンクされたアクションを持つ少なくとも 1 つの可視コントロールが必要です。そうしないと、ActionList の OnUpdate ハンドラーも呼び出されません。

ところで、Actions と ActionLists が最初に導入されたとき、Ray Konopka (Raize コンポーネント) がそれらの実装に関するいくつかの記事を書き、それらの使用方法について非常に的確なアドバイスを提供しました。それ以来、私は個々の Action の OnExecute を使用するのではなく、ActionList の OnUpdate を使用するという慣行を採用してきました。また、そのハンドラーで最初に行うことは、必要以上に呼び出されないように Handled を True に設定し、そのハンドラーで Action の Enabled プロパティを一度だけ変更して、結果として GUI がちらつかないようにすることです。オフにしてからオンにします。

Ray Konopkaの記事は、"Effectively Using Action Lists" です「結合」バージョン (オリジナルは手元にありません)。

于 2012-04-12T19:06:52.490 に答える