转载:http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579185.html

基本绘图操作(Basic Drawing Operations)

现在大家已经知道Rectangle方法用来画正方形和矩形,Ellipse方法用来画圆和椭圆,MoveTo和LineTo方法则用来画线。

还有Arc方法用于画弧,Pie方法用于画饼形,一切一切都是非常基础的,没有太大的必要详细了解TCanvas的这些方法,下面开始更有趣的图形操作,这些图形操作在编写Delphi应用程序时很可能遇到。

绘制文本(Drawing Text)

绘制文本听起来不像太难,是么?实际上有一些容易犯的小错误,如果不加注意,可能会使绘制文本变得很困难,另外有几条好的文本绘制特性应该了解。

1、TextOut与TextRect方法(The TextOut and TextRect Methods)

TextOut方法是在画布上绘制文本的最基本的方法,关于TextOut没有太多可讲的,只需输入X,Y位置和要显示的文本——例如:

1
Canvas.TextOut(20, 20, '最简单的文本输出');

这个代码在窗体上位置20,20处显示指定的字符串。


X、Y坐标是指所要绘制文本的左上角而不是底线,为了说明这个意思,试验这段代码:

1
2
3
Canvas.TextOut(20, 20, 'This is a text');
Canvas.MoveTo(20, 20);
Canvas.LineTo(100, 20);

这段代码(20,20)处显示一些文字并从这个位置到(100,20)画线。如下图,显示了这段代码的执行结果。注意直线画在文本上部。

每当要显示文本时,使用TextOut不需要许多精确定位。


TextRect方法要求指定要显示的文本,还要指定剪切矩形框。当文本需要限制在一定的界域内时使用这种方法。落在界线外的文本均被剪掉,下面代码确保显示不超过100像素的文本。

1
2
Canvas.TextRect(Rect(20, 50, 120, 70), 20, 50,
  '这是非常长的一行文字,可能会被裁减掉');

显示如下,因为字符串长度超过了100像素,因此被裁减掉了。

TextOut和TextRect都只能绘制单行文字,不能对文本进行换行。

Tip

To draw text with tab stops, see the Windows API function TabbedTextOut.

输出具有制表符的文本,参见Windows API函数TabbedTextOut。

2、文本背景(Text Backgrounds)

改变文本背景颜色是非常容易的,因此可以这样做,如下代码:

1
Canvas.Brush.Color := clWhite;

显示效果如下:


在进行设置背景色的时候应该养成这种习惯,即先存储先前的刷子类型,处理完文本后再恢复到原来的类型。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var
  OldStyle: TBrushStyle;
  OldColor: TColor;
begin
  ClearCanvas;
  OldStyle := Canvas.Brush.Style;
  OldColor := Canvas.Brush.Color;
  Canvas.Brush.Color := clRed;
  Canvas.TextOut(20, 20, '现在文本的背景色为红色了');
  Canvas.Brush.Style := OldStyle;
  Canvas.Brush.Color := OldColor;
  Canvas.TextOut(20, 50, '现在又恢复原始的样式了');
end;

显示效果如下:

如果要使用文本透明背景,可将刷子类型设置为bsClear。如下代码:

1
Canvas.Brush.Style := bsClear;

使用透明背景还有其他好处,比如说要在图像背景上显示一些文本,在这种情况下,使用透明背景输出文本比较理想,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var
  OldStyle: TBrushStyle;
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;
  Bitmap.LoadFromFile('handshak.bmp');
  Canvas.Draw(0, 0, Bitmap);
  Canvas.Font.Name := 'Arial Bold';
  Canvas.Font.Size := 13;
  OldStyle := Canvas.Brush.Style;
  Canvas.Brush.Style := bsClear;
  Canvas.TextOut(20, 5, '透明背景色文本');
  Canvas.Brush.Style := OldStyle;
  Canvas.TextOut(20, 30, '非透明背景色文本');
  Bitmap.Free;
end;

这个代码在窗体上画位图,之后在窗体位图上用透明背景绘制文本,在以常规样式绘制文本,效果如下:


3、DrawText函数(The DrawText Function)

Windows API的DrawText函数提供了比TextOut更大的制作画布上的文本的控制能力,基于某种原因,TCanvas类没有DrawText方法。使用DrawText则意味着直接使用API。首先看一看一个基本的DrawText例子,然后再讲述这个函数的更多用途。

1
2
3
4
5
6
7
8
var
  R: TRect;
begin
  R := Rect(20, 20, 220, 80);
  Canvas.Rectangle(20, 20, 220, 80);
  DrawText(Canvas.Handle, 'An example of DrawText.', -1, R,
    DT_SINGLELINE or DT_VCENTER or DT_CENTER);
end;

下图显示了该代码结果以及下面几个例子的结果。

首先TRect记录利用Windows API Rect函数初始化。之后,一个规则的矩形绘制于画布上(矩形画于画布上以便可以设想所要画的矩形大小)。最后,调用DrawText函数绘制文本。

