C++ Builder 第七章 图形

本章涵盖了VCL的图形编程的基本知识 .vcl封装了Windows图形设备接口,或GDI。 GDI 的方案可能是一个微妙而危险的进程。 塔梅斯这项技术并使其非常容易使用。

在下面的页面中,您将了解到:

 

  • The TCanvas object 画布对象

     

  • Painting shapes on the screen 在屏幕上画形状

     

  • Working with colors 同色

     

  • Working with bitmaps  与位图

     

  • Working with metafiles  与图元文件

     

  • Drawing fractals  绘图形

     

  • Working with fonts  与字体

 

重要的是要理解基本图形功能这里是从你在第28章,“游戏编程见过的DirectX程序查找先进的工具相距甚远。” 这只是基本的功能需要本标准的Windows程序.然而,在这一章所提供的材料是有用的大多数程序标准的Windows,它的核心是知识,所有的VCL的程序员应该具备的一部分。特别是,它显示了如何VCL的封装和简化的Windows GDI编程。

Graphics.Hpp Graphics.Hpp

在VCL的图形支持的核心是发现Graphics.Hpp。 下列对象中可以找到这个文件:

Object 对象 Description 描述
TCanvas 画布 这是基本的图形对象用于绘制窗体上或其他表面形状。这是周围的GDI的主要包装。
TBrush 画刷 这是用来指定颜色或图案,在中心的填充的形状,如矩形或椭圆形的对象。
TPen 画笔 这是画线所使用的对象,作为矩形或椭圆形的轮廓。
TPicture  这是广义的,高层次的VCL包装围绕“如位图,图元文件,图片或图标”。
TMetaFileCanvas 这是图元文件绘图表面。
TMetaFile  这是围绕一个Windows图元文件的VCL包装。
TBitmap 这是围绕位图的VCL包装。
TIcon TIcon 这是围绕图标的VCL包装。
TGraphicsObject Thi这是画刷,TFont基类,和画笔
TGraphic 这是TMetaFile,TBitmap基类,Ticon。

 

这些对象的许多探索,在未来几页。特别是,我演示如何使用位图和笔,并显示如何绘制基本几何形状在屏幕上。你也可以看到如何使用位图和图元文件。 了解TFont对象后,下一个最重要的图形VCL的对象是画布 。这是周围的Windows GDI或图形设备接口的包装。在GDI是子系统Windows程序员使用油漆图片和实物,其他图形。对Graphics.Hpp中的大部分内容,目的是设法简化的GDI,使其相对容易使用。

另外两个重要的图形,并非源于Graphics.Hpp找到的对象是TImageTPaintBox。 这两个组件包括在本章。

TColor类型

几乎所有的图形对象使用简单TColor类型。 这是建设该系统的整体图形奠定基石之一。

对于大多数实际目的,类型TColor,就是变量内置的Windows类型COLORREF。然而,TColor实际声明如下:

enum TColor {clMin=-0x7fffffff-1, clMax=0x7fffffff};

 

如果您知道COLORREF类型,你可以看到类似TColor类型。 在某种意义上说,TColor类型,不过是一组

预定COLORREF

调色板的Windows系统使您可以定义三种不同的颜色,红色,绿色和蓝色,其中每种颜色有255个不同的色调。 这些颜色指定在过去的3个字节字节长的值用来表示一个变量的类型TColor。

这里是什么三原色如下所示:

Canvas->Brush->Color = 0x000000FF; // Red 油画,“刷”颜色= 0x000000FF; / /红色

Canvas->Brush->Color = 0x0000FF00; // Green油画,“刷”颜色= 0x0000FF00; / /绿

Canvas->Brush->Color = 0x00FF0000; // Blue油画,“刷”颜色= 0x00FF0000; / /蓝

 

"你用这些色彩和这些颜色组合,在从第2章RGBShape计划“,基本事实的C + + Builder的。”

当然,这不是方便要写出这些数字的16进制直接。 相反,你可以使用RGB宏:

Canvas->Brush->Color = RGB(255, 0, 0); // Red 油画,“刷”的RGB颜色=(255,0,0); / /红色

Canvas->Brush->Color = RGB(0, 255, 0); // Green油画,“刷”的RGB颜色=(0,255,0); / /绿

Canvas->Brush->Color = RGB(0, 0, 255); // Blue油画,“刷”的RGB颜色=(0,0,255); / /蓝

 

你当然可以,结合红,绿,蓝,生产各种色调:

RGB(255, 0, 255); // Purple 的RGB(255,0,255); / /紫

RGB(255, 255, 0); // Yellow的RGB(255,255,0); / /黄色

RGB(127, 127, 127); // Gray的RGB(127,127,127); / /灰色

 

VCL中还提供了可以使用常量来指定常见的颜色系列。clBlack,例如,具有相同的内部编号你会从下面的代码:

COLORREF clBlack = RGB(0, 0, 0); COLORREF clBlack =的RGB(0,0,0);

 

下面是一些来自GRAPHICS.HPP声明:

#define clBlack TColor(0)

#define clMaroon TColor(128)

#define clGreen TColor(32768)

#define clOlive TColor(32896)

 

如果您想与这个系统进行试验,可以在BCB创建一个新的项目,拖放到主窗体的按钮和运行的方法有所改变,看起来像这样:

void __fastcall TForm1::Button1Click(TObject *Sender) 

{

Canvas->Brush->Color = 0x0000FFFF;

Canvas->Rectangle(0, 0, 200, 200);//画布

}

 

此代码将绘制在主窗体右上角明亮的黄色矩形。 尝试改变的颜色值0x00FF0000,到RGB(255,0,255),clBlue,等等。 如果你绘制矩形厌了,您可以切换到椭圆形,而不是:

Canvas->Ellipse(0, 0, 200, 200);

 

我谈到与绘图画布后面的章节中形状多。

在大多数情况下你会选择从颜色属性编辑器提供的大多数组件的颜色。 例如,您可以双击一个TForm对象的颜色属性造就TColorDialog。然而,有些时候你需要与TColor类型直接,这就是为什么我有详细解释的主题。

Canvas 画布对象

一切形式的许多组成部分,有一个画布。你能想到的一个帆布被表面上的图形对象可以油漆。 总之,这里的开发人员使用的比喻是一个画家的画布。

画布对象纳入层次结构的核心组件,通过聚合,在许多情况下意味着你可以通过一个对象的领域,例如TFormTImage.

例如,您可以编写如下:

Form1->Canvas->TextOut(1, 1, "Hello from the canvas");

 

.本声明中写道从帆布改为“你好”,窗体的左上角。 请注意,您没有访问或引用一个设备上下文进行直接使用此方法。

当然,很多时候,你是从Form1 内部访问Form1的大部分,因此,你可以写

Canvas->TextOut(1, 1, "Hello from the canvas");

 

但是,你不能写

Form1->TextOut(1, 1, "Hello from the canvas"); 

 

这是因为Canvas对象是 Form1。 画布是通过多重继承带来的汇总。 此外,聚合并没有试图对包内的TForm方法画布的每一种方法。 "聚集在讨论19章更详细,“继承”和20,“封装。”

Canvas对象有几个关键的方法,所有的VCL的程序员应该知道:

 

Arc 画弧线
Chord 和弦 一个封闭的数字显示1线和椭圆相交
CopyRect 复制一个到另一个地区帆布
Draw 绘制 绘制位图或其他图形画布上
Ellipse 椭圆 绘制椭圆
FillRect 填充矩形
FloodFill 填写一个封闭的区域
FrameRect Draw a border around a rectangle周围绘制一个矩形边框
LineTo 画线
MoveTo 画线
Pie 画一个饼形对象
Polygon 绘制多面对象
PolyLine  连接一组点的画布
Rectangle 绘制一个矩形
RoundRect Draw a rectangle with rounded corners绘制一个圆角矩形
StretchDraw 绘制相同,但该对象延伸,以填补区
TextHeight 一个在当前字体弦高
TextOut 输出文本
TextRect 输出文本在某个特定地区的
TextWidth 一个在当前字体字符串的宽度


画布以下属性的对象很重要:

 

Font 字体

Brush

Pen

Pixels像素

 

以下事件可能对一些非常重要的技术程序:

OnChange

OnChanging

 

如果您知道在Windows API,这些方法中的许多人都会熟悉。从用帆布大可以获得对象而不是原始的Windows GDI调用是使用的资源会为你自动管理。特别是,你永远必须有一个设备上下文,也不必为选择到一个设备上下文对象。

在某些情况下,您将得到更好的性能,如果你直接写入到Windows GDI的。 然而,这是一个错误的假设,你将总是得到这样更好。 例如,VCL的图形子系统将缓存在一个复杂的方式共享资源,将很难复制在自己的代码。 我个人的看法是,你应该使用VCL的图形程序只要有可能,只有转向原始的Windows API当你碰到一个没有被覆盖的VCL图形区域。

该DrawShapes程序演示是多么容易使用的画布在程序中的对象。 此应用程序勾划出一个简单的画图程序的有能力来画线,矩形和椭圆轮廓。 该程序的屏幕截图见图7.1,以及该程序的源表7.1和7.2出现。

清单7.1为DrawShapes程序头文件中声明了一个枚举类型和几个简单的领域。

/// ///

// Main.cpp / /主程序

// DrawShapes Example / / DrawShapes范例

// Copyright (c) 1997 by Charlie Calvert / /版权所有(c)1997年由查理卡尔弗特

// / /

#ifndef MainH

#define MainH

#include  

#include

#include  

#include

#include

#include

#include  

#include  

enum TCurrentShape {csLine, csRectangle, csEllipse};

class TForm1 : public TForm

{

__published: 

TMainMenu *MainMenu1; ;

TMenuItem *File1; 

TMenuItem *Open1; ;

TMenuItem *Save1; 

TMenuItem *N1;

TMenuItem *Rectangle1; 

TMenuItem *Shapes1; 

TMenuItem *Rectangle2;

TMenuItem *Ellipse1;

TMenuItem *Colors1; 

TMenuItem *Brush1; 

TMenuItem *Pen1; 

TPanel *Panel1; 

TSpeedButton *SpeedButton1; 

TSpeedButton *SpeedButton2;

TSpeedButton *SpeedButton3; 

TSpeedButton *SpeedButton4;

TMenuItem *Lines1; 

TColorDialog *ColorDialog1; 

TSpeedButton *SpeedButton5; 

void __fastcall FormMouseDown(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y);

void __fastcall FormMouseUp(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y);

void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X,

int Y);

void __fastcall SpeedButton1Click(TObject *Sender);

void __fastcall Brush1Click(TObject *Sender);

void __fastcall Pen1Click(TObject *Sender);

void __fastcall SpeedButton5Click(TObject *Sender);

private:

TRect FShapeRect;

TColor FPenColor;

TColor FBrushColor;

bool FDrawing;

TCurrentShape FCurrentShape;

int FPenThickness;

void __fastcall DrawShape();

public:

virtual __fastcall TForm1(TComponent* Owner);

}; );

extern TForm1 *Form1;

#endif

 清单7.2 为DrawShapes计划的主要形式展示了如何在画布上绘制形状。

/// ///

// Main.cpp / /主程序

// DrawShapes Example / / DrawShapes范例

// Copyright (c) 1997 by Charlie Calvert / /版权所有(c)1997年 查理卡尔弗特

// / /

#include

#pragma hdrstop

#include "Main.h"

#pragma resource "*.dfm"

TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner) 

{

FDrawing= False;

FCurrentShape = csRectangle;

FBrushColor = clBlue;

FPenColor = clYellow;

FPenThickness = 1;

}

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y) 

{

FShapeRect.Left = X;

FShapeRect.Top = Y;

FShapeRect.Right = - 32000;

FDrawing = True;

}

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

FDrawing = False;

FShapeRect.Right = X;

FShapeRect.Bottom = Y;

Canvas->Pen->Mode = pmCopy;

DrawShape();

}

void __fastcall TForm1::DrawShape()

