如何在DBGrid中選中行,而又讓它可以進入編輯狀態?
也許你會問我這有什麼用?呵呵,做數據庫應用的兄弟們會深有感觸,當用DBGrid顯示的字段過多時,用戶不得不拉動最下面的滾動條,去看最右邊的東西,如果沒有設置DBGrid->Options[dgRowSelect],那麼,拉到最右邊之後,很有可能看串行的;如果設置了DBGrid->Options[dgRowSelect],則在拉到最右邊之後,不會看串行,但是鼠標點擊其它行(不是當前選中行)時,DBGrid的視圖一下子就會回到顯示最左邊的那一列,確實很麻煩,用戶不得不一次又一次的拖運下面的滾動條。
核心代碼如下:
type
TMyDBGrid=class(TDBGrid);
//////////////////////////////////
//DBGrid1.Options->dgEditing=True
//DBGrid1.Options->dgRowSelect=False
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
with TMyDBGrid(Sender) do
begin
if DataLink.ActiveRecord=Row-1 then
begin
Canvas.Font.Color:=clWhite;
Canvas.Brush.Color:=$00800040;
end
else
begin
Canvas.Brush.Color:=Color;
Canvas.Font.Color:=Font.Color;
end;
DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;
end;
他的解決辦法是:曲線救國,取消DBGrid->Options[dgRowSelect],把當前選中行的背景繪制成藍色,就象是被選中一樣,想法確實很妙。我們公司使用C++Builder,我只好把這段代碼改為C++Builder版本的,這時,我才發現這段代碼的精妙之處。
我發現DataLink屬性是TCustomDBGrid中聲明為protected的,而在DBGrid中並未聲明它的可見性,因此,不能直接使用它;而Row屬性則是在TCustomGrid中聲明為protected的,在TCustomGrid的子類中也未聲明它的可見性,那麼,這段代碼為何在Delphi中運行的很好?
原因就在於:ObjectPascal的單元封裝,在同一個單元中定義的類,互相之間是友員的關系,我們再來看這段代碼的開頭:
type
TMyDBGrid = class(TDBGrid);
聲明了一個TMyDBGrid類,那麼,當前這個窗體類就和TMyDBGird類互為友元了,那麼當然當前窗體類可以直接訪問TMyDBGrid的私有屬性Row和DataLink了,一切都明了了,那麼用C++就好實現了,核心代碼如下:
void __fastcall TMainForm::LineSelEdit(TObject *Sender,const TRect &Rect, int DataCol, TColumn *Column,TGridDrawState State)
{
class TMyGridBase : public TCustomGrid
{
public:
__property Row;
};
class TMyGrid : public TCustomDBGrid
{
public:
__property DataLink;
};
TMyGrid *MyGrid = (TMyGrid*)Sender;
TMyGridBase *MyGridBase = (TMyGridBase*)Sender;
TDBGrid *Grid = (TDBGrid*)Sender;
if(MyGrid->DataLink->ActiveRecord == MyGridBase->Row-1) {
Grid->Canvas->Font->Color = clWhite;
Grid->Canvas->Brush->Color = TColor(0x00800040);
} else {
Grid->Canvas->Brush->Color = Grid->Color;
Grid->Canvas->Font->Color = Grid->Font->Color;
}
Grid->DefaultDrawColumnCell(Rect,DataCol,Column,State);
}
我把它封裝成一個函數,函數的參數與DBGrid的OnDrawDataCell的參數一樣,使用它的方法就是取消設置DBGrid->Options[dgRowSelect],然後設置DBGrid->DefaultDrawing = false,然後在這個DBGrid的OnDrawDataCell事件中調用這個函數,如下:
void __fastcall TMainForm::DBGridDrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
this->LineSelEdit(Sender,Rect,DataCol,Column,State);
}