Delphi Tips 
-----------------------------

キーワード:DataControls

>> Index

01/02 TField.EditMask の y2k 回避
09/09 DLL 内で TDBCtrlGrid を使うときの注意事項
08/28 データコントロールのDataLinkオブジェクトを取得する方法(ReadOnlyプロパティのバグの解決法)
02/11 DBGrid のスクロールバーを非表示に
02/08 StringGrid/DBGrid でのセル編集の動作を細かく指定する

最終更新: 9090 日前

0296  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 2000/01/02 osamu rev 1.3
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 2000/01/02 osamu 編集
TField.EditMask の y2k 回避

> DBEditで日付入力させるのですが、関連付けているTTable側の
> 日付フィールドのTFieldのEditMaskプロパティで

>  !99/99/00;1;_

>  ・・とマスクをかけています。
>  すると、西暦を下2桁で打つマスクが有効になるのですが
> 2000/05/05 の意で 00/05/05 とか打つと、期待した
> 2000/05/05にならずに、1900/05/05と表示されてしまいます。

OnCreate イベントハンドラ内で

    TwoDigitYearCenturyWindow := 50;
    ShortDateFormat := 'yyyy/mm/dd';

の設定を行うと,現在の年が1999年のとき,1999年の前後50年である
1949/1/1 から 2048/12/31 の100年を変換の対象として扱います.
ただし D4 からの機能のようです。

詳しくはヘルプか以下のサイトをご覧になられるとよいと思います.

    http://www.inprise.com/devsupport/y2000/

【追記】
Delphi 5 になってから TwoDigitYearCenturyWindow グローバル変数の初期値が「0」から「50」に変更されました。UI 簡略化等で西暦2桁年を使っているような場合、TwoDigitYearCenturyWindow 変数を設定しないまま日付型に変換しているような処理では、処理結果がD4以前と変わる場合があります。

ヘルプの記述(初期値は0)は誤っていますので、ご注意ください。
参照: [Delphi-ML:37908] [Delphi-ML:43093] <データベース> <コンポーネント >

0246  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/09/09 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/09/09 osamu 編集
DLL 内で TDBCtrlGrid を使うときの注意事項

>DLL化したアプリのフォームにDBCtrlGrid,DBCheckBoxを置いてローカルDB
>の内容を表示させているのですが、DLL化した途端にカレントレコードしか
>表示されなくなってしまいました。

この現象は以下の理由で発生します。

1.DLLの中では、何もしなければApplication.Handle=0です。
2.DBCtrlGridに配置されるコンポーネントの一部(DBCheckBoxを含む)はカレントレコード以外へ複製表示を行うために、Application.Handleを利用しています。

具体的にはDBCtrls.pasのTPaintControl.GetHandleで、次のようなコードで表示用の別ウインドウを生成しています。
  with Params do
    FHandle := CreateWindowEx(ExStyle, PChar(FClassName),
      PChar(TWinControlAccess(FOwner).Text), Style or WS_VISIBLE,
      X, Y, Width, Height, Application.Handle, 0, HInstance, nil);

Application.Handle=0 だと CreateWindowEXは失敗し、FHandle=0となるので複製表示が正常に行われないのです。

対処方法としては、Delphiヘルプの TApplication.Handle に書いてありますが、EXE ホストのメインウィンドウのウィンドウハンドルを DLL の Application.Handleに割り当てます。

別の方法としては、上記の TPaintControl.GetHandle の Application.Handle を FOwner.Handle に書き換えてもいいでしょう。

このスレッドではさらに、TApplication.MainForm.Handle を渡すべきか、TApplication.Handle を渡すべきか。また、TApplication.Handle を渡す際には、DLL 側の uses から Forms を削除しなければ、など、使い方に関する細かい注意点が議論されています。
参照: [Delphi-ML:33636] [Delphi-ML:33791] <データベース> <コンポーネント >

0222  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/08/28 西坂良幸 rev 1.2
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/08/28 西坂良幸 編集
データコントロールのDataLinkオブジェクトを取得する方法(ReadOnlyプロパティのバグの解決法)