{

Canvas->Brush->Color = FBrushColor;

Canvas->Pen->Color = FPenColor;

Canvas->Pen->Width = FPenThickness;

switch (FCurrentShape)

{

case csLine:

Canvas->MoveTo(FShapeRect.Left, FShapeRect.Top);

Canvas->LineTo(FShapeRect.Right, FShapeRect.Bottom);

break;

case csRectangle:

Canvas->Rectangle(FShapeRect.Left, FShapeRect.Top,

FShapeRect.Right, FShapeRect.Bottom);

break;;

case csEllipse:

Canvas->Ellipse(FShapeRect.Left, FShapeRect.Top,

FShapeRect.Right, FShapeRect.Bottom);

break;

default:

;

}

}

void __fastcall TForm1::FormMouseMove(TObject *Sender,

TShiftState Shift, int X, int Y)

{

if (FDrawing)

{

Canvas->Pen->Mode = pmNotXor;

if (FShapeRect.Right != -32000)

DrawShape();

FShapeRect.Right = X; 

FShapeRect.Bottom = Y; 

DrawShape();

}

}

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)

{

FCurrentShape = TCurrentShape(dynamic_cast(Sender)->Tag);

}

void __fastcall TForm1::Brush1Click(TObject *Sender)

{

ColorDialog1->Color = FBrushColor; 

if (ColorDialog1->Execute())

FBrushColor = ColorDialog1->Color;

}

void __fastcall TForm1::Pen1Click(TObject *Sender)

{

ColorDialog1->Color = FPenColor;

if (ColorDialog1->Execute())

FPenColor = ColorDialog1->Color; ;

}

void __fastcall TForm1::SpeedButton5Click(TObject *Sender)

{

FPenThickness = dynamic_cast(Sender)->Tag;

}

 

该程序使您能够画线,矩形,并在应用程序的主要形式椭圆形。您可以选择的形状类型您要通过菜单或以速度按钮即可。该计划还允许您设置的形状要绘制并指定宽度和形状周围边框的颜色。

Pens and Brushes 钢笔和刷子

当设置形状的颜色,你需要知道,在一个区域获得形状填充设置为画布当前颜色。该行构成了形状的边界是受当前的

以下是如何设置当前的颜色和的宽度:

Canvas->Pen->Color = clBlue;

 

Canvas->Pen->Width = 5;

 

如果你想改变颜色,您可以编写下面的代码:

Canvas->Brush->Color = clYellow;

 

我不工作正是在这一程序,但您可以分配不同风格的刷子 ,如以下定义的枚举类型:

TBrushStyle { bsSolid, bsClear, bsHorizontal, bsVertical, 

bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross };

 

 

默认情况下, 刷子bsSolid类型。

若要设置一刷子风格,你会编写的代码如下:

Canvas->Brush->Style = bsSolid;

 

上课也有刷颜色位图属性。 图属性可以被设置为一个小的外部位图图像定义为画笔模式。

只有一个的画刷对象,你很可能会使用的方法。这种方法被称为分配 ,这是当你要复制的一刷到另一个特点刷。

 

所有已全部刷类作为相同的属性,但它们添加宽度模式的财产。属性定义的宽度以像素为单位的,Mode属性定义的类型 .操作时要使用油漆在屏幕上。这些逻辑业务将进一步讨论在短短的几分钟。

Rubber Banding 橡皮

在阅读本节,加快DrawShapes程序和惯例制定椭圆和矩形屏幕上的灭火器,你可以看到如何橡皮技术工程。 如果由于某种原因,你不能运行DrawShapes程序,打开Windows画图和借鉴一下,首先从工具菜单中选择相应的图标一些正方形或圆形。观察这些程序的方式创造一个弹性方形或圆形,您可以拖动桌面。这些形状播放你决定什么尺寸和位置为您的几何图形想要的。

这些工具似乎难以程序员创建,但到Windows的API,代码是比较小.以下是主要涉及的步骤,每个解释深入本节后面:

 

1。当用户点击鼠标左键,DrawShapes“背”的x和y坐标的WM_LBUTTONDOWN事件。

