摘 要:本文給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下調試通過。