⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000002.htm

📁 水木清华关于C++Builder程序的代码
💻 HTM
📖 第 1 页 / 共 3 页
字号:
另外我们再定义一般性的绘图物件都会用到的基本特性,如颜&nbsp;<BR>色及线条宽度,再加上绘图时所需要的&nbsp;Canvas,如此就组成&nbsp;<BR>了CShape的类别定义:&nbsp;<BR> &nbsp;<BR>TCanvas*&nbsp;m_pCanvas;&nbsp;//&nbsp;绘图所需的Canvas&nbsp;&nbsp;<BR>TColor&nbsp;m_Color;&nbsp;//&nbsp;颜色&nbsp;<BR>int&nbsp;m_nWidth;&nbsp;//&nbsp;宽度&nbsp;<BR> &nbsp;<BR>至於CShape的解构函式为何也设成virtual呢?这关系到继&nbsp;<BR>承物件的毁灭方法。若是基础类别的解构函式没有定义成虚拟&nbsp;<BR>函式时,会造成特定情况下,子类别的解构函式没有被呼叫到&nbsp;<BR>的情形:&nbsp;<BR>如:&nbsp;<BR> &nbsp;<BR>CLine&nbsp;*pLine&nbsp;=&nbsp;new&nbsp;Line;&nbsp;<BR>CShape*&nbsp;pShape=pLIne;&nbsp;<BR>delete&nbsp;pShape;&nbsp;<BR> &nbsp;<BR>上述的例子因为CLine为CShape的子类别,因此可以直接将&nbsp;<BR>pShape指标指向pLine,然而在後面delete&nbsp;&nbsp;<BR>pShape时,若是pShape的解构函式不为虚拟函式,会造成pLine&nbsp;<BR>的解构函式不被呼叫到。这是一般C++&nbsp;程式设计时很容易犯的&nbsp;<BR>错误。&nbsp;<BR> &nbsp;<BR>我们可以将以上的经验法则归纳成一个原则,即是:只要该类&nbsp;<BR>别有可能被继承,就必须将其解构函式设为虚拟函式。如此就&nbsp;<BR>有了以下的定义了:&nbsp;<BR> &nbsp;<BR>CShape(TCanvas*&nbsp;pCanvas)&nbsp;{m_pCanvas&nbsp;=&nbsp;pCanvas;}&nbsp;<BR>virtual&nbsp;~CShape()&nbsp;{}&nbsp;<BR> &nbsp;<BR>CShape的建构函式必须传入Canvas以便绘图,而解构函式则&nbsp;<BR>不做任何事,只将其定义为虚拟函式。&nbsp;<BR> &nbsp;<BR>XX-03-02&nbsp;CLine类别定义及实作-画直线的类别&nbsp;<BR> &nbsp;<BR>class&nbsp;CLine&nbsp;:&nbsp;public&nbsp;CShape&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>POINT&nbsp;m_ptMove;&nbsp;<BR>POINT&nbsp;m_ptOrigin;&nbsp;<BR>public:&nbsp;<BR>CLine(TCanvas*&nbsp;pCanvas):CShape(pCanvas)&nbsp;{}&nbsp;<BR>virtual&nbsp;~CLine()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseMove(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseDown(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR> &nbsp;<BR>我们将CLine定义为一个画直线的类别,而我们希望在画直线&nbsp;<BR>时可以在拖弋滑鼠时将原先的线条擦去,并画出新的线,因此&nbsp;<BR>我们必须宣告两个点来记载滑鼠按下的点及上次的点以便擦去&nbsp;<BR>原来的线条。&nbsp;<BR>以下就是CLine对於三个滑鼠事件的处理函式:&nbsp;<BR> &nbsp;<BR>//&nbsp;滑鼠按下的事件处理函式&nbsp;<BR>//&nbsp;1.&nbsp;设定原点及上个启始点为目前所在点。&nbsp;<BR>//&nbsp;2.&nbsp;移动至目前所在点。&nbsp;<BR>void&nbsp;CLine::OnMouseDown(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_ptOrigin.x&nbsp;=&nbsp;m_ptMove.x&nbsp;=&nbsp;x;&nbsp;<BR>m_ptOrigin.y&nbsp;=&nbsp;m_ptMove.y&nbsp;=&nbsp;y;&nbsp;<BR>m_pCanvas-&gt;MoveTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>//&nbsp;滑鼠移动事件处理函式&nbsp;<BR>//&nbsp;1.将画笔模式设为XOR模式,以便擦去上一条线。&nbsp;<BR>//&nbsp;2.擦去原来的线(以XOR模式再画一次就会擦去了)&nbsp;<BR>//&nbsp;3.在目前的位置画出一条新线。&nbsp;<BR>//&nbsp;4.更新坐标并改变画笔模式。&nbsp;<BR>void&nbsp;CLine::OnMouseMove(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmXor;&nbsp;<BR>m_pCanvas-&gt;MoveTo(m_ptOrigin.x,m_ptOrigin.y);&nbsp;<BR>m_pCanvas-&gt;LineTo(m_ptMove.x,m_ptMove.y);&nbsp;<BR>m_pCanvas-&gt;MoveTo(m_ptOrigin.x,m_ptOrigin.y);&nbsp;<BR>m_pCanvas-&gt;LineTo(x,y);&nbsp;<BR>m_ptMove.x&nbsp;=&nbsp;x;&nbsp;<BR>m_ptMove.y&nbsp;=&nbsp;y;&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmCopy;&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>//&nbsp;滑鼠放开事件处理函式&nbsp;<BR>//&nbsp;1.画出原点至目前点的直线。&nbsp;<BR>void&nbsp;CLine::OnMouseUp(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;MoveTo(m_ptOrigin.x,m_ptOrigin.y);&nbsp;<BR>m_pCanvas-&gt;LineTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>这就是画直线类别的定义及实作内容。&nbsp;<BR> &nbsp;<BR>XX-03-03&nbsp;CPolyline类别定义及实作&nbsp;-&nbsp;画随意线的类别&nbsp;<BR> &nbsp;<BR>class&nbsp;CPolyline&nbsp;:&nbsp;public&nbsp;CShape&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>POINT&nbsp;m_ptOrigin;&nbsp;<BR>public:&nbsp;<BR>CPolyline(TCanvas*&nbsp;pCanvas):CShape(pCanvas)&nbsp;{}&nbsp;<BR>virtual&nbsp;~CPolyline()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseMove(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseDown(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR> &nbsp;<BR>CPolyline类别其实和我们前面所写的涂鸦程式的行为模式极&nbsp;<BR>为类似,所以我就简单带过好了。&nbsp;<BR>void&nbsp;CPolyline::OnMouseDown(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_ptOrigin.x&nbsp;=&nbsp;x;&nbsp;<BR>m_ptOrigin.y&nbsp;=&nbsp;y;&nbsp;<BR>m_pCanvas-&gt;MoveTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>void&nbsp;CPolyline::OnMouseMove(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;LineTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>void&nbsp;CPolyline::OnMouseUp(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;LineTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>XX-03-04&nbsp;CPolygon类别定义及实作&nbsp;-&nbsp;画多边形的类别&nbsp;<BR> &nbsp;<BR>class&nbsp;CPolygon&nbsp;:&nbsp;public&nbsp;CPolyline&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>CPolygon(TCanvas*&nbsp;pCanvas):CPolyline(pCanvas){}&nbsp;<BR>virtual&nbsp;~CPolygon()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR> &nbsp;<BR>CPolygon是CPolyline的子类别,其差别仅在於它会将首尾两&nbsp;<BR>点连接,使其成为一个多边形,因此我们就直接由CPolyline&nbsp;<BR>继承而来,只改写其OnMouseUp成员函式即可。&nbsp;<BR> &nbsp;<BR>void&nbsp;CPolygon::OnMouseUp(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;MoveTo(m_ptOrigin.x,m_ptOrigin.y);&nbsp;<BR>m_pCanvas-&gt;LineTo(x,y);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>XX-03-05&nbsp;CRectangle类别定义及实作&nbsp;-&nbsp;画矩形的类别&nbsp;<BR> &nbsp;<BR>class&nbsp;CRectangle&nbsp;:&nbsp;public&nbsp;CShape&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>POINT&nbsp;m_ptMove;&nbsp;<BR>POINT&nbsp;m_ptOrigin;&nbsp;<BR>public:&nbsp;<BR>CRectangle(TCanvas*&nbsp;pCanvas):CShape(pCanvas)&nbsp;{}&nbsp;<BR>virtual&nbsp;~CRectangle()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseMove(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseDown(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR> &nbsp;<BR>画矩形类别其实和画线类别有些类似,它们同样必须记载上次&nbsp;<BR>滑鼠移动的点,并擦掉原来的图形画出新的图形,所以我只针&nbsp;<BR>对其相异的部份加以说明之:&nbsp;<BR> &nbsp;<BR>//&nbsp;滑鼠移动事件处理函式&nbsp;<BR>//&nbsp;原理和CLine类似,只不过改成画矩形。&nbsp;<BR>void&nbsp;CRectangle::OnMouseMove(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmXor;&nbsp;<BR>m_pCanvas-&nbsp;<BR>><I>Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMo&nbsp;</I><BR>ve.y);&nbsp;<BR>m_ptMove.x&nbsp;=&nbsp;x;&nbsp;<BR>m_ptMove.y&nbsp;=&nbsp;y;&nbsp;<BR>m_pCanvas-&nbsp;<BR>><I>Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMo&nbsp;</I><BR>ve.y);&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmCopy;&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>XX-03-06&nbsp;CRoundRect类别定义及实作&nbsp;-&nbsp;画圆矩形的类别&nbsp;<BR> &nbsp;<BR>class&nbsp;CRoundRect&nbsp;:&nbsp;public&nbsp;CShape&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>POINT&nbsp;m_ptMove;&nbsp;<BR>POINT&nbsp;m_ptOrigin;&nbsp;<BR>public:&nbsp;<BR>CRoundRect(TCanvas*&nbsp;pCanvas):CShape(pCanvas)&nbsp;{}&nbsp;<BR>virtual&nbsp;~CRoundRect()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseMove(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseDown(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR>CRoundRect的实作几乎和Crectangle相同,只不过它们呼叫&nbsp;<BR>不同的API罢了,CRoundRect是以Canvas-&gt;RoundRect来画出&nbsp;<BR>图形的。&nbsp;<BR> &nbsp;<BR>void&nbsp;CRoundRect::OnMouseMove(int&nbsp;x,int&nbsp;y)&nbsp;<BR>{&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmXor;&nbsp;<BR>m_pCanvas-&nbsp;<BR>><I>RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMo&nbsp;</I><BR>ve.y,4,4);&nbsp;<BR>m_ptMove.x&nbsp;=&nbsp;x;&nbsp;<BR>m_ptMove.y&nbsp;=&nbsp;y;&nbsp;<BR>m_pCanvas-&nbsp;<BR>><I>RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMo&nbsp;</I><BR>ve.y,4,4);&nbsp;<BR>m_pCanvas-&gt;Pen-&gt;Mode&nbsp;=&nbsp;pmCopy;&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>XX-03-07&nbsp;CEllipse&nbsp;类别定义及实作&nbsp;-&nbsp;画圆形的类别&nbsp;<BR> &nbsp;<BR>画圆形的处理和画矩形也大致相同,因为在Windows中是以包&nbsp;<BR>围矩形来定义一个圆形,因此和CRoundRect相同的,我们只&nbsp;<BR>要改写成画圆函式即可。其馀我就不多说了。&nbsp;<BR> &nbsp;<BR>class&nbsp;CEllipse&nbsp;:&nbsp;public&nbsp;CShape&nbsp;<BR>{&nbsp;<BR>public:&nbsp;<BR>POINT&nbsp;m_ptMove;&nbsp;<BR>POINT&nbsp;m_ptOrigin;&nbsp;<BR>public:&nbsp;<BR>CEllipse(TCanvas*&nbsp;pCanvas):CShape(pCanvas)&nbsp;{}&nbsp;<BR>virtual&nbsp;~CEllipse()&nbsp;{}&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseMove(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseDown(int,int);&nbsp;<BR>virtual&nbsp;void&nbsp;OnMouseUp(int,int);&nbsp;<BR>};&nbsp;<BR> &nbsp;<BR>XX-03-08小结&nbsp;<BR> &nbsp;<BR>以上就是此绘图程式中所使用的各个物件的定义,此乃血统纯&nbsp;<BR>正的C++&nbsp;&nbsp;<BR>写法的程式,不像C++Builder官方的范例是由Delphi的范例&nbsp;<BR>修改而来,充满了Object&nbsp;Pascal的味道。&nbsp;<BR> &nbsp;<BR>若你对C++&nbsp;尚不太熟悉的话,请你一定要细细领略以上的精神。&nbsp;<BR>因为它是C++&nbsp;式的物件导向程式最基本且精要的精神所在,当&nbsp;<BR>你了解了以上的精神,你就可谓掌握了C++&nbsp;&nbsp;<BR>的封装、继承、及动态连结这三把权仗的基本精神。&nbsp;<BR> &nbsp;<BR>至於C++&nbsp;老手,以上的定义都是很自然就可以接受的。也许有&nbsp;<BR>人会质疑以上的物件定义并未考虑到物件的永续性&nbsp;(Object&nbsp;&nbsp;<BR>Persistence)。没错,不过这并不是我疏忽了,而是在本章的&nbsp;<BR>程式中图形的存取是以Timage来存取,因此所有向量式的物&nbsp;<BR>件都已转化成点阵图了,自然不需考虑到物件的储存问题。&nbsp;<BR> &nbsp;<BR>在後续章节,我还会再针对物件的永续性来做一讨论。现在我&nbsp;<BR>们先就TImage的点阵图存取方式为平台讨论之。&nbsp;<BR> &nbsp;<BR>最後,在完成了物件的定义之後,我们再将程式根据物件导向&nbsp;<BR>的方式再加以改写之。因为我目前尚未加入选择物件的方法,&nbsp;<BR>所以我只能用预设物件型态的方式来展示程式的结果。&nbsp;<BR> &nbsp;<BR>//&nbsp;表格建构函式,设定m_bDraw旗标初值&nbsp;<BR>__fastcall&nbsp;TForm1::TForm1(TComponent*&nbsp;Owner)&nbsp;<BR>∶<I>&nbsp;TForm(Owner)&nbsp;</I><BR>{&nbsp;<BR>m_bDraw&nbsp;=&nbsp;FALSE;&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>//&nbsp;Form的OnCreate事件处理函式。Form建立时引发。&nbsp;<BR>//&nbsp;1.设定笔的颜色及宽度。&nbsp;<BR>//&nbsp;2.产生一个CLine绘图物件。&nbsp;<BR>//&nbsp;注:你可以自行修改CLine成CPolyline、CPolygon、CRect&nbsp;<BR>等值。&nbsp;<BR> &nbsp;<BR>void&nbsp;__fastcall&nbsp;TForm1::FormCreate(TObject&nbsp;*Sender)&nbsp;<BR>{&nbsp;<BR>Canvas-&gt;Pen-&gt;Color&nbsp;=&nbsp;clRed;&nbsp;<BR>Canvas-&gt;Pen-&gt;Width&nbsp;=&nbsp;2;&nbsp;<BR>m_pObj&nbsp;=&nbsp;new&nbsp;CLine(Canvas);&nbsp;<BR>}&nbsp;<BR> &nbsp;<BR>//&nbsp;Form的OnClose事件处理函式。Form关闭时引发。&nbsp;<BR>//&nbsp;1.杀掉绘图物件。&nbsp;<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -