すみません恥のかきついでにもうつっこみお願いします
TJvRichEdit と TEditor には SelLength 同様 Lines プロパティなど同じように使えるモノが多くありますが
やはりそこは、前回の件のようなプロパティ設定を全てに対して設定するべきなのでしょうか
function Edior:T??;
常に Editor.SelLength、Editor.Lines などとアクセス出来るようにする方法があればいいなということなのですが
継承元の同じ先祖は TWinControl まで遡ってしまいそうですが
回答がないみたいなので
言われていることや気持ちは察しますが、
まったく関連性がない2つのクラスに関係性を持たせることは
各プロパティやメソッドに分岐をさせない限り難しいと思われます。
RTTIなどを使って関連づけることは余計な手間になります。
単純に、継承関係の無い違うコンポーネントで
同じプロパティを持たせたいだけなら
それぞれのコンポーネントに、同じ名前同じ引数で
個別にプロパティを記述すればいいんじゃないでしょうか。
そうすれば
var
EditorA: TEditorA;
EditorB: TEditorB;
・
・
EditorA.Property1 := xxx;
EditorB.Property1 := xxx;
と、こんな風にできますけど。
そういう意味じゃないのかな?
やりたいことは おそらく
FEdit : TWinControl; // 2つのコンポーネントのどちらかを参照したい
FREdit : TJvRichEdit; // 高機能エディタ
FNEdit : TEditor; // 標準エディタ
// 外部から現在使用しているエディタを参照
property Edit : TWinControl read FEdit;
// False : 標準 True :高機能
property Mode : Boolean read FMode SetMode;
procedure SetMode(const Value : Boolean);
begin
if Value then begin
FEdit := FREdit;
end
else begin
FEdit := FNEdit;
end;
end;
こうしておけばTJvRichEdit、TEditorが
同じ名称で持っているプロパティにアクセス出来ていいなぁ
// 現在使っているエディタに値を代入
xxx.Edit.SelLength := 20;
両方ともコンポーネントを自作しているか
もしくはその上位のカスタムコンポーネントから派生させて
必要な機能を実装すれば出来るけど
必要なメソッド、プロパティの数だけif分書いた方が楽だよね
継承元の異なるコンポーネントに対するプロパティ代入
https://www.petitmonte.com/bbs/answers?question_id=7978
↑この話の続きですよね。
わからんちんな私の理解ですが、考えてみました。
>前回の件のようなプロパティ設定を全てに対して設定するべきなのでしょうか
これが「結局全部書き分けなきゃいけないのをなんとか楽したい」というのなら無理だと思いますが、
>常に Editor.SelLength、Editor.Lines などとアクセス出来るようにする方法があればいい
こちらがメインで、「どうせ大変ならEditor.Nantokaで統一してカッコよく使いたい」
という要望であるなら、2つのコンポーネントを同じ方法で操作することだけを目的としたクラスを
作れば良いかと。
こういうのって、ラッパーって言うんですよね?(よく分かってない)
TJvRichEditもTEditorも使ってないので、TMemoとTRichEditで作ってみました。
とりあえずLines、SelStart、SelLengthだけ実装しましたけど、面倒ですね。
(しかもTMemoとTRichEditなら本当はこんなことする必要ないので、何かむなしい)
以下、無駄に長くて失礼しますがコード例です。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, Unit2;
type
TForm1 = class(TForm)
Memo1: TMemo;
RichEdit1: TRichEdit;
CheckBox1: TCheckBox;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private 宣言 }
Editor: TEditorWrapper;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Editor:=TEditorWrapper.Create(Memo1, RichEdit1);
Editor.PlainEditor.HideSelection:=False;
Editor.RichEditor.HideSelection:=False;
CheckBox1Click(CheckBox1);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Editor.Free;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Editor.PlainEditMode:=(Sender as TCheckBox).Checked;
Editor.Lines.Add('Current: '+Editor.CurrentEditor.Name);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Editor.Lines.Add('abcdef');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Editor.Lines.Add(Format('Start: %d Length: %d', [Editor.SelStart, Editor.SelLength]));
Editor.SelStart:=2;
Editor.SelLength:=7;
end;
end.
unit Unit2;
interface
uses
Classes, Controls, ComCtrls, StdCtrls;
type
TEditorWrapper = class(TObject)
private
FPEdit: TMemo;
FREdit: TRichEdit;
FPlainEditMode: Boolean;
public
constructor Create(PEdit: TMemo; REdit: TRichEdit);
function CurrentEditor: TWinControl;
function GetLines: TStrings;
function GetSelStart: Integer;
function GetSelLength: Integer;
procedure SetLines(Value: TStrings);
procedure SetSelStart(Value : Integer);
procedure SetSelLength(Value : Integer);
property PlainEditor: TMemo read FPEdit write FPEdit;
property RichEditor: TRichEdit read FREdit write FREdit;
property PlainEditMode: Boolean read FPlainEditMode write FPlainEditMode;
property Lines: TStrings read GetLines write SetLines;
property SelStart: Integer read GetSelStart write SetSelStart;
property SelLength: Integer read GetSelLength write SetSelLength;
end;
implementation
constructor TEditorWrapper.Create(PEdit: TMemo; REdit: TRichEdit);
begin
FPEdit:=PEdit;
FREdit:=REdit;
FPlainEditMode:=True;
end;
function TEditorWrapper.CurrentEditor: TWinControl;
begin
if FPlainEditMode then Result:=FPEdit else Result:=FREdit;
end;
function TEditorWrapper.GetLines: TStrings;
begin
if FPlainEditMode then Result:=FPEdit.Lines else
Result:=FREdit.Lines;
end;
procedure TEditorWrapper.SetLines(Value : TStrings);
begin
if FPlainEditMode then FPEdit.Lines:=Value else
FREdit.Lines:=Value;
end;
function TEditorWrapper.GetSelStart: Integer;
begin
if FPlainEditMode then Result:=FPEdit.SelStart else
Result:=FREdit.SelStart;
end;
procedure TEditorWrapper.SetSelStart(Value : Integer);
begin
if FPlainEditMode then FPEdit.SelStart:=Value else
FREdit.SelStart:=Value;
end;
function TEditorWrapper.GetSelLength: Integer;
begin
if FPlainEditMode then Result:=FPEdit.SelLength else
Result:=FREdit.SelLength;
end;
procedure TEditorWrapper.SetSelLength(Value : Integer);
begin
if FPlainEditMode then FPEdit.SelLength:=Value else
FREdit.SelLength:=Value;
end;
end.
皆さんありがとうございます
おおむね「なんとか楽したい」の方なのですが
既存の TJvRichEdit を使って作られたものにプレーンエディタモードを付けようとして
「出来るだけ追加、修正箇所が少ない方が新たなバグも発生しない」
という理由の方が聞こえがいいのでこちらにしてください(^^;
前回の「継承元の異なる〜」で開眼?して
property は EditorSelLength,EditorText,EditorSelText くらいまで作って
SetFocus あたりは
function EditCompo:TWinControl;
で済ましてみたのですがもう少しサマにならないものかなぁと思った次第です
助監督 様の別ユニットでのクラス定義はいいですね
Create=それ自体の生成だと思い込んでいた固い私の頭では出てきませんでした
>別ユニットでのクラス定義はいいですね
投稿前に思い直し、あえて別ユニットに分割した甲斐がありましたー。
自分と同じ初級者や入門者向けに、「長いコードは分割しちゃえばイインダヨ」ということを伝えたかったつもりです。
いま見直したら、GetやSetがpublicになってた…。
別クラス作成で問題なく使い分け出来そうですので今日は解決ボタンを押しに来ましたm(_ _)m
ツイート | ![]() |