How To Custom Paint the Grid Control Using Custom Painters
- 3 minutes to read
If you need to custom paint grid View elements, the standard implementation is to handle associated events.
However, for some elements, the only way is to override methods of classes used to paint these elements. You will also need to override methods that return an appropriate painter class.
The ViewInfo and painter getters use a special naming convention. All methods that provide access to ViewInfo objects use the following identifier pattern: GetXXXViewInfoClass
. Use the GetPainterClass
method to access each instance of a painter class from the ViewInfo object.
To illustrate how you can implement custom paint tasks in these cases, consider the following example. Suppose you need to custom paint the master data row. The grid doesn’t have an associated event for this, so you’ll need to derive from TcxGridMasterDataRowViewInfo
and TcxGridMasterDataRowPainter
classes.
In the TcxGridMasterDataRowViewInfo
descendant, override the GetPainterClass
method, within which you return the TcxGridMasterDataRowPainter
‘s subclass.
Then, to inform the control that new classes are now used to display the master data row, implement descendants of the following classes and override the following methods:
The TcxGridMasterDataRow class and its
GetViewInfoClass
method.The TcxGridViewData class and its
GetRecordClass
method.The TcxGridTableView class and its
GetViewDataClass
method.The
TcxGridMasterDataRowViewInfo
class and itsGetPainterClass
method.
And lastly, override the TcxMyGridMasterDataRowPainter.DrawExpandButtonCell
method to paint the master data row’s expand button area with the specified color.
The following example demonstrates how to implement the master data row custom painting using the described inheritance mechanism:
// ...
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData, cxDataStorage, cxEdit, DB, cxDBData, cxGridLevel, cxGridCustomTableView, cxGridTableView, cxGridDBTableView, cxClasses, cxControls, cxGridCustomView, cxGrid, DBTables, cxGridRows;
type
TcxMyGridDBTableView = class(TcxGridDBTableView)
protected
function GetViewDataClass: TcxCustomGridViewDataClass; override;
end;
TcxMyGridViewData = class(TcxGridViewData)
protected
function GetRecordClass(ARecordInfo: TcxRowInfo): TcxCustomGridRecordClass; override;
end;
TcxMyGridMasterDataRow = class(TcxGridMasterDataRow)
protected
function GetViewInfoClass: TcxCustomGridRecordViewInfoClass; override;
end;
TcxMyGridMasterDataRowViewInfo = class(TcxGridMasterDataRowViewInfo)
protected
function GetPainterClass: TcxCustomGridCellPainterClass; override;
end;
TcxMyGridMasterDataRowPainter = class(TcxGridMasterDataRowPainter)
protected
procedure DrawExpandButtonCell; override;
end;
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
DataSource2: TDataSource;
Table2: TTable;
cxGrid1: TcxGrid;
cxGrid1DBTableView1: TcxGridDBTableView;
// ...
cxGrid1Level1: TcxGridLevel;
cxGrid1Level2: TcxGridLevel;
cxGrid2Level1: TcxGridLevel;
cxGrid2: TcxGrid;
cxGrid2Level2: TcxGridLevel;
cxGrid2DBTableView1: TcxGridDBTableView;
cxGrid2TableView1: TcxGridTableView;
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
cxGridDBDataDefinitions;
{ TcxMyGridDBTableView }
function TcxMyGridDBTableView.GetViewDataClass: TcxCustomGridViewDataClass;
begin
Result := TcxMyGridViewData;
end;
{ TcxMyGridViewData }
function TcxMyGridViewData.GetRecordClass(
ARecordInfo: TcxRowInfo): TcxCustomGridRecordClass;
begin
if GridView.IsMaster then
Result := TcxMyGridMasterDataRow
else
Result := inherited GetRecordClass(ARecordInfo);
end;
{ TcxMyGridMasterDataRow }
function TcxMyGridMasterDataRow.GetViewInfoClass: TcxCustomGridRecordViewInfoClass;
begin
Result := TcxMyGridMasterDataRowViewInfo;
end;
{ TcxMyGridMasterDataRowViewInfo }
function TcxMyGridMasterDataRowViewInfo.GetPainterClass: TcxCustomGridCellPainterClass;
begin
Result := TcxMyGridMasterDataRowPainter;
end;
{ TcxMyGridMasterDataRowPainter }
procedure TcxMyGridMasterDataRowPainter.DrawExpandButtonCell;
var
ABounds: TRect;
begin
Canvas.Brush.Color := $4FC8FB;
ABounds := TcxMyGridMasterDataRowViewInfo(ViewInfo).ExpandButtonCellViewInfo.Bounds;
Canvas.FillRect(ABounds);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
AView: TcxMyGridDBTableView;
begin
cxGrid2.BeginUpdate;
try
AView := TcxMyGridDBTableView(cxGrid2.CreateView(TcxMyGridDBTableView));
AView.Assign(cxGrid1DBTableView1);
cxGrid2Level1.GridView := AView;
AView := TcxMyGridDBTableView(cxGrid2.CreateView(TcxMyGridDBTableView));
AView.Assign(cxGrid1DBTableView2);
cxGrid2Level2.GridView := AView;
finally
cxGrid2.EndUpdate;
end;
end;
end.
Here is the code execution result: