在一个图片管理程序中,为了提高效率,我没有把图片的资料放入DataController.Values[i]中,而是通过TcxGridBandedTableColumn.OnCustomDrawCell来自己绘制。
procedure TFormImageRepository.CustomDrawImage(AOID: integer;
ACanvas: TCanvas; ARect: TRect;AIsExpand:Boolean);
var
ABmp:TGraphic;
AData:AnsiString;
AFormat:WideString;
R:TRect;
begin
ABmp:=ThumbnailList.Find(InttoStr(AOID));
if ABmp=nil then
begin
if FDataSetImage.Locate('OID',AOID,[]) and
not FDataSetImage.FieldByName('Thumbnail').IsNull then
begin
AData:=FDataSetImage.FieldByName('Thumbnail').AsString;
AFormat:=VarToWideStr(FDataSetImage.FieldByName('Format').asVariant);
if VarIsNull(AFormat) then AFormat:='';
//缩略图都是bmp格式
ABmp:=ThumbnailList.AddThumbnail(InttoStr(AOID),AData);
end;
end;
ACanvas.Pen.Color:=ACanvas.Brush.Color;
ACanvas.Rectangle(ARect);
if ABmp<>nil then
begin
R:=ARect;
R:=TThumbnailList.GetStretchRect(R,ABmp.Width,ABmp.Height,AIsExpand);
if AIsExpand then
ACanvas.StretchDraw(R,ABmp)
else
ACanvas.Draw(R.Left,R.Top,ABmp);
end;
end;
这样的处理在画面上看起来效果很好。
同样,需要在TdxCompoentPrinter的TdxGridReportLink中也处理CustomDraw,首先,设置其SupportedCustomDraw=true,然后在其OnCustomDrawCell事件处理:
但是打印预览时,完全看不到图片。
跟踪发现,AnItem.BoundsRect的坐标非常大,Left=46050;Right=51300,这个Cell的宽度是5250,远远超过Screen.Width的大小,因此看起来这里计量单位不是所谓的Pixel,我们图片相对于这样的坐标系,实在太小,根本看不见了,验证一下,画个椭圆:
可以看到这个椭圆很正确的显示出来了。
那么屏幕和打印机的这个尺寸的大小比例因子到底是多少呢?我们应该把图片放大多少倍来绘制呢?上面说了,Cell的宽度是5250,而我们的Column.Width是100,这个因子是5250/100吗?修正一下之前的函数,试试看:
procedure TFormImageRepository.ReportLink_ImageCustomDrawCell(
Sender: TdxGridReportLink; ACanvas: TCanvas;
AView: TcxCustomGridTableView; ARecord: TcxCustomGridRecord;
AColumn: TcxGridColumn; AnItem: TAbstractdxReportCellData;
var ADone: Boolean);
var
AOID:integer;
begin
inherited;
if AColumn=Column_Picture then
begin
AOID:=ARecord.Values[Column_ImageOID.Index];
CustomDrawImage(AOID,ACanvas,AnItem.BoundsRect,false,Round(AnItem.Width/AColumn.Width));
ADone:=true;
end;
end;
看看效果,图片显示出来了,但是看起来放得大了点,与在画面中看到的效果有点不一样,这个比例因子还是不太对,为什么呢?
突然想到,TdxGridReportLink.OptionSize.AutoWidth设置为了True,那么Column的实际大小会根据纸张变化,所以应该使用Column的实际大小,这个值需要从ViewInfo获得:
ok,这样看起来比例就很协调了,这个比例因子是50。(上面在获得ColumnViewInfo的时候注意要使用AColumn.VisibleIndex,不要用Index,因为VisibleIndex考虑的是看到的Column,隐藏的不算)
末了,还要问问,这个比例因子devexpress是如何计算出来的,高中时的毛吉中老师说“打破砂锅问到底,还要看渣渣在哪里?”赶紧追踪一下AnItem.Width如何来的,TAbstractdxReportCellData定义在dxPSCore.pas,其祖先是TdxReportVisualItem,查看其成员函数,发现一个感兴趣的:
再查查看谁调用了这个函数,找到了这个:
再看看PixelsNumerator和PixelsDenominator的值,这两个公用函数,用到两个全局变量:
function PixelsDenominator: Integer;
begin
Result := FPixelsDenominator;
end;
var
FPixelsDenominator: Integer;
FPixelsNumerator: Integer;
单元initialization部分初始化了这个变量:
var
FUnitsPerInch: Integer = 4800;
对我们的windowsXP,一般Screen.PixelsPerInch=96,4800/96=50,这就是打印机的像素与屏幕像素的比例。再仔细一看,恰好有一个函数告诉了我们这个比例:
因此,我们的CustomDrawCell就可以直接写成这样了: