天天看點

TDBGRID一些小技巧 .

摘  要:本文給TDBGrid增加了dgThumbTracking、及dgMouseWheel兩個選項,用來支援滾動條的跟蹤和滑鼠滾輪。以及有關DBGrid行列顔色的一個技巧。

關鍵詞:C++Builder  TDBGrid  ThumbTracking  MouseWheel  控件

  TDBGrid是資料庫應用程式不能不使用的一個控件,它功能出奇的強大,基本上可以完成所有資料報表的顯示,甚至還可以顯示ADT和數組字段;TDBGrid的操作也很簡單,比如固定字段的轉換,實用又友善,它的屬性、方法、事件等也都很直覺;但就像能耐大的人都有點脾氣一樣,TDBGrid也有一些讓我們不好了解的行為,其中大家談論最多就是它怪異的鍵盤操作方式。

  我在實際應用中感到很奇怪的是TDBGrid經TCustomDBGrid從TCustomGrid派生而來,卻為什麼不再支援TCustomGrid的goThumbTracking選項,滾動條的實時跟蹤是很實用的,無法想象浏覽一個記錄集時,非要放開滑鼠鍵才能知道滾動到記錄集的什麼位置。另外,TDBGrid對滑鼠滾輪的支援有問題,當使用滾輪時,隻是滾動了輸入框,而沒有滾動記錄集,出現了焦點與目前記錄不一緻的錯誤。

  技巧一、二,提供滾動條的實時跟蹤及滑鼠滾輪的支援。

  直接從TDBGrid繼承,建立一個TJDBGrid控件,增加了dgThumbTracking、及dgMouseWheel兩個選項,源碼如下:

  //JDBGrid.h檔案内容

//-------------------------------------------------------------------------  #ifndef JDBGridH

  #define JDBGridH

//-------------------------------------------------------------------------  #include <SysUtils.hpp>

  #include <Classes.hpp>

  #include <Controls.hpp>

  #include <DBGrids.hpp>

  #include <Grids.hpp>

//-------------------------------------------------------------------------  class PACKAGE TJDBGrid : public TDBGrid

  {

  enum TDBGridOption{ dgEditing, dgAlwaysShowEditor,

                       dgTitles, dgIndicator, dgColumnResize,

                       dgColLines, dgRowLines, dgTabs,

                       dgRowSelect, dgAlwaysShowSelection,

                       dgConfirmDelete, dgCancelOnExit,

                       dgMultiSelect ,dgThumbTracking,dgMouseWheel};

  typedef Set<TDBGridOption,dgEditing,goThumbTracking>  TDBGridOptions;

  private:

          TDBGridOptions FOptions;

  protected:

          TWndMethod DBGridProc;

          TWndMethod DBInplaceEditProc;

          virtual void __fastcall JDBInplaceEditProc(Messages::TMessage &Message);

          virtual void __fastcall JDBGridProc(Messages::TMessage& Message);

          virtual Grids::TInplaceEdit* __fastcall CreateEditor(void);

          void __fastcall SetOptions(TDBGridOptions Value);

  public:

  __fastcall TJDBGrid(TComponent* Owner);

  __published:

__property TDBGridOptions Options = {read=FOptions, write=SetOptions,default=27901};

  };

  //-------------------------------------------------------------------------

  #endif

//JDBGrid.cpp檔案内容

//-------------------------------------------------------------------------  #include <vcl.h>

  #pragma hdrstop

  #include "JDBGrid.h"

  #pragma package(smart_init)

 //-------------------------------------------------------------------------         static inline void ValidCtrCheck(TJDBGrid *)

  {

          new TJDBGrid(NULL);

  }

//-------------------------------------------------------------------------fastcall TJDBGrid::TJDBGrid(TComponent* Owner):TDBGrid(Owner)

  {

     short *shortTmp;

     Dbgrids::TDBGridOptions optionsTmp;

     (void*)shortTmp=(void*)&FOptions;

     *shortTmp=27901;

     (void*)shortTmp=(void*)&optionsTmp;

     *shortTmp=3325;

     TDBGrid::Options=optionsTmp;

     DBGridProc=WindowProc;

     WindowProc=JDBGridProc;

  }

