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プロパティの変更で
見た目の統一したいということなんですけども。。。(欲深い)
お使いの環境で可能かどうかわからないのですが(環境を持っていないので、XE10.2では可能であるだけです)、jclとjvclをインストールして、
TJvEditを使うと
DisabledColor
DisabledTextColor
等のプロパティがあります。
外していると思いますが、すいません。
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)
> Delphi 6, 7, 2007
ということになると、
> コンポーネント自体に手を加えず
なら
> 一応、イカの方法もあるのは知っていますが、これに頼らない方法がありますか?
> type
> TMyEdit=class(TCustomEdit)
> end;
しかないでしょうね。コンポーネントのソースを変更可能ならAAAさんの方法で。
自分も同じようなことを考えたことがあるのですが
共通の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;
回答いただいた皆様ありがとうごさいました。
まとめレスで失礼します。
結果として、以下の通りで対応しました。
1)is でクラスごとに分岐(できるだけ分岐を少なく)
2)TMyEdit=class(TCustomEdit)のような定義を、1)の分岐したクラス分、定義
条件の後出しではありますが、フォーム数、コントロール数が膨大なので、
新しいコンポーネントに入れ替えは、めんd(略)
間にプロパティを公開したクラスを挟むのは、ソース変更の手間としては楽なほうかと思いましたが、
最近の忘れ病で、いろいろ自信がなくなっているので、上記の方法で対応することにしました。
(間にクラス挟むなんて、余裕で忘れそう)
> Colorが published で定義されているので
> 実行時型情報(RTTI)を使えば型が異なっていても
> プロパティ名経由で読み書き出来るかと思います。
なるほど!その発想はなかった!
でも、ほぼ経験がない部分なので、もう少し余裕のあるときにチャレンジしてみます。
めんどくさがりとか、忘れっぽいというオプションつきで、すいません。
これにて解決といたします。
これで
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;
遅くなりましたが
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 でしょうけど。
ツイート | ![]() |