ZC: 测试使用的控件是 Delphi7版本的 TAdvStringGrid(第3方控件)

  “DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);” 先绘制,

  “CustomCellDraw(Sender: TObject; Canvas: TCanvas; ACol, ARow: Integer; AState: TGridDrawState; ARect: TRect; Printing: Boolean);” 后绘制。

  于是 CustomCellDraw()中绘制的内容,位于DrawCell()绘制内容的上层

1、http://bbs.csdn.net/topics/350106894

  ZC: 主要是 CustomCellDraw()

2、StringGrid 中单元格的内容,是默认 左对齐的,无法设置属性使之 水平中间对齐,只能在 DrawCell()中自己绘制单元格内容。参考网址:

  http://blog.sina.com.cn/s/blog_54da9cc00101f2he.html

  http://bbs.csdn.net/topics/380112986

  http://bbs.csdn.net/topics/40272991

  2.1、ZC: 基本思路为两种(其实是一样的)

    2.1.1、使用 WinAPI:“DrawText(Canvas.Handle,PChar(s),Length(s),r,DT_CENTER or DT_SINGLELINE or DT_VCENTER);”

      ZC: 这个函数中有参数,可以自动使字符串 水平中间对齐。

    2.1.2、使用 Delphi7封装的Canvas.TextRect(Rect, X, Y, str);

      ZC: 这个函数,需要自己计算字符串所占用的像素宽度,然后 计算得到字符串开始的坐标(x,y),然后再 绘制字符串

      2.1.2.1、Canvas.TextWidth()/TextHeight() 可以得到 字符串的像素宽度/高度,代码跟进去,可以看到 它其实也是调用的 WinAPI “function GetTextExtentPoint32(DC: HDC; Str: PChar; Count: Integer;var Size: TSize): BOOL; stdcall;”

3、Delphi7 测试代码:

  ZC: 表格里 一共就处理了 4列(1~4)3行(1~3)数据

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DateUtils, Grids, BaseGrid, AdvGrid; type
Prelation = ^Rrelation;
Rrelation =record
FbUsing :Boolean;
FbDrawn :Boolean; // 已经画过了
Fnumber :Integer;
FiCol1, FiRow1 :Integer;
FiCol2, FiRow2 :Integer;
end; TForm1 = class(TForm)
Memo1: TMemo;
grid: TAdvStringGrid;
Button4: TButton;
Button5: TButton;
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure gridCustomCellDraw(Sender: TObject; Canvas: TCanvas; ACol,
ARow: Integer; AState: TGridDrawState; ARect: TRect;
Printing: Boolean);
procedure gridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
private
{ Private declarations }
public
Fcells :array [..,..] of Rrelation;
procedure CustomCellDraw();
procedure CustomCellDraw1(Canvas: TCanvas; ACol, ARow: Integer; AState: TGridDrawState; ARect: TRect);
end; var
Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button4Click(Sender: TObject);
var iCol, iRow :Integer;
begin
Fcells[, ].FbUsing := true;
Fcells[, ].Fnumber := ;
Fcells[, ].FiCol1 := -;
Fcells[, ].FiRow1 := -;
Fcells[, ].FiCol2 := ;
Fcells[, ].FiRow2 := ; Fcells[, ].FbUsing := True;
Fcells[, ].Fnumber := ;
Fcells[, ].FiCol1 := ;
Fcells[, ].FiRow1 := ;
Fcells[, ].FiCol2 := ;
Fcells[, ].FiRow2 := ; Fcells[, ].FbUsing := true;
Fcells[, ].Fnumber := ;
Fcells[, ].FiCol1 := ;
Fcells[, ].FiRow1 := ;
Fcells[, ].FiCol2 := -;
Fcells[, ].FiRow2 := -; for iRow:= to do
for iCol:= to do
grid.Cells[iCol, iRow] := IntToStr(iCol);
end; procedure TForm1.Button5Click(Sender: TObject);
begin
CustomCellDraw;
end; procedure TForm1.gridCustomCellDraw(Sender: TObject; Canvas: TCanvas; ACol,
ARow: Integer; AState: TGridDrawState; ARect: TRect; Printing: Boolean);
var bm :TBitmap;
p :Prelation;
rtSour, rtDest :TRect;
iWidth, iHeight :Integer;
ptMiddle, ptMiddle1, ptMiddle2 :TPoint;
rt1, rt2 :TRect;
begin
CustomCellDraw;
//CustomCellDraw1(Canvas, ACol, ARow, AState, ARect);
end; procedure TForm1.gridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var str :string;
w, h :Integer;
begin
str := grid.Cells[ACol, ARow];
if (Length(str)>) then
begin
//grid.Canvas.Brush.Color := clSilver;
grid.Canvas.FillRect(Rect); // 清空原来的背景色
DrawText(grid.Canvas.Handle, PChar(str), Length(str), Rect, DT_CENTER or DT_SINGLELINE or DT_VCENTER);
//TextRect State := [gdSelected];
end; //CustomCellDraw;
//CustomCellDraw1(grid.Canvas, ACol, ARow, State, Rect); end; procedure TForm1.FormCreate(Sender: TObject);
var p :Prelation;
i, j :Integer;
begin
for i:= to do
for j:= to do
Fcells[i,j].FbUsing := false;
// p := @(Fcells[1,1]);
// ZeroMemory(p, SizeOf(Rrelation)*12);
end; procedure TForm1.CustomCellDraw();
var bm :TBitmap;
p :Prelation;
rtSour, rtDest :TRect;
iWidth, iHeight :Integer;
ptMiddle, ptMiddle1, ptMiddle2 :TPoint;
rt, rt1, rt2 :TRect;
i, j :integer;
cv :TCanvas;
begin
for i:= to do
for j:= to do
begin
p := @(Fcells[i, j]); if (p.FbUsing)and(not p.FbDrawn) then
begin
p.FbDrawn := true; rt := grid.CellRect(i, j);
iWidth := rt.Right - rt.Left;
iHeight := rt.Bottom - rt.Top; ptMiddle.X := rt.Left + iWidth div ;
ptMiddle.Y := rt.Top + iHeight div ; rtDest.Left := ptMiddle.X - iHeight div ;
rtDest.Right:= rtDest.Left + iHeight;
rtDest.Top := rt.Top;
rtDest.Bottom := rt.Bottom; cv := grid.Canvas;
if (p.FiCol1<>-)and(p.FiRow1<>-) then
begin
rt1 := grid.CellRect(p.FiCol1, p.FiRow1);
ptMiddle1.X := rt1.Left + (rt1.Right - rt1.Left) div ;
ptMiddle1.Y := rt1.Top + (rt1.Bottom - rt1.Top) div ; cv.MoveTo(ptMiddle.X, ptMiddle.Y);
cv.LineTo(ptMiddle1.X, ptMiddle1.Y);
end;
if (p.FiCol2<>-)and(p.FiRow2<>-) then
begin
rt2 := grid.CellRect(p.FiCol2, p.FiRow2);
ptMiddle2.X := rt2.Left + (rt2.Right - rt2.Left) div ;
ptMiddle2.Y := rt2.Top + (rt2.Bottom - rt2.Top) div ; cv.MoveTo(ptMiddle.X, ptMiddle.Y);
cv.LineTo(ptMiddle2.X, ptMiddle2.Y);
end; bm := nil;
try
bm := TBitmap.Create;
bm.LoadFromFile('C:\Users\33\Desktop\D7_Test\bmp\_'+inttostr(p.Fnumber)+'.bmp');
rtSour.Left := ;
rtSour.Top := ;
rtSour.Right := bm.Width;
rtSour.Bottom := bm.Height; cv.CopyRect(rtDest, bm.Canvas, rtSour);//.Draw(ARect.Left, ARect.Top, bm);
finally
if bm<>nil then
bm.Free;
end;
end;
end; for i:= to do
for j:= to do
Fcells[i, j].FbDrawn := false;
end; procedure TForm1.CustomCellDraw1(Canvas: TCanvas; ACol, ARow: Integer; AState: TGridDrawState; ARect: TRect);
var bm :TBitmap;
p :Prelation;
rtSour, rtDest :TRect;
iWidth, iHeight :Integer;
ptMiddle, ptMiddle1, ptMiddle2 :TPoint;
rt1, rt2 :TRect;
begin
if (ACol>=)and(ACol<=)and(ARow>=)and(ARow<=) then
begin
p := @(Fcells[ACol, ARow]); if (p.FbUsing) then
begin
bm := nil;
iWidth := ARect.Right - ARect.Left;
iHeight := ARect.Bottom - ARect.Top; ptMiddle.X := ARect.Left + iWidth div ;
ptMiddle.Y := ARect.Top + iHeight div ; rtDest.Left := ptMiddle.X - iHeight div ;
rtDest.Right:= rtDest.Left + iHeight;
rtDest.Top := ARect.Top;
rtDest.Bottom := ARect.Bottom; if (p.FiCol1<>-)and(p.FiRow1<>-) then
begin
rt1 := grid.CellRect(p.FiCol1, p.FiRow1);
ptMiddle1.X := rt1.Left + (rt1.Right - rt1.Left) div ;
ptMiddle1.Y := rt1.Top + (rt1.Bottom - rt1.Top) div ; Canvas.MoveTo(ptMiddle.X, ptMiddle.Y);
Canvas.LineTo(ptMiddle1.X, ptMiddle1.Y);
end;
if (p.FiCol2<>-)and(p.FiRow2<>-) then
begin
rt2 := grid.CellRect(p.FiCol2, p.FiRow2);
ptMiddle2.X := rt2.Left + (rt2.Right - rt2.Left) div ;
ptMiddle2.Y := rt2.Top + (rt2.Bottom - rt2.Top) div ; Canvas.MoveTo(ptMiddle.X, ptMiddle.Y);
Canvas.LineTo(ptMiddle2.X, ptMiddle2.Y);
end; try
bm := TBitmap.Create;
bm.LoadFromFile('C:\Users\33\Desktop\D7_Test\bmp\_'+inttostr(p.Fnumber)+'.bmp');
rtSour.Left := ;
rtSour.Top := ;
rtSour.Right := bm.Width;
rtSour.Bottom := bm.Height; Canvas.CopyRect(rtDest, bm.Canvas, rtSour);//.Draw(ARect.Left, ARect.Top, bm);
finally
if bm<>nil then
bm.Free;
end;
end;
end;
end; end.

  3.1、效果图:

  ZC: 自己绘制了 3张bmp图片,自己绘制了 2根线