1
2
3
4
5
6
7
8
//DrawText函数的声明如下:
DrawText(
  hDC: HDC;          {设备句柄}
  lpString: PChar;   {文本}
  nCount: Integer;   {要绘制的字符个数; -1 表示全部}
  var lpRect: TRect; {矩形结构}
  uFormat: UINT      {选项}
): Integer;          {返回文本高度}

下面详解讨论下函数的各种参数,如下所示:

  • 第一个参数用来指定绘制的设备描述环境。TCanvas的Handle属性是画布的HDC。因此输入它作为第一参数。
  • 第二个参数是将要显示的字符串。
  • 第三个参数是用于指定要绘制的字符数,但参数为-1时,字符串中所有字符都绘制。
  • 第四个参数是var TRect,这个参数是var参数,因为DrawText操作修改矩形。
  • 最后一个参数是指定绘制文本时使用的标志,在这个例子中使用了DT_SINGLELINE(单行文本)、DT_VCENTER(垂直居中)和DT_CENTER(水平居中)标志。DrawText一共有将近20个标志可供指定。这里不打算讲每一个标志,全部标志参见Win32 API帮助。

前面的例子说明了DrawText函数一个最为普遍的用途;使文本水平居中、垂直居中等。在自制组件时这个特性非常有用。特别地,自制列表框、组合框和菜单经常需要使文本居中。现在可能不会马上认识到这个函数的好处。但是,若开始做自制组件时或者开始写自己的图形组件时,就会认识到这一点。

DrawText另一个有趣的标志是DT_END_ELLIPSIS标志,如果文本太长不能套入指定矩形中,Windows将截取部分字符串,末尾加上省略号,表示字符串被截取,例如,下面的代码:

1
2
3
4
5
6
var
  R: TRect;
begin
  R := Rect(20, 20, 120, 70);
  DrawText(Canvas.Handle, 'This text is too long to fit', -1, R, DT_END_ELLIPSIS);
end;

这段执行后,结果文本显示如下图:

如果矩形内文本可能太长的话,可以使用这种标志。


DT_CALCRECT是又一个非常有用的标志,它用来计算容纳指定文本所需的矩形高度。当使用这个标志时,Windows计算所需高度,并返回这个高度,但不绘制文本。用户告诉Windows矩形框应多宽,Windows将告诉用户容纳的文本所需矩形多高。事实上,Windows也修改矩形的bottom和left值。绘制多行文本时,这显的尤为重要。

下列程序例子询问Windows要包含所有文本所需的矩形框多高。之后,在屏幕上画出矩形框,最后文本绘制在矩形框中。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
var
  R: TRect;
  S: string;
begin
  R := Rect(20, 20, 150, 30);
  S := 'This is a very long string which will' +
    'run into multiple lines of text.';
  DrawText(Canvas.Handle, PChar(S), -1, R, DT_CALCRECT or DT_WORDBREAK);
  Canvas.Brush.Style := bsSolid;
  Canvas.Rectangle(R);
  Canvas.Brush.Style := bsClear;
  DrawText(Canvas.Handle, PChar(S), -1, R, DT_WORDBREAK);
end;

最后运行该代码,效果如下:

注意,必须将DrawText的第二个参数由string类型转化为PChar类型,这是因为DrawText需要的参数是指向字符数组的指针,而不是字符串类型本身。

将上面的代码进行多次执行,每次修改显示的字符串长度。不管怎么增加字符,矩形框总能准确框住文本。

Note

如果编写适应各种版本的Delphi程序,就不能像上面那样将string强制转化为PChar类型,因为Delphi1下不能编译,必须采用StrPCopy函数来使用,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.btn10Click(Sender: TObject);
var
  R: TRect;
  S: string;
  temp: array[0..100] of Char; { 至少要有 length(s) + 1 的空间大小}
begin
  R := Rect(20, 20, 150, 30);
  S := 'This is a very long string which will' +
    'run into multiple lines of text.';
  { 采用StrPCopy函数转化string类型为PChar类型}
  DrawText(Canvas.Handle, StrPCopy(temp, S), -1, R, DT_CALCRECT or DT_WORDBREAK);
  Canvas.Brush.Style := bsSolid;
  Canvas.Rectangle(R);
  Canvas.Brush.Style := bsClear;
  DrawText(Canvas.Handle, StrPCopy(temp, S), -1, R, DT_WORDBREAK);
end;

如果不考虑低版本的Delphi,则不必使用StrPCopy函数。

Note

用DrawText绘制文本比使用TextOut稍慢一些,若绘制操作对速度反应敏感,应该使用TextOut而不应该使用DrawText。用户自己必须做更多的工作,但是执行速度将可能更快。当然,对于大多数的文本绘制,不必注意TextOut与DrawText之间的差别。

