ちょっと、思いつきで頼まれた仕事のサンプルを作成中。
見積もり以前の段階なのに、ここまで作りこんでしまうのも、どうかと思うが。
今回、TDBCtrlGridに個別の配色をしたく、試行錯誤した。
***
まず、OnPanelPaintのイベント。
にあるように、
if Odd(index) then? begin DBCtrlGrd1.Color:=clSkyBlue; end else begin DBCtrlGrd1.Color:=clCream;
end;
※奇数、偶数で、配色を変えるコード
やりたいことは、レコードに保存した色で、パネル毎の背景色を変えたいので、
ちょっと、これでは物足りず。
Canvasに直接描画するも、そのパネルがどのデータを持っているか、取り出せないので、
アクティブ・レコードの時にしか、色データを取り出せず・・・
数時間、WEBを探し回るが、そんなサンプルに出会えず、
やっと見つけた、これ↓
>>?https://github.com/Evil-Spirit/Nutmeg/blob/master/Library/AlphaControls/AlphaDB/acDBCtrlGrid.pas
DB系コンポーネントは、どれもそうだけど、
DataLinkというプロパティーで、データを取得している。
特に、TDBGridや、TDBCtrlGridは、アクティブ・レコード以外のデータを
参照する必要があるため、内部的にDataLinkを参照しているのだけど、
これが、
private 宣言なので、外部のユニットからは、参照出来ないわけで。
上記は、コンポーネントなんだけど、
DataLink プロパティーの値を引いてくることが出来る、簡単なコードがあった!!
Result := TDBCtrlGrid_(Self).FDataLink;
TDBCtrlGrid_ というのは、TDBCtrlGridから派生させたもので、
TDBCtrlGrid_ = class(TWinControl) private FDataLink: TDBCtrlGridLink; end;
たった、これだけのもの。
privateは、同一ファイル上でしか、アクセスできないけど、
プロジェクト内のフォーム(TForm1)上で、TDBCtrlGrid_を
派生させて、キャストすれば、同一ファイル上になるので、
アクセスが出来るようになるという、方法。
DataLinkをpublic宣言に置き換えた、コンポーネントを作れば可能なんだけど、
それを、キャストでやってしまうというのは、
目からウロコでした!!
このやり方で、
procedure DBCtrlGridPaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Integer); var DL: TDataLink; SaveActive: Integer; begin // paint color // with DBCtrlGrid do if Index <> PanelIndex then begin DL := TDBCtrlGrid_(DBCtrlGrid).FDataLink; if not VarIsNull(DL.DataSet.FieldValues['color']) then begin Color := DL.DataSet.FieldValues['color']; end else Color := DBCtrlGrid_Color; end;
※DataLink上のデータは、ActiveRecord = Index(イベントの変数)で、取得できる
課題として、
大量の描画イベントが発生してしまうため、その対応を検討中。
していましたが、
完成しました!!
試行錯誤の過程は、あえてコメントアウトして、残していますが、
コメント行は、全消しでOK。
procedure TfMain.DBCtrlGridPaintPanel(DBCtrlGrid: TDBCtrlGrid; Index: Integer); var DL: TDataLink; SaveActive: Integer; begin // paint color // with DBCtrlGrid do if Index <> PanelIndex then begin DL := TDBCtrlGrid_(DBCtrlGrid).FDataLink; // SaveActive := DL.ActiveRecord; // DL.ActiveRecord := Index; try // DebugPrint(DL.DataSet.FieldValues['color']); if not VarIsNull(DL.DataSet.FieldValues['color']) then begin // http://delphimaster.net/view/3-51640 // Canvas.Brush.Color := DL.DataSet.FieldValues['color']; // Canvas.FillRect(Rect(0, 0, PanelHeight, PanelWidth)); Panel1.Color := DL.DataSet.FieldValues['color']; end else Panel1.Color := DBCtrlGrid_Color; finally // DL.ActiveRecord := SaveActive; end; end else Panel1.Color := DBCtrlGrid.SelectedColor; end;
Panel1というのは、TDBCtrlGrid上に置いた、
何の変哲もないTPanelですが、ちゃんと理由ははあります。
TDBCtrlGrid上には、TDBEditを幾つか置いていますが、
編集モードでない時は、カーソル表示させたくないので、
Enabled := false としたところ、文字が灰色になってしまうため、
(ReadOnlyだと、カーソルは表示されてしまう)
Panelを置き、それをEnabled := falseにすることで、
色は変わらず、カーソルが表示されない様になります。
偶然の結果ですが、
Panel1というのは、TDBCtrlGrid上に置いたことが、重要でした!!
最初は、Canvasの背景を描画して、
その上に、透明のTDBEditを置けばいいだろうとやっていたんですが、うまく行かず、
直接、TDBCtrlGrid.Colorを書き換えると、再描画が無限に行われますが、
TPanelのColorを書き換えてみたところ、うまく行きました。
APIでゴリゴリやろうかとも思っていましたが、
結果が同じなら、コード自体はシンプルな方がいいものです。
苦労した分、能書きが長くなりましたが(笑
PS.
あと、TDBEditの背景が透明にできるコンポーネントもあると、楽ですね。
DB非対応のTEditなのですが、TEdit > TDBEditと置き換えてやればいい。
※詳しくは、コンポーネントの作り方を学習してね
とやっていたのですが、
編集画面を作っている時に、落ち度が・・・ = ちゃんと描画されない
ので、
オリジナルのTDBEditに戻して、Panel1同様に、
DBEdit.Color := Panel1.Color;
を、足してやると、背景色が同色のまま、処理されます。