4、

5、

Grid_自绘的更多相关文章

  1. 关于DOM的操作以及性能优化问题-重绘重排

     写在前面: 大家都知道DOM的操作很昂贵. 然后贵在什么地方呢? 一.访问DOM元素 二.修改DOM引起的重绘重排 一.访问DOM 像书上的比喻:把DOM和JavaScript(这里指ECMScri ...

  2. arcgis api for js入门开发系列五地图态势标绘(含源代码)

    上一篇实现了demo的地图查询功能,本篇新增地图态势标绘模块,截图如下: 本篇核心的在于调用API的Draw工具:https://developers.arcgis.com/javascript/3/ ...

  3. android图片验证码--自绘控件

    自绘控件的内容都是自己绘制出来的 大致流程如下: 1.定义一个类继承view 使用TypedArray初始化属性集合 在view的构造方法中 有一个AttributeSet的参数 很明显是用来保存控件 ...

  4. 关于repaint(重绘)和reflow( 回流)

    repaint就是重绘,reflow就是回流.repaint主要是针对某一个DOM元素进行的重绘,reflow则是回流,针对整个页面的重排 严重性: 在性能优先的前提下,性能消耗 reflow大于re ...

  5. MFC 滑动条的重绘

    MFC自带的滑动条的样子是这样的. 比较难看,所以需要重绘下,重绘后的样子是这样的. 代码如下: CustomSliderCtr.h #pragma once // CCustomSliderCtr ...

  6. MFC 静态文本的自绘 空心字的实现

    想在对话框里,显示几个字是很简单的,只要用静态文本的输出就可以了.然而有时候我们需要显示特效的字,我们希望显示的文字就像Word里的艺术字一样,看起来美观.这时我们可以重写CStatic类.用Draw ...

  7. WinForm中重绘TabControl选项卡标题

    最近开发WinForm频繁使用了TabControl控件,这个控件的选项卡没有BackgroundImage这个属性,那么如何为其各个选项卡添加背景图片呢?(这里说的是每个TabPage的头部,也就是 ...

  8. 回流(reflow)与重绘(repaint)

    最近项目排期不紧,于是看了一下之前看了好久也没看明白的chrome调试工具的timeline.但是很遗憾,虽然大概懂了每一项是做什么的,但是用起来并不能得心应手.所以今天的重点不是timeline,而 ...

  9. 2013 duilib入门简明教程 -- 自绘标题栏(5)

        如果大家有做过标题栏的自绘,肯定会感慨各种不容易,并且现有的一些资料虽然完美的实现了功能,但是代码比较乱,需要自行整理.如果用duilib,就是小case啦.     duilib其实并没有区 ...

随机推荐

  1. ibatis 大于等于小于等于的写法

    在ibatis的sql语句xml配置文件中,写sql语句会经常用到大于等于小于等于等等符号.网上搜罗了一些写法,大致有3种: 其实就是xml特殊符号,转义的方式. < < > > ...

  2. 巨蟒python全栈开发django3:url&&视图

    1.url正则匹配分组和命名分组 2.路由分发 3.url别名和反向解析 4.httprequest和httpresponse的使用 内容回顾: .jinja2(flask框架,没有内置模板对象,需要 ...

  3. JLable设置复制粘贴

    final JLabel keyLable = new JLabel(key); keyLable.addMouseListener(new MouseAdapter() { @Override pu ...

  4. 2014-08-28——PC端几款主流浏览器的内核

    Trident(IE浏览器) Mozilla(Gecko)(熟悉的有Firefox,Flock等浏览器) WebKit(熟悉的有Safari.Chrome等浏览器) Opera(presto)(Ope ...

  5. DBProxy 入门到精通系列(一):DBProxy概述

    DBProxy概述 DBProxy是支持分库分表,读写分离的中间件,博客内容除了阅读github官方文档外,还会附加上本人个人测试的结果,但了解一个中间件,需要对这个中间件有一个基本的认识,方便控制. ...

  6. sql server监控图解

  7. postgrSQL 错误ERROR: permission denied

    赋权限: GRANT ALL PRIVILEGES ON TABLE 表名 TO 用户;

  8. Summaries On Java

    @1:== 和 equals(): ==用于比较引用和比较基本数据类型时具有不同的功能: 比较基本数据类型:如果两个值相同,则结果为true. 比较引用:如果引用指向内存中的同一对象,结果为true( ...

  9. 做测试时,启动SpringBoot出现警告,在ClassPath中一个类多次出现

    Found multiple occurrences of org.json.JSONObject on the class path: jar:file:/C:/Users/niaomingjian ...

  10. Python函数之—— 装饰器(Day13)

    一.什么是装饰器 顾名思义,装饰器指为其他函数添加新功能 装饰器定义:本质就是函数,功能是为其他函数添加新功能 二.装饰器需要遵循的原则 1.不修改被装饰函数的源代码(开放封闭原则) 2.为被装饰函数 ...