2。当用户拖动与左边的按钮仍下跌了鼠标在屏幕上,DrawShapes绘制一个正方形或圆形每次获得一个WM_MOUSEMOVE消息。 就在画每一个新的形状,程序上空格内方形或圆形。 新形状的尺寸计算,结合原有的WM_LBUTTONDOWN消息坐标与当前坐标通过在WM_MOUSEMOVE消息。
 
3。当用户生成WM_LBUTTONUP消息,DrawShapes油漆的颜色和用户指定笔大小的最终形状。

 

虽然这种描述显然省略了一些重要细节,纲要应在你的脑海中只有几个相对简单,逻辑抚摸形状的算法。 事情变得有点复杂的细节时,超过1一个心理转折实在不足,但基本步骤应该是比较清楚的。

 

 

 


(NOTE)注意: 在前面的编号列表,我给的消息的名称,生成的VCL事件。 例如,WM_LBUTTONDOWN消息生成一个OnMouseDown事件的WM_MOUSEMOVE消息产生一个onMouseMove事件,等等。 我指的是基本的信息,因为这是一个好主意记住之间的VCL事件及其相关的Windows消息的连接。


 

 

放大的细节,这里有一个在一个WM_LBUTTONDOWN消息的响应看看:

void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

FShapeRect.Left = X;

FShapeRect.Top = Y;

FShapeRect.Right = - 32000;

FDrawing = True;

}

 

FormMouseDown保存的位置上鼠标是在首两个月的TRect结构字段点击称为FShapeRect。FShapeRect是作为一个TForm1领域的申报。 本人设置TRect结构的权利方面有很大的负数,所以我知道这是第一次,我需要开始跟踪用户的鼠标移动。这是非常必要的,因为第一个形状我提请作为一种特例来处理的需要。

最后一件事,在FormMouseDown方法所做的是建立一个TForm1私有变量FDrawing为 True。这让程序知道用户已经开始绘图操作。

鼠标左键被按下后,该程序拿起一切开始DrawShape飞行一条WM_MOUSEMOVE消息的消息:

void __fastcall TForm1::FormMouseMove(TObject *Sender, 

TShiftState Shift, int X, int Y)

{

if (FDrawing)

{

Canvas->Pen->Mode = pmNotXor;

if (FShapeRect.Right != -32000)

DrawShape();

FShapeRect.Right = X;

FShapeRect.Bottom = Y;

DrawShape();

}

}

 

该函数的第一行使用的检查,看看几个可能的方法之一,如果鼠标左键下降。如果该按钮不下来,函数忽略此消息。如果它已关闭,该函数获取设备上下文,设置氏绘图模式pmNotXor,背的数字目前尺寸,绘制它,并释放设备上下文。

一个画笔对象的模式属性设置方式类似于在BitBLT等方式最后一个参数设置当前绘画模式当前绘图模式。您可以实现通过直接调用Windows API函数调用SetROP2同样的效果。在这种情况下,DrawShape使用逻辑异或和 NOT行动blit的弹性图像的屏幕。这是合乎逻辑的行动选择,因为它描绘的原始图像的顶部的老形状直接,从而有效地清除每个形状:

 

  • I如果您向屏幕广场,广场将显示清楚。

     

  • 如果您异或相同的形象再次在同一位置,图像就会消失。

 

这就是在图形模式下简单的逻辑运算的优点。

 

 

 


(NOTE)注意: Aficionados 的图形芯片将注意到,合乎逻辑的行动DrawShapes就业是一个关于异或 (XOR)变异操作。这种变化确保在形状的中心填写要绘制不会抹杀它下面是什么的。 微软文档解释了这样的区别:

 

R2_XOR: final pixel = pen ^ screen pixel

R2_NOTXORPEN : final pixel = ~(pen ^ screen pixel)

此代码测试,看看是否像素是署属于一支笔。不要浪费太多的逻辑运算令人担忧,它们是如何工作。 如果您感兴趣的罚款;如果他们不这样做,没关系。 这本书的主题是编程,而不是逻辑。

