いつも参考にしています。
コンポーネントの作成について相談させてください。
TDBGridColumnsのメソッドに LoadFromFile と SaveToFile がありますが,
このメソッドを TDBGrid作成時と破棄時に 組み込み
列データの保存と呼び出しを自動で行えるように実装したいと考えています(プロパティで切替可能)
現在,作成時は CreateWnd メソッドを,終了時は Destroy メソッドを override を行って処理をしています。
ただこのままだとプロジェクトを開いた時と終了する時に,CreateWndとDestory が動くみたいで,
開く時は下記のエラーが発生します。
フォーム作成中にエラーが発生しました。_1.Columns の読み込み中のエラー : TColumn.Expanded の読み込み中のエラー : リストのインデックスが範囲を超えています (0)
終了する際はエラーは出ないのですが,設計時の列データが保存されてしまいます。
(設計時は無効にするコンパイラ指令があったりする?)
何か対処法又は,良い手法があれば教えて頂けると幸いです。
コンポーネントを作成するのは初めてで考え方が間違っている所もあると思います。
よろしくお願いします。
=====================================================================
unit MyDBGrid;
interface
uses
SysUtils, Classes, Controls, Grids, DBGrids;
type
TMyDBGrid = class(TDBGrid)
private
FColumnSave: Boolean;
{ Private 宣言 }
procedure SetColumnSave(const Value: Boolean);
protected
{ Protected 宣言 }
procedure CreateWnd; override;
public
{ Public 宣言 }
destructor Destroy; override;
published
{ Published 宣言 }
property ColumnAutoSave: Boolean read FColumnSave write SetColumnSave default False;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Data Controls', [TMyDBGrid]);
end;
{ TMyDBGrid }
procedure TMyDBGrid.CreateWnd;
begin
inherited;
if FColumnSave then
begin
if FileExists('Col_' + Owner.Name + Name + '.dat') = True then
begin
Columns.LoadFromFile('Col_' + Owner.Name + Name + '.dat');
end;
end;
end;
destructor TMyDBGrid.Destroy;
begin
if FColumnSave then
begin
Columns.SaveToFile('Col_' + Owner.Name + Name + '.dat');
end;
inherited;
end;
procedure TMyDBGrid.SetColumnSave(const Value: Boolean);
begin
FColumnSave := Value;
end;
end.
Create部分記載忘れました。
type
TMyDBGrid = class(TDBGrid)
private
FColumnSave: Boolean;
{ Private 宣言 }
procedure SetColumnSave(const Value: Boolean);
protected
{ Protected 宣言 }
procedure CreateWnd; override;
public
{ Public 宣言 }
constructor Create(AOwner: TComponent); override; //追加
destructor Destroy; override;
published
{ Published 宣言 }
property ColumnAutoSave: Boolean read FColumnSave write SetColumnSave default False;
end;
constructor TMyDBGrid.Create(AOwner: TComponent);
begin
inherited;
FColumnSave := False;
end;
自己レスです。
CreateWndメソッド部分をLoadedメソッドに変更したところ,
プロジェクトを開いた際のエラーは発生しなくなりました。
しかしいまだプロジェクトファイルを開いた時と閉じた時に,
overrideした部分が動いてしまいます(ColumnAutoSave=True時)。
これはコンポーネントの性質,又は私の作成方法では対処方法がないのでしょうか?
よろしくお願いします。
=====================================================================================
unit MyDBGrid;
interface
uses
SysUtils, Classes, Controls, Grids, DBGrids, DB;
type
TMyDBGrid = class(TDBGrid)
private
FColumnSave: Boolean;
{ Private 宣言 }
procedure SetColumnSave(const Value: Boolean);
protected
{ Protected 宣言 }
procedure Loaded; override;
public
{ Public 宣言 }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published 宣言 }
property ColumnAutoSave: Boolean read FColumnSave write SetColumnSave default False;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Data Controls', [TMyDBGrid]);
end;
{ TMyDBGrid }
constructor TMyDBGrid.Create(AOwner: TComponent);
begin
inherited;
FColumnSave := False;
end;
procedure TMyDBGrid.Loaded;
begin
inherited;
if FColumnSave then
begin
Columns.Clear;
if FileExists('Col_' + Owner.Name + Name + '.dat') = True then
begin
Columns.LoadFromFile('Col_' + Owner.Name + Name + '.dat');
end;
end;
end;
destructor TMyDBGrid.Destroy;
begin
if FColumnSave then
begin
//列設定なしでデータセットが閉じている時は Columns.Count = 1 になる
//この場合は保存しない
if (DataSource.DataSet.State <> dsInactive) or
((DataSource.DataSet.State = dsInactive) and (Columns.Count > 1)) then
begin
Columns.SaveToFile('Col_' + Owner.Name + Name + '.dat');
end;
end;
inherited;
end;
procedure TMyDBGrid.SetColumnSave(const Value: Boolean);
begin
FColumnSave := Value;
end;
end.
さらに自己レスです。
Create時とDestory時に
if Not(csDesigning in ComponentState) then
とすればデザイン時は無効にするようにできました。
コンポーネント作る上で基本なんでしょうが初めて見ました・・・
あとDestory時にDataSourceが解放されているとメモリエラーになるので
以下のように修正しました。
destructor TMyDBGrid.Destroy;
begin
if Not(csDesigning in ComponentState) then
begin
if FColumnSave then
begin
//列設定なしでデータセットが閉じている時は Columns.Count = 1 になる
//この場合は保存しない
if Assigned(DataSource) then
begin
if (DataSource.DataSet.State <> dsInactive) or
((DataSource.DataSet.State = dsInactive) and (Columns.Count > 1)) then
begin
Columns.SaveToFile('Col_' + Owner.Name + Name + '.dat');
end;
end
else
begin
if Columns.Count > 1 then
begin
Columns.SaveToFile('Col_' + Owner.Name + Name + '.dat');
end;
end;
end;
end;
inherited;
end;
とりあえず動く形にはなったので完了とします。
もし問題点があれば助言いただくと幸いです。
ツイート | ![]() |