摘 要:本文给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下调试通过。