特别写了一个效率比较的程序,通过统计执行相同工作所需的时间来判断。具体代码请大家自行下载示例代码查看,这里不再贴出。如下图:

DrawText函数是一个非常有用并且功能强大的函数,当编写自己组件时,毫无疑问,这种函数将经常被使用。


以上代码均在Delphi7下测试通过,示例代码下载:GDI之绘制文本.rar

Delphi GDI对象之绘制文本的更多相关文章

  1. Delphi GDI对象之绘制位图

    http://www.cnblogs.com/pchmonster/archive/2012/07/06/2579334.html 绘制位图(Drawing Bitmaps) 绘制位图听起来似乎很难, ...

  2. Delphi GDI对象之脱屏位图(Offscreen Bitmaps),也叫内存位图

    http://www.cnblogs.com/pchmonster/archive/2012/07/09/2583613.html 脱屏位图(Offscreen Bitmaps) 脱屏位图,也叫内存位 ...

  3. Delphi GDI对象之脱屏位图(Offscreen Bitmaps)

    脱屏位图(Offscreen Bitmaps) 脱屏位图,也叫内存位图,普遍用于Windows程序设计中.它在内存中制作图像,然后利用Draw方法在屏幕上显示出来.当用户想更快的在屏幕上绘制图像时,脱 ...

  4. Delphi GDI对象之剪切区域

    原文链接: http://www.cnblogs.com/pchmonster/archive/2012/07/05/2577627.html 剪切区域(Clipping Regions) Regio ...

  5. 『备注』GDI+ 绘制文本有锯齿,透明背景文本绘制

    背景: GDI+ 绘制文本 时,如果 背景是透明的 —— 则会出现 锯齿. //其实,我不用这三个 属性 好多年了 //而且,这三个属性 在关键时刻还有可能 帮倒忙 //关键是:这三个属性,鸟用都没有 ...

  6. GDI基础(2):绘制文本

    1.TextOut()和DrawText()函数 CDC::TextOut()在窗口的指定位置处输出文本,函数声明: virtual BOOL TextOut(int x, int y, LPCTST ...

  7. 使用GDI绘制文本

    /// <summary>        /// 定义一个绘制文本        /// </summary>        public void Texts()       ...

  8. 使用WebBrowser控件时在网页元素上绘制文本或其他自定义内容

    原文:使用WebBrowser控件时在网页元素上绘制文本或其他自定义内容 第一次在CNBlogs上发Post是提出一个有关使用WebBrowser控件时对SELECT网页元素操作的疑惑,这个问题至今也 ...

  9. Win32汇编学习(5):绘制文本2

    这次我们将学习有关文本的诸多属性如字体和颜色等. 理论: Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,B 代表蓝色.如果您想指定一种颜色就必须给该颜色赋相关的 RGB ...

随机推荐

  1. solr 单机模式搭建

    系统环境:centos 7 安装前准备 安装JDK环境 下载tomcat.solr安装包:solr下载地址:http://archive.apache.org/dist/lucene/solr/ 安装 ...

  2. 目录扫描工具DirBuster

    DirBuster是用来探测web服务器上的目录和隐藏文件的.因为DirBuster是采用java编写的,所以运行前要安装上java的环境. 来看一下基本的使用: ①:TargetURL下输入要探测网 ...

  3. vue+axios+promise实际开发用法

    axios它是基于promise的http库,可运行在浏览器端和node.js中,然后作者尤雨溪也是果断放弃了对其官方库vue-resource的维护,直接推荐axios库,小编我也是从vue-res ...

  4. Hive和Hbase整合

    Hive只支持insert和delete操作,并不支持update操作,所以无法实施更新hive里的数据,而HBASE正好弥补了这一点,所以在某些场景下需要将hive和hbase整合起来一起使用. 整 ...

  5. Python 模块和包的概念

    模块&包(* * * * *) 模块(modue)的概念: 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函 ...

  6. Oracle联合主键

    转https://www.cnblogs.com/king-xg/p/6721272.html alter table tablename add constraint unionkeyname pr ...

  7. bs4--官方文档

    如何使用 将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄. from bs4 import BeautifulSoup soup = ...

  8. python基础——10(三元运算符、匿名函数)

    一.三元运算符 本质是if--else--的语法糖 前提:简化if--else--的结构,且两个分支有且只有一条语句 案例: a = 20 b = 30 res = a if a > b els ...

  9. 解决img标签上下出现间隙的方法

    图片与父元素下边缘有 2px 的间隙,并不是因为空格.多个 inline-block 元素之间的间隙才是因为空格. 任何不是块级元素的可见元素都是内联元素,其表现的特性是“行布局”形式.----< ...

  10. Django中的app及mysql数据库篇(ORM操作)

    Django常见命令 在Django的使用过程中需要使用命令让Django进行一些操作,例如创建Django项目.启动Django程序.创建新的APP.数据库迁移等. 创建Django项目 一把我们都 ...