DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

再帰関数引き渡し関数

再帰関数引き渡し関数


         |  めっぽう暑い!
(       ∬\__ _______________
(    丿   ∫   ∨           └┴┴┘
 (  ノ           ∧,,∧  
  ソ            ミ゚Д゚υ彡
∬∬            U  Uミ  
∬∬       / ̄ ̄ミ,,,,ミ,,,,ミ ̄ ̄ ̄ ̄
 ■●▲ ̄フ | ̄ ̄ ̄ し' し' ̄ ̄ ̄ ̄ ̄
▲◆■◆// ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄| ̄| ̄|  | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄| ̄| ̄|  |


ますますますます温暖化の季節。いかがお過ごしでしょうか?

エコエコエコエコ騒いでも、原油があれだけ流出したら、
全部台無しじゃねーか、という話題は大人の事情でなかったことにしてください。


ということで、今日もエコのために、効率のよいコードを考えていきましょう。

再帰関数を書く機会って、意外と少ないかもしれません。
俺も今までまともに書いた事がありませんでした。(ウソウソ(w


Panel1にPanel2がのっていて、Panel3がのって、Panel4がのっている場合
そして、それぞれのPanelにEditやComboやMemoやRadioがのっていたりする場合、

Panel1(もしくはPanel2やPanel3)にのっている全てのコントロールに対して
Enabledを変更したり、Colorを変更したり、DoubleBufferを変更したりする場合に、毎回再帰呼び出しを書いている人もいるかもしれません。

Panel1に対して処理をする関数Aから子コントロールに対して関数Aを呼び出して、その内部からまた関数Aが呼び出され…という仕組みになるわけですが、

これをライブラリ化してみましょう。
再帰関数なんて面倒なので、ライブラリ内部に隠蔽してしまえばいいことです。

/////////////ライブラリ側
type
 TRecursiveCallProcedure = procedure(Control: TControl; Args: array
of variant);

procedure RecursiveCallControl(WinControl: TWinControl; Proc:
TRecursiveCallProcedure; Args: array of variant);

  procedure RecursiveCallChildControl(Parent: TWinControl);
  var
   i: Integer;
  begin
   for i := 0 to Parent.ControlCount-1 do
   begin
    if (Parent.Controls[i] is TWinControl) then
     RecursiveCallChildControl( (Parent.Controls[i] as TWinControl) );

    Proc(Parent.Controls[i], Args);
   end;
  end;

begin
 RecursiveCallChildControl(WinControl);
 Proc(WinControl, Args);
end;

///////////////ライブラリを使ってライブラリとして拡張する側
procedure SetEnabled(Control: TControl; Args: array of variant);
begin
 Control.Enabled := Args[0];
end;

procedure SetChildControlEnabled(WinControl: TWinControl; Value: Boolean);
begin
  RecursiveCallControl(WinControl, SetEnabled, [Value]);
end;
///////////////


ここまで実装しておけば、ライブラリを使う側としては

  SetChildControlEnabled(Panel2, False);

このように指定すれば、Panel2に載っているコンポーネントのEnabledを制御できます

また、こんな実装もできます。

///////////////ライブラリを使ってライブラリとして拡張する側
procedure SetColor(Control: TControl; Args: array of variant);
begin
 if Control is TLabel then
  TLabel(Control).Font.Color := Args[0];

 if Control is TEdit then
 begin
  TEdit(Control).Color := Args[1];
 end;

 if Control is TMemo then
 begin
  TEdit(Control).Color := Args[2];
 end;

end;

procedure SetChildControlColor(WinControl: TWinControl; LabelColor, EditColor, MemoColor: TColor);
begin
  RecursiveCallControl(WinControl, SetColor, [LabelColor, EditColor, MemoColor]);
end;
///////////////

使う側はこんな感じ。
  SetChildControlColor(Panel2, clRed, clBlue, clGreen);


下記のように書くと
///////////////
procedure ReCallListup(Control: TControl; Args: array of variant);
begin
 TMemo(Args[0]).Lines.Add(Control.Name);
end;

procedure ChildListUp(WinControl: TWinControl; OutputMemo: TMemo);
begin
  RecursiveCallControl(WinControl, ReCallListup, [OutputMemo]);
end;
///////////////

  ChildListUp(Panel2, Self.Memo1);
これで、再帰呼び出しされるコントロール名を順番にメモに出力することもできます。

こうしておくと、再帰呼び出しを実装しなくても使いこなせるようになるでしょう。


「複雑なものをシンプルにするのは難しい」

とはよくいったものですが、
複雑なものをよりシンプルに見せるための難しいさをうまくやりこなすのが腕の見せ所。

ライブラリをライブラリとして使いやすくするための、オープン配列Variantパラメータ。
なかなか使いどころ、あるようです。

スポンサーサイト

| 未分類 | 23:05 | comments:0 | trackbacks(-) | TOP↑

COMMENT















非公開コメント

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。