如果你是工作在Windows API直接,你会与一个常数,而不是所谓的pmNotXor RT_NOTXORPEN。我必须承认,VCL的倾向重新命名的Windows API使用的常量是不是一个很成功的特征。当然,在微软的人谁带着这些标识多了一些值得可怕的,无名的命运,但一旦损害已经造成,可能有简单的坚持使用原来的常量。这样人们就不会记住,是Windows API的使用两套标识符与VCL的使用1,和其他。您不能使用VCL的常量将Windows常数,因为各标识符没有映射到相同的值。

尽管有这些反对意见,我仍然认为这是明智的使用VCL的,而不是直接写入到Windows的API。 VCL的是更安全和更容易使用。 从大多数的VCL对象的性能是伟大的,也将是比大多数程序员可以直接写入Windows API中取得更好的许多案件。


 

 

请注意,FormMouseMove 调用 DrawShape两次。第一次,它通过在旧的数字,需要擦除的尺寸。这意味着它的S 异或相同的图像直接对原始图像的顶部,从而抹去了。 然后FormMouseMove记录了最新的WM_MOUSEMOVE消息的位置并通过这项新的信息DrawShape,其中涂料的新形象在屏幕上。这整个过程重复一遍又一遍(以难以置信的速度),直到用户解除了鼠标左键。

DrawImage功能, 隐喻首先检查的形状用户选择,然后继续塑造绘制到屏幕上使用当前的笔和填充颜色:

void __fastcall TForm1::DrawShape()

{

Canvas->Brush->Color = FBrushColor;

Canvas->Brush->Style = bsSolid;

Canvas->Pen->Color = FPenColor;

Canvas->Pen->Width = FPenThickness;

switch (FCurrentShape)

{

case csLine:

Canvas->MoveTo(FShapeRect.Left, FShapeRect.Top);

Canvas->LineTo(FShapeRect.Right, FShapeRect.Bottom);

break;

case csRectangle:

Canvas->Rectangle(FShapeRect.Left, FShapeRect.Top,

FShapeRect.Right, FShapeRect.Bottom);

break;

case csEllipse:

Canvas->Ellipse(FShapeRect.Left, FShapeRect.Top,

FShapeRect.Right, FShapeRect.Bottom);

break;

default:

; ;

}

}

 

此代码设置当前的刷子由用户选择的值。 然后,使用switch语句来选择适当类型的形状绘制到屏幕上。 如FPenColor这些私有变量大多设置允许用户从菜单中作出选择。要清楚地看到它的工作原理,你可以研究在应用程序代码。

请注意,当这些形状绘图,没有必要跟踪当前画布 HDC。对画布对象的主要目标之一是完全隐藏在用户的HDC。"本人更深入地讨论这一问题在本章下一节,“为了GDI或不GDI的。”

在整个行动的最后一步发生时,用户抬起关闭鼠标手指:

在整个行动的最后一步发生时,用户抬起关闭鼠标手指:

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,

TShiftState Shift, int X, int Y)

{

FDrawing = False;

FShapeRect.Right = X;

FShapeRect.Bottom = Y; 

Canvas->Pen->Mode = pmCopy;

DrawShape();

}

 

此代码执行下列操作:

 

  • 设置一个标志,说明用户已决定停止绘图。

     

  • 形状尺寸的最后记录。

     

  • 模式切换从pmNotXor为默认值,这是pmCopy。

     

  • 最后的图像绘制到屏幕上。

 

油漆的代码,最后形成考虑到颜色和厚度的笔,用户选择的菜单。 那么,你有它。 .这就是你画的形状在屏幕上用橡皮筋技术。 总的来说,如果你在一件事,但这个过程并不是太复杂。 正是这样您可以使这些步骤清醒的头脑,在这里他们再次:

 

  • 记得在哪里的WM_LBUTTONDOWN消息发生。

     

  • 绘制形状每次获得WM_MOUSEMOVE消息。

     

  • 作出最后的形状时,您会获得一个WM_LBUTTONUP消息。

 

这就是这么简单。

To GDI or not to GDI 为了GDI或不是为了GDI

VCL的你永远不会完全关闭削减从底层的Windows API代码。 如果你想工作在Windows API的级别,可以这样做。事实上,你经常可以编写代码,VCL和原料混合Windows API的代码。