//-------------------------------------------------------------------------  void __fastcall TJDBGrid::SetOptions(TDBGridOptions Value)

  {

     short *pValue,*pOp,*pFOp,saveValue;

     Dbgrids::TDBGridOptions DBGridOptions;

     (void*)pValue=(void*)&Value;

     (void*)pOp=(void*)&DBGridOptions;

     (void*)pFOp=(void*)&FOptions;

     *pOp=*pValue & 0x1fff;

     TDBGrid::Options=DBGridOptions;

     DBGridOptions=TDBGrid::Options;

     *pFOp=*pOp | (*pValue & 0x6000);

  }

  //-------------------------------------------------------------------------  void __fastcall TJDBGrid::JDBInplaceEditProc(Messages::TMessage &Message)

  {

     switch (Message.Msg)

     {

        case WM_MOUSEWHEEL:

           if(Options.Contains(dgMouseWheel))

           {

              if (DataLink->Active)

              {

               if (Message.WParam<0)

                 {

                if (DataLink->DataSet->RecNo<DataLink->DataSet->RecordCount)

                DataLink->DataSet->RecNo++;

                 }

                 else

                 {

                    if (DataLink->DataSet->RecNo>1)

                       DataLink->DataSet->RecNo--;

                 }

              }

              if (!Options.Contains(dgAlwaysShowEditor))

                 EditorMode=false;

              return;

           }

        break;

     }

     DBInplaceEditProc(Message);

  }

//-------------------------------------------------------------------------  Grids::TInplaceEdit* __fastcall TJDBGrid::CreateEditor(void)

  {

     TInplaceEdit *tmp;

     tmp=TDBGrid::CreateEditor();

     DBInplaceEditProc=tmp->WindowProc;

     tmp->WindowProc=JDBInplaceEditProc;

     return tmp;

  }

 //-------------------------------------------------------------------------  void __fastcall TJDBGrid::JDBGridProc(Messages::TMessage& Message)

  {

     switch (Message.Msg)

     {

        case WM_VSCROLL:

        case WM_HSCROLL:

           if (Options.Contains(dgThumbTracking))

              if (Message.WParamLo==5)

              {

                 DBGridProc(Message);

                 Message.WParamLo=4;

                 DBGridProc(Message);

                 Message.WParam=8;

              }

        break;

        case WM_MOUSEWHEEL:

           if(Options.Contains(dgMouseWheel))

           {

              DBGridProc(Message);

              if (DataLink->Active)

              {

                 if (Message.WParam<0)

                 {

              if (DataLink->DataSet->RecNo<DataLink->DataSet->RecordCount)

              DataLink->DataSet->RecNo++;

                 }

                 else

                 {

              if (DataLink->DataSet->RecNo>1)

              DataLink->DataSet->RecNo--;

                 }

              }

              if (!Options.Contains(dgAlwaysShowEditor))

              EditorMode=false;

              return;

           }

        break;

     }

     DBGridProc(Message);

  }

  //-------------------------------------------------------------------------

  namespace Jdbgrid

  {

          void __fastcall PACKAGE Register()

          {

                   TComponentClass classes[1] = {__classid(TJDBGrid)};

                   RegisterComponents("Samples", classes, 0);

          }

  }

  //-------------------------------------------------------------------------

  技巧三,行列不同顔色時,交叉部位顔色的設定。

  如圖:在交叉部位使用行列顔色的alpha混合。

響應TDBGrid的OnDrawColumnCell事件如下:

    void __fastcall TForm1::JDBGrid1DrawColumnCell(TObject *Sender,

          const TRect &Rect, int DataCol, TColumn *Column,

          TGridDrawState State)

    {

       int recordNo,tmpInt;

       if (JDBGrid1->DataSource->DataSet->Active)

       {

          recordNo=DataCol=JDBGrid1->DataSource->DataSet->RecNo % 10;

          if (recordNo ==0 || recordNo>5 )

             JDBGrid1->Canvas->Brush->Color=0xb0b0ff;

          else

             JDBGrid1->Canvas->Brush->Color=0xffe0e0;

          tmpInt=Column->Color;

          if (tmpInt!=clWindow)

          {

              int R1,G1,B1,R2,G2,B2,rgbTmp;

              int alpha=60;

              rgbTmp=JDBGrid1->Canvas->Brush->Color;

              R1=tmpInt & 0xff;

              G1=(tmpInt & 0xff00)>>8;

              B1=(tmpInt & 0xff0000)>>16;

              R2=rgbTmp & 0xff;

              G2=(rgbTmp & 0xff00)>>8;

              B2=(rgbTmp & 0xff0000)>>16;

              R1=(R1*alpha+R2*(256-alpha))>>8;

              G1=(G1*alpha+G2*(256-alpha))>>8;

              B1=(B1*alpha+B2*(256-alpha))>>8;

              JDBGrid1->Canvas->Brush->Color=(TColor)(R1+(G1<<8)+(B1<<16));

          }

          JDBGrid1->Canvas->FillRect(Rect);

       }

       JDBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);

    }

  以上代碼在C++Builder 6.0 Windows XP下調試通過。