VCLでは、DataControlのFDataLinkは、プロパティになっていないので、アクセスできませんが、
DataControlにCM_GETDATALINKメッセージを投げる事で取得(参照)できます。[Delphi-ML:41387]田原
多重継承ができないので、こうなっているそうです。

これによって、MLでも多い質問ですが、いわゆる「極東仕様」問題、すなわち、TDBEdit の ReadOnly と継承元の TCustomEdit のReadOnly の同期がとれないバグを解決することができます。[Delphi-ML:41051]藤中

以下は、藤中さんの例示コード(省略部あり)です。

// このデータコントロール(フィールド対応)は編集可能か?
function IsCanModifyFieldDataControl(Control: TControl) : Boolean;
var
  DataLink : TFieldDataLink;
begin
  // データリンクを取得
  DataLink := TFieldDataLink(Control.Perform(CM_GETDATALINK,0,0));
  if (DataLink = nil) then
     DatabaseError('CM_GETDATALINK は無効', Control);
  // データリンクが編集可能かどうか調べる
  Result := DataLink.CanModify and
          ( DataLink.DataSource.AutoEdit or
           (DataLink.DataSource.State in [dsInsert, dsEdit]) );
end;

// たとえば、Table1のAfterScrollイベントなどで動的にReadOnlyを変更する

type TCustomEditCracker = class(TCustomEdit);

procedure TForm1.Table1AfterScroll(DataSet: TDataSet);
var
  Flg :Boolean;
begin
  // 条件
  if DataSet.FieldByName('制御フラグ').AsString = '1' then
    Flg := True
  else
    Flg := False;
  // 以下でReadOnlyを変更
  DBEdit1.ReadOnly := Flg;
  if (Flg = False) then
  begin
    TCustomEditCracker(DBEdit1).ReadOnly :=
               not IsCanModifyFieldDataControl(DBEdit1);
  end
  else begin
    TCustomEditCracker(DBEdit1).ReadOnly := True;
  end;
end;

参照: [Delphi-ML:41387] [Delphi-ML:17611] [Delphi-ML:41051] <データベース> <バグ> <コンポーネント >

0165  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/11 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/11 osamu 編集
DBGrid のスクロールバーを非表示に

この DBGrid のスクロールバーを力で消す方法,大変参考になりました。じっと見ているとちらりと映りますが,言われなければたぶん誰も気づかないでしょう(^^)

>   private
>     { Private 宣言 }
>     FCellBottom : Integer;
>
> procedure TForm1.DBGrid1DrawColumnCell
> (Sender: TObject; const Rect: TRect;
> DataCol: Integer; Column: TColumn; State: TGridDrawState);
> begin
>   if (FCellBottom < Rect.bottom) then FCellBottom := Rect.bottom;
> end;
>
> procedure TForm1.Query1BeforeInsert(DataSet: TDataSet);
> begin
>   Abort;
> end;
>
> procedure TForm1.Query1AfterScroll(DataSet: TDataSet);
> begin
>   ShowScrollBar(DBGrid1.Handle, SB_VERT, False);
> end;
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   DBGrid1.Height := FCellBottom - DBGrid1.Top + 6;
> end;
参照: [Delphi-ML:31864] <データベース> <コンポーネント >

0009  D1   D2   D3   D4   D5   D6   D7   3.1   95   98    作成: 1999/02/08 osamu rev 1.1
   B1   B3   B4   B5   B6   B7   NT3   NT4   2K   XP  更新: 1999/02/08 osamu 編集
StringGrid/DBGrid でのセル編集の動作を細かく指定する

下のような関数を使って、TCustomGridで定義されているインプレースエディタを取得すれば、

    GetGridEditor(StringGrid1).SelStart:=0;

などとできます。

function GetGridEditor(Grid: TCustomGrid): TCustomEdit;
var i: Integer;
begin
    Result:=nil;
    for i:=0 to Grid.ControlCount-1 do
        if Grid.Controls[i] is TCustomEdit then begin
            Result:=TCustomEdit(Grid.Controls[i]);
            Exit;
        end;
end;
参照: [Delphi-ML:18726] <データベース> <Additional> <コンポーネント >

[新規作成] [最新の情報に更新]

How To
Lounge
KeyWords

Tips
Delphi
Home
Osamu Takeuchi osamu@big.or.jp

.