📄 00000001.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: life (沙加~重结晶), 信区: BCB <BR>标 题: 图形程式设计基本观念 <BR>发信站: BBS 水木清华站 (Thu Nov 19 08:58:58 1998) <BR> <BR>第XX章 图形程式设计基本观念 <BR> <BR>XX-0 前言 <BR> <BR>由於Windows是一个图形界面的作业系统,所以传统的Windows程式设计方法在 <BR>处理有关图形设计时,多半是遵循自着Windows诞生以来的方法,透过所谓的GDI <BR>(Graphics Device Interface)来实作图形的绘制。GDI式的绘图法对於早期 <BR>曾经在Dos下自行撰写绘图模组的程式设计师来说,虽然节省了不少 <BR><重新发明轮子> 的麻烦,但是相对地也带来另外一种程式设计的思维模式转变, <BR>相信曾经经历过这段过程的人都馀悸犹存。 <BR> <BR>对於完全没有任何程式经验的初学者来说,庞大复杂的GDI绘图系统更是一个难 <BR>以跨越的学习障疑。 <BR> <BR>在Windows中难道没有一个简易可行的绘图方法吗?有的,本章要为你介绍的C++ <BR>Builder绘图系统,就提供了一个高度抽象化的绘图模组,让你可以用非常直观 <BR>的方式来实作出Windows下的绘图功能。 <BR> <BR>XX-01 C++ Builder的神奇画布 (Canvas) <BR> <BR>在C++ Builder中提供了一种称为Canvas的性质 (Property),在仔细观察後 <BR>你会发现,几乎所有的视觉化元件都包含这个性质,它就是C++ <BR>Builder为程式设计师所提供的神奇画布。 <BR> <BR>Canvas包含了许多和绘图有关的性质,如Pen、Brush、Pixels、Font等;另外 <BR>也包含了各种绘图的函式,如LineTo、Rectangle、MoveTo、Polygon等等。在 <BR>本单元中,我会一一为你介绍这些性质及工具的用法,相信在领略了C++ <BR>Builder的直觉式绘图法後,你再也不会为它所困扰。 <BR> <BR>对於Canvas,Pen,Brush等C++ <BR>Builder的关键字,往後我会采取直接使用原文而不翻译的方式,这是因为原文 <BR>非常简洁,译成中文反而饶舌,有画蛇添足之虞。当然,在某些时候,使用中文 <BR>可以使文意较为流畅时,我还不会择其善者而用之。 <BR> <BR>XX-02 C++ Builder的直觉绘图法 <BR> <BR>在进入主题前,我先以几个范例来说明C++ <BR>Builder绘图法的优点。如果你曾经尝试过传统Windows的绘图法,大概已经感 <BR>受了它的不友善及繁杂,这时你也许会想:只是画条线而已嘛,为什麽还要搞什 <BR>麽DC、GDI <BR>Object等等又 又长的叙述。 <BR> <BR>你说得没错!虽然庞大的GDI绘图系统具备通天彻地的完整Windows绘图功能, <BR>可是也许大部份的人要求的并不多,只是希望可以在Windows下画出自已心中理 <BR>想的图而已。 <BR> <BR>以下我以几个绘图范例来说明C++ Builder的绘图法。 <BR> <BR>简易绘图范例XX-01 <BR> <BR>范例一的输出 <BR> <BR>图XX-01 <BR> <BR>这个程式很简单,只是重复地画出几个图形,如此就组成了一个美丽且和谐的图 <BR>形。我们来看看其关键性的绘图部份: <BR>其中Ellipse为一个画椭圆的绘图函式。 <BR> <BR>void __fastcall Ellipse(int X1, int Y1, int X2, int Y2); <BR>函式说明: <BR>利用Ellipse可在Canvas上画出圆形或椭圆形. 其环绕矩形的左上角为座标为 <BR>(X1, Y1) 而右下角坐标为 (X2, Y2). <BR>若是该矩形为正方形,则所绘之图形为圆形。. <BR>当此椭圆形绘制时,使用Pen的值画出其外框,而使用Brush值填满其内部。 <BR>注: 在Windows 95下X1+X2,Y1+Y2及X1+X2+Y1+Y2的值皆不可超过 32768。 <BR> <BR>void __fastcall TForm1::FormPaint(TObject *Sender) <BR>{ <BR>double AL,x1,y1,x2,y2; <BR>int L=120; <BR>for (int i=0; i<48; i++) <BR>{ <BR>AL = i*M_PI/24; <BR>x1 = L*cos(AL); <BR>y1 = L*sin(AL); <BR>x2 = x1+320; <BR>y2 = -y1+240; <BR>Canvas->Ellipse(x2-90,y2-90,x2+90,y2+90); <BR>} <BR>} <BR> <BR>怎麽样?简单吧!这个程式只是做一些简单的数学运算,然後以视窗中心为准, <BR>画出48个图形而已。我在这个程式中没有用到任何的软体元件,只是以表格 <BR>(Form)做为显示的基台,由於表格中亦包含了Canvas性质,因此表示我们可 <BR>以在上绘图。同时为了绘图的方便,我将表格的背景色调为黑色,并将适当地调 <BR>整画笔的颜色及视窗的大小: <BR> <BR>void __fastcall TForm1::FormCreate(TObject *Sender) <BR>{ <BR>Width = 640; <BR>Height = 480; <BR>Canvas->Pen->Color = clTeal; <BR>Canvas->Brush->Style = bsClear; <BR>} <BR> <BR>基本上以上的调整都可以用二种方式来达成,一种是在属性编辑器,另一种则是 <BR>在程式执行时动态改变,上面的程式码就是在改变视窗的宽度及高度,并设定画 <BR>笔及笔刷,我将画笔颜色设为clTeal并将笔刷型式设为bsClear,以避免填色的 <BR>动作,画笔及笔刷的动作在後续单元中会详细介绍,在此你只要大略了解其动作 <BR>即可。 <BR> <BR>程式输出时,其背景为黑色是因为我在属性编辑器设定了黑色的背景值 <BR> <BR>简易绘图范例XX-02 <BR> <BR>范例二的输出 <BR> <BR> <BR>图XX-02 <BR> <BR>这个范例使用了画线的函式来画出图形,同样地我们来看看其关键的函式LineTo <BR>及MoveTo: <BR> <BR>void __fastcall LineTo(int X, int Y); <BR>函式说明 <BR>LineTo函式由画笔位置画一条至 (X,Y)点的直线,此直线不包含(X,Y)点,同时 <BR>将画笔位置移至 (X,Y)。此函式通常必须配合MoveTo来移动画笔位置。 <BR>此直线使用Pen来绘制。 <BR> <BR> <BR>void __fastcall MoveTo(int X, int Y); <BR>函式说明 <BR>MoveTo是用以在呼叫LineTo前设定画笔位址值。呼叫此函式和直接设定PenPos <BR>属性的效果相同。 <BR> <BR> <BR>void __fastcall TForm1::FormPaint(TObject *Sender) <BR>{ <BR>double A,x1,y1,x2,y2; <BR>int D=150,E=50; <BR>double L,M,O,P; <BR>for (int i=0; i<240; i++) <BR>{ <BR>A = i*M_PI/120; <BR>L = D+D/3*(1+cos(12*A)/2)*cos(A); <BR>x1 = 240+1.25*L*cos(A); <BR>M = E+E/3*(1+sin(12*A)/2)*cos(A); <BR>x2 = 240+1.25*M*cos(A); <BR>O = D+D/3*(1+cos(10*A)/2)*sin(A); <BR>y1 = 240-O*sin(A); <BR>P = E+E/2*(1+cos(15*A)/2)*sin(A); <BR>y2 = 240-P*sin(A); <BR>Canvas->MoveTo(x1,y1); <BR>Canvas->LineTo(x2,y2); <BR>} <BR>} <BR> <BR>以上的程式列表就是范例XX-2的关键部份,也就是实际负责绘图的FormPaint <BR>部份,其中用了许多的三角函数如sin,cos,M_PI等运算,我在此就不另加说明 <BR>了,之所用使用了这些函数只是为了在介绍这些简单的函式时,利用这些简单函 <BR>式所产生的美丽图形,加深你的印象及学习效果罢了。电脑绘图之所以迷人也在 <BR>於此,它可以利用电脑强大的运算及绘图能力,很容易地将一些复杂的图显示出 <BR>来。 <BR> <BR>除了以上两个范例之外,我再为你示范两个同样使用简单的画线函式的绘图范 <BR>例,不过细节我就不再详述了,另外因为它的关键部份程式很短,为了避免你来 <BR>回读取档案交互叁考的困扰,我还是把它列出来,你可以尝试着修改其中的叁数, <BR>说不定可以产生更为美观的图形呢! <BR> <BR>范例三的输出 <BR> <BR>图XX-03 <BR> <BR>void __fastcall TForm1::FormPaint(TObject *Sender) <BR>{ <BR>double A,x1,y1,x2,y2; <BR>int D=100; <BR>double E; <BR>for (int i=0; i<720; i++) <BR>{ <BR>A = i*M_PI/360; <BR>E = D*(1+sin(4*A)); <BR>x1 = 320+E*cos(A); <BR>x2 = 320+E*cos(A+M_PI/5); <BR>y1 = 240+E*sin(A); <BR>y2 = 240+E*sin(A+M_PI/5); <BR>Canvas->MoveTo(x1,y1); <BR>Canvas->LineTo(x2,y2); <BR>} <BR>} <BR> <BR>范例四的输出 <BR> <BR> <BR>图XX-04 <BR> <BR>void __fastcall TForm1::FormPaint(TObject *Sender) <BR>{ <BR>double A,x1,y1,x2,y2; <BR>int D=80; <BR>double E,F; <BR>for (int i=0; i<960; i++) <BR>{ <BR>A = i*M_PI/480; <BR>E = D*(1+cos(20*A)/4); <BR>F = E*(1+sin(4*A)); <BR>x1 = 320+F*cos(A); <BR>x2 = 320+F*cos(A+M_PI/5); <BR>y1 = 240-F*sin(A); <BR>y2 = 240-F*sin(A+M_PI/5); <BR>Canvas->MoveTo(x1,y1); <BR>Canvas->LineTo(x2,y2); <BR>} <BR>} <BR> <BR>以上四个范例程式是我先为你准备的开胃小菜,主要用以说明C++Builder <BR>的Canvas绘图基本观念,同时也让你明了:利用几个简单的基本函式也可以做 <BR>出美丽的电脑绘图。 <BR> <BR>XX-03 TCanvas的Handle性质 <BR> <BR>在平时,你不太会有机会用到TCanvas的Handle性质,它其实就是在Windows SDK <BR>绘图函式中都必须要用到的DC (Device <BR>Context)值。在Windows系统中,所有的绘图动作都必须透过DC来达成, <BR>举例来说标准的SDK画线函式应该是这样的 <BR> <BR>BOOL LineTo( <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -