EditのEnabled=False処理で

解決


オリファー・イノエ  2022-03-16 05:21:52  No: 150115  IP: [192.*.*.*]

Delphi 6, 7, 2007 です。

Edit系のコンポーネントが3種類ほどあります。
継承元をたどると、TCustomEditが共通の親クラスです。

このとき、これらのEnabledをFalseにしたとき、文字色や背景色を変更したい場合、
以下のように共通化しようとしても、protectedプロパティにアクセスできないため、
コンパイルできません。

procedure EnabledChange(Edit: TCustomEdit; Enabled: Boolean);
begin
  Edit.Enabled := Enabled;
  if Enabled then 
  begin
    Edit.Font.Color := clWindowText;
    Edit.Color := clWindow;
  end else
  begin
    Edit.Font.Color := clGray;
    Edit.Color := clLtGray;
  end;
end;

イカのようなクラスを定義すれば、ActionLinkのSetEnabled が使えるので 
Enabled プロパティは変更できます。
type
  THogeLink  =class(TWinControlActionLink)
  end;

しかし、フォント色、背景色を変更する手法が思いつきません。


一応、イカの方法もあるのは知っていますが、これに頼らない方法がありますか?
type  
  TMyEdit=class(TCustomEdit)
  end;

  TMyEdit(Edit).Font.Color := clWindowText;
  TMyEdit(Edit).Color := clWindow;

ソースもあるので、共通した何かを追加することはできますが、
コンポーネント自体に手を加えず、対応する方法があれば、お願いします。


さらに言えば、TCustomComboBox を共通の親とする、ComboBox系コンポーネントも数種類あって・・・
真の目的は、上記のEnabledChangeの引数がTWinControlで、Enabeldプロパティの変更で
見た目の統一したいということなんですけども。。。(欲深い)

編集 削除
mam  2022-03-16 06:35:12  No: 150116  IP: [192.*.*.*]

お使いの環境で可能かどうかわからないのですが(環境を持っていないので、XE10.2では可能であるだけです)、jclとjvclをインストールして、
TJvEditを使うと
DisabledColor
DisabledTextColor
等のプロパティがあります。
外していると思いますが、すいません。

編集 削除
AAA  2022-03-16 08:53:55  No: 150117  IP: [192.*.*.*]

FONT と COLOR の PROPERTY を PUBLIC に持ってくる

TAEdit = class(TCustomEdit)
TBEdit = class(TCustomEdit)
TCEdit = class(TCustomEdit)

TZEdit = class(TCustomEdit)
public
  property Font
  property Color
end 

TAEdit = class(TZEdit)
TBEdit = class(TZEdit)
TCEdit = class(TZEdit)


編集 削除
HFUKUSHI  2022-03-16 10:19:34  No: 150118  IP: [192.*.*.*]

> Delphi 6, 7, 2007
ということになると、
> コンポーネント自体に手を加えず
なら
> 一応、イカの方法もあるのは知っていますが、これに頼らない方法がありますか?
> type  
>   TMyEdit=class(TCustomEdit)
>   end;
しかないでしょうね。コンポーネントのソースを変更可能ならAAAさんの方法で。

編集 削除
take  2022-03-18 00:17:20  No: 150119  IP: [192.*.*.*]

自分も同じようなことを考えたことがあるのですが
共通のTWinCotrolから簡単にプロパティを変更しようとすると
is でクラスごとに処理を変えるぐらいしか思いつきませんでした。

Colorが  published で定義されているので
実行時型情報(RTTI)を使えば型が異なっていても
プロパティ名経由で読み書き出来るかと思います。
ただ、結構なプログラム量になるかもしれないので
その処理の使用頻度によるかもしれません。

procedure TForm7.Button1Click(Sender: TObject);
begin
  EnabledChange(Edit1,not Edit1.Enabled);
end;

procedure TForm7.Button2Click(Sender: TObject);
begin
  EnabledChange(ComboBox1,not ComboBox1.Enabled);
end;

procedure TForm7.EnabledChange(ctrl: TWinControl; Enabled: Boolean);
var
  Edit : TEdit;
  Combo : TComboBox;
  c,cf : TColor;
begin
  ctrl.Enabled := Enabled;
  if Enabled then
  begin
    cf := clWindowText;
    c  := clWindow;
  end else
  begin
    cf := clGray;
    c := clLtGray;
  end;

  if ctrl is TEdit then begin
    Edit := TEdit(ctrl);
    Edit.Font.Color := cf;
    Edit.Color := c;
  end;
  if ctrl is TComboBox then begin
    Combo := TComboBox(ctrl);
    Combo.Font.Color := cf;
    Combo.Color := c;
  end;
