1. 程式人生 > >在DBGrid中可選中行而又可進入編輯狀態

在DBGrid中可選中行而又可進入編輯狀態

如何在DBGrid中選中行,而又讓它可以進入編輯狀態?
  也許你會問我這有什麼用?呵呵,做資料庫應用的兄弟們會深有感觸,當用DBGrid顯示的欄位過多時,使用者不得不拉動最下面的滾動條,去看最右邊的東西,如果沒有設定DBGrid->Options[dgRowSelect],那麼,拉到最右邊之後,很有可能看序列的;如果設定了DBGrid->Options[dgRowSelect],則在拉到最右邊之後,不會看序列,但是滑鼠點選其它行(不是當前選中行)時,DBGrid的檢視一下子就會回到顯示最左邊的那一列,確實很麻煩,使用者不得不一次又一次的拖運下面的滾動條。
  一同事因這個問題而苦惱,而我又在CSDN的文件庫中看到了這篇文章:
  《DBGrid使用全書(五)》,連結:http://dev.csdn.net/article/51/51845.shtm,是Delphi版本的,核心程式碼如下:
  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)
// 本文轉自 C++Builder研究 - http://www.ccrun.com/article.asp?i=637&d=2724wn
  {
      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);
  }
原文連結:

http://www.ccrun.com/article.asp?i=637&d=2724wn