如果你想获得一个窗口的HDC,你可以在它通过画布的Handle属性:

MyOldPenHandle = SelectObject(Canvas->Handle, MyPen->Handle);

In this case you are copying the Handle of a Pen object into the HDC of the TCanvas object.

Having free access to the Handle of the TCanvas object can be useful at times, but the longer I use the VCL, the less inclined I am to use it. The simple truth of the matter is that I now believe that it is best to let an object of some sort handle all chores that require serious housekeeping. This course of action allows me to rely on the object's internal logic to correctly track the resources involved.

If you are not using the VCL, whenever you select something into an HDC, you need to keep track of the resources pumped out of the HDC by the selection. When you are done, you should then copy the old Handle back into the HDC. If you accidentally lose track of a resource, you can upset the balance of the entire operating system. Clearly, this type of process is error-prone and best managed by an object that can be debugged once and reused many times. My options, therefore, are to either write the object myself or use the existing code found in the VCL. In most cases, I simply take the simplest course and use the excellent TCanvas object provided by the VCL.

When I do decide to manage an interaction with the GDI myself, I often prefer to get hold of my own HDC and ignore the TCanvas object altogether. The reason I take this course is simply that the TCanvas object will sometimes maintain the Canvas 's HDC on its own, and I therefore can't have complete control over what is happening to it.   

 

这里有一个如何使用程序内的VCL了GDI直接简单的例子:

HDC DC = GetDC(Form1->Handle); HDC直流= GetDC(Form1上,“柄);

HFONT OldFont = SelectObject(DC, Canvas->Font->Handle); HFONT OldFont = SelectObject(区,帆布,“字体”柄);

TextOut(DC, 1, 100, "Text", 4);

SelectObject(DC, OldFont);

ReleaseDC(Form1->Handle, DC);

 

如果您在此处显示的代码,你会看到我通过调用Windows API函数GetDC我自己的直流。 然后我将选择一个DC新字体。 请注意,我使用的VCL TFont对象。 我通常会更容易地管理字体秒, 秒,并比原始的Windows API代码的VCL对象上课。 不过,如果你想创建原始的Windows API编写自己的字体,您可以自由地这样做。

下面是一个创建的VCL 字体从头对象的例子:

TFont *Font = new TFont();

Font->Name = "Time New Roman";

Font->Size = 25;

Font->Style = TFontStyles() << fsItalic << fsBold;

HDC DC = GetDC(Form1->Handle);

HFONT OldFont = SelectObject(DC, Font->Handle);

TextOut(DC, 1, 100, "Text", 4);

SelectObject(DC, OldFont);

ReleaseDC(Form1->Handle, DC);

delete Font;

 

此代码分配了一个字体对象的内存,分配一些值其主要属性,然后复制的句柄Font对象到当前DC。请注意,我仍然要保存旧的字体处理和复制到当我与它所做的直流回来。这是我喜欢的运作有一个对象处理的类型。当我与此处显示的示例代码一样,我删除我创建Font对象。 

 

 

摘要:

 在这一章中你有一个图形编程与VCL的概述。我并没有试图掩盖这一问题的所有方面,但希望你现在有足够的资料,以满足您的需求最大。

本章涉及的关键议题包括画布对象,绘制在窗体或部件的表面形状或使用的措词。你也看到了TFont,画刷和画笔对象,定义的形状特征或在组件上绘制的信件。在TMetaFile和TBitmap对象们介绍,虽然我从来没做的简单和容易使用的TIcon对象的任何东西。该章的最后一节有一点乐趣华丽的图像绘制到屏幕上。

一个有关的问题,这不是本章所覆盖的TImageList对象。如果您对这个问题感兴趣,你可能想看看KdAddExplore程序上找到的CD - ROM伴随着这本书。该计划应在Chap14目录。该TImageList组件提供了一个图像存储在内存列表意味着同时采取了最低的系统资源的数量。这是更昂贵的存储图像列表5张图像比将是在程序中使用五个不同的位图。

你可能感兴趣的:(c++,windows,图形,object,api,button)