end;

編集 削除
オリファー・イノエ  2022-03-18 03:30:17  No: 150120  IP: [192.*.*.*]

回答いただいた皆様ありがとうごさいました。
まとめレスで失礼します。

結果として、以下の通りで対応しました。
1)is でクラスごとに分岐(できるだけ分岐を少なく)
2)TMyEdit=class(TCustomEdit)のような定義を、1)の分岐したクラス分、定義

条件の後出しではありますが、フォーム数、コントロール数が膨大なので、
新しいコンポーネントに入れ替えは、めんd(略)

間にプロパティを公開したクラスを挟むのは、ソース変更の手間としては楽なほうかと思いましたが、
最近の忘れ病で、いろいろ自信がなくなっているので、上記の方法で対応することにしました。
(間にクラス挟むなんて、余裕で忘れそう)

> Colorが  published で定義されているので
> 実行時型情報(RTTI)を使えば型が異なっていても
> プロパティ名経由で読み書き出来るかと思います。
なるほど!その発想はなかった!
でも、ほぼ経験がない部分なので、もう少し余裕のあるときにチャレンジしてみます。

めんどくさがりとか、忘れっぽいというオプションつきで、すいません。
これにて解決といたします。

編集 削除
AAA  2022-03-18 08:39:25  No: 150121  IP: [192.*.*.*]

これで
  TX = class(TWinControl)
  public
    property Color;
    property Font;
  end;

procedure EnabledChange(Edit: TControl; Enabled: Boolean);
begin
  Edit.Enabled := Enabled;
  if Enabled then
  begin
    TX(Edit).Font.Color := clWindowText;
    TX(Edit).Color := clWindow;
  end else
  begin
    TX(Edit).Font.Color := clGray;
    TX(Edit).Color := clLtGray;
  end;
end;

編集 削除
オリファー・イノエ  2022-03-23 09:48:05  No: 150127  IP: [192.*.*.*]

遅くなりましたが

AAAさん
>  TX = class(TWinControl)
そうですね、これが一番ラクチンですね。
TCustomEditとかTCustomComboBoxとかそれぞれのコントロール別の判定不要で、is TWinControl で済みますから。


そんなわけで、正攻法?と組み合わせたのを作ってみました

procedure SetEnabledCtrl(aCtrl: TControl; aEnabled: Boolean);

implementation

type
  //誤魔化し用
  TWCtrl  =class(TWinControl)
  public
    property Color;
    property Font;
  end;

  TCALink  =class(TControlActionLink)
  private
    FAction  :TAction;
    FWClient  :TWCtrl;
  public
    constructor Create(AClient: TObject); override;
    destructor Destroy; override;
  protected
    function IsEnabledLinked: Boolean; override;
    procedure AssignClient(AClient: TObject); override;
    procedure SetEnabled(Value: Boolean); override;
  end;

constructor TCALink.Create(AClient: TObject);
begin
  inherited Create(AClient);
  FAction := TAction.Create(nil);
  Action := FAction;
end;
destructor TCALink.Destroy;
begin
  FAction.Free;
  inherited Destroy;
end;
function TCALink.IsEnabledLinked: Boolean;
begin
  //無条件リンクしていると判定
  Result := True;
end;
procedure TCALink.AssignClient(AClient: TObject);
begin
  inherited AssignClient(AClient);
  //↓↓↓↓↓↓ (※)ココ
  if AClient is TWinControl then FWClient := TWCtrl(AClient);
end;
procedure TCALink.SetEnabled(Value: Boolean);
begin
  inherited SetEnabled(Value);
  if FWClient <> nil then begin
    if Value then
    begin
      FWClient.Font.Color := clWindowText;
      FWClient.Color := clWindow;
    end else
    begin
      FWClient.Font.Color := clGray;
      FWClient.Color := clLtGray;
    end;
  end;
end;

procedure SetEnabledCtrl(aCtrl: TControl; aEnabled: Boolean);
var
  wcal  :TCALink;
begin
  wcal := TCALink.Create(aCtrl);
  try
    wcal.SetEnabled(aEnabled);
  finally
    wcal.Free;
  end;
end;

これで、「おお!いい感じ!」などと自己満足していましたが、
TCheckBoxとかも対象にしたとき、フォントやら背景やら変わってしまって、よろしくありませんでした。

上記ソース内、(※)ココ の部分を、フォントとか更新してもいいコントロールであるかの判定にすると、
使えるようになりそうです。
単純に考えて、 is TCustomEdit とか is TCustomComboBox でしょうけど。

編集 削除