近日在DBGRID应用中涉及到需要对特殊数据进行显式的显示,于是设定指定单元格颜色、指定单元格根据数据显示向上或向下方向箭头。发现画箭头的和颜色指定的代码有一定的通用性,于是单独写出来,并且尽量优化了代码,以便于增强通用性。先拿出来以便分享。效果如下图所示:
//图片暂时没办法上传,似乎csdn后台目前有问题,稍后补上
整段代码如下[你可以根据自己的需要,修改相应的参数即可]:
procedure TfrmClientCenter.DBGrid2DrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);
var
tx,tn:Integer;
begin
//设定"上涨"的记录,指定特定单元格颜色
with Clientdataset do
begin
if (FieldByName('markup').AsString<>'') and (FieldByName('markup').AsInteger>0) then
begin
if (Column.Field=FieldByName('bargain')) then //是特定的字段则显示指定颜色
begin
DBGrid2.Canvas.Font.Color:=clRed; //指定红色字体
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('bargain').AsString);
end;
if (Column.Field=FieldByName('buy1')) then
begin
DBGrid2.Canvas.Font.Color:=clGreen; //指定绿色字体
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('buy1').AsString);
end;
if (Column.Field=FieldByName('high')) then
begin
DBGrid2.Canvas.Font.Color:=clRed;
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('high').AsString);
end;
if (Column.Field=FieldByName('low')) then
begin
DBGrid2.Canvas.Font.Color:=clRed;
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('low').AsString);
end;
if (Column.Field=FieldByName('aver')) then
begin
DBGrid2.Canvas.Font.Color:=clRed;
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('aver').AsString);
end;
if (Column.Field=FieldByName('tempmarkup')) then
begin
DBGrid2.Canvas.Font.Color:=clRed;
DBGrid2.Canvas.TextOut(Rect.Left,Rect.Top,Fieldbyname('tempmarkup').AsString);
end;
end;
end;
//画"涨/跌"箭头
{由于此处画箭头是根据"markup"的值为正负来确定的,所以画箭头的时候不能显示负号"-",于是我用了另一个字段'tempmarkup"来保存并用于显示无符号数值"markup"(前面已经处理了tempmarkup:=abs(markup)的动作),而"markup"本身在DBGRID中则不显示即可}
if Trim(Column.Field.DataSet.FieldByName('markup').AsString) <>'' then
begin
tx:=length(Column.Field.DataSet.Fields.FieldByName('tempmarkup').AsString); //数据实际长度
tn:=(tx+1)*5; //换算数据的显示长度{此段很重要,直接影响到箭头和数据的相对位置}
TDBGrid(Sender).DefaultDrawColumnCell(Rect,DataCol,Column,State);
if (Column.FieldName='tempmarkup') then
begin
with TDBGrid(Sender).Canvas do
begin
//正数画向上箭头
if Column.Field.DataSet.FieldByName('markup').AsInteger>0 then
begin
Pen.Color :=clRed ; //指定画箭头的颜色为红色
drawArrow(TDBGrid(Sender).Canvas,'up',Rect.Right-tx-tn-2,Rect.Bottom-6,Rect.Right-tx-tn-2,Rect.Top+2,5);
end;
//负数画向下箭头
if Column.Field.DataSet.FieldByName('markup').AsInteger<0 then
begin
Pen.Color :=Column.Font.Color; //指定画箭头的颜色为字段本身的颜色
drawArrow(TDBGrid(Sender).Canvas,'down',Rect.Right-tx-tn-2,Rect.Bottom-6,Rect.Right-tx-tn-2,Rect.Top+2,5);
end;
end;
end;
end;
end;
{说明: drawArrow(TDBGrid(Sender).Canvas,'up',Rect.Right-tx-tn-2,Rect.Bottom-6,Rect.Right-tx-tn-2,Rect.Top+2,5); 中用Rect.Right-tx-tn-2,是因为我的数据字段靠右对齐的,其中"-2"就是让箭头距离数据的距离,想要加大箭头和数据的距离就把2变大即可;当然如果你的数据是靠左对齐的,那么这里所有的减号,就要变成加号,变成Rect.Left+tx+tn+2。}
//画箭头函数体 {可以用不同的参数直接调用,无须更改}
procedure TfrmClientCenter.drawArrow(acanvas:Tcanvas;updown:string;x0,y0,x1,y1:Integer;arrowlen:real);
var
xa, ya, xb, yb: real;
d: real;
begin
acanvas.pen.style := pssolid;
//acanvas.pen.color := clRed ;
//画直线
acanvas.moveto(x0,y0); //箭头的起点
acanvas.lineto(x1,y1); //箭头的终点
//画箭头
if updown='up' then //向上箭头
begin
d := sqrt((y1 - y0) * (y1 - y0) + (x1 - x0) * (x1 - x0));
if d > 0 then
begin
xa := x1 + arrowlen * ((x0 - x1) + (y0 - y1) / 2) / d;
ya := y1 + arrowlen * ((y0 - y1) - (x0 - x1) / 2) / d;
xb := x1 + arrowlen * ((x0 - x1) - (y0 - y1) / 2) / d;
yb := y1 + arrowlen * ((y0 - y1) + (x0 - x1) / 2) / d;
acanvas.moveto(x1,y1);
acanvas.lineto(trunc(xa), trunc(ya));
acanvas.moveto(x1,y1);
acanvas.lineto(trunc(xb), trunc(yb));
end;
end;
if updown='down' then //向下箭头
begin
d := sqrt((y0 - y1) * (y0 - y1) + (x0 - x1) * (x0 - x1));
if d > 0 then
begin
xa := x0 - arrowlen * ((x0 - x1) + (y0 - y1) / 2) / d;
ya := y0 - arrowlen * ((y0 - y1) - (x0 - x1) / 2) / d;
xb := x0 - arrowlen * ((x0 - x1) - (y0 - y1) / 2) / d;
yb := y0 - arrowlen * ((y0 - y1) + (x0 - x1) / 2) / d;
acanvas.moveto(x0,y0);
acanvas.lineto(trunc(xa), trunc(ya));
acanvas.moveto(x0,y0);
acanvas.lineto(trunc(xb), trunc(yb));
end;
end;
end;