?? chap09.htm
字號:
<P> </P></FONT><FONT SIZE=2><P>class CPolygon : public CPolyline</P><P>{</P><P>public:</P><P>		CPolygon(TCanvas* pCanvas):CPolyline(pCanvas){}</P><P> virtual ~CPolygon() 				 {}</P><P>virtual void OnMouseUp(int,int);</P><P>};</P><P> </P><P>CPolygon</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>是</FONT><FONT SIZE=2>CPolyline</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的子類別,其差別僅在於它會將首尾兩點連接,使其成為一個多邊形,因此我們就直接由</FONT><FONT SIZE=2>CPolyline</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>繼承而來,只改寫其</FONT><FONT SIZE=2>OnMouseUp</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>成員函式即可。</P><P> </P></FONT><FONT SIZE=2><P>void CPolygon::OnMouseUp(int x,int y)</P><P>{</P><P>	m_pCanvas->MoveTo(m_ptOrigin.x,m_ptOrigin.y);</P><P>	m_pCanvas->LineTo(x,y);</P><P>}</P><P> </P><P>XX-03-05 CRectangle</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>類別定義及實作</FONT><FONT SIZE=2> </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>畫矩形的類別</P><P> </P></FONT><FONT SIZE=2><P>class CRectangle : public CShape</P><P>{</P><P>public:</P><P> POINT m_ptMove;</P><P>	 POINT	m_ptOrigin;</P><P>public:</P><P>		CRectangle(TCanvas* pCanvas):CShape(pCanvas)	{}</P><P> virtual ~CRectangle() 				{}</P><P>virtual void OnMouseMove(int,int);</P><P>virtual void OnMouseDown(int,int);</P><P>virtual void OnMouseUp(int,int);</P><P>};</P><P> </P></FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2><P>畫矩形類別其實和畫線類別有些類似,它們同樣必須記載上次滑鼠移動的點,并擦掉原來的圖形畫出新的圖形,所以我只針對其相異的部份加以說明之:</P><P> </P></FONT><FONT SIZE=2><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>滑鼠移動事件處理函式</P></FONT><FONT SIZE=2><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>原理和</FONT><FONT SIZE=2>CLine</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>類似,只不過改成畫矩形。</P></FONT><FONT SIZE=2><P>void CRectangle::OnMouseMove(int x,int y)</P><P>{</P><P> m_pCanvas->Pen->Mode = pmXor;</P><P>	m_pCanvas->Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y);</P><P> m_ptMove.x = x;</P><P> m_ptMove.y = y;</P><P> m_pCanvas->Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y);</P><P> m_pCanvas->Pen->Mode = pmCopy;</P><P>}</P><P> </P><P>XX-03-06 CRoundRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>類別定義及實作</FONT><FONT SIZE=2> </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>畫圓矩形的類別</P><P> </P></FONT><FONT SIZE=2><P>class CRoundRect : public CShape</P><P>{</P><P>public:</P><P> POINT m_ptMove;</P><P>	 POINT	m_ptOrigin;</P><P>public:</P><P>		CRoundRect(TCanvas* pCanvas):CShape(pCanvas)	{}</P><P> virtual ~CRoundRect() 				{}</P><P>virtual void OnMouseMove(int,int);</P><P>virtual void OnMouseDown(int,int);</P><P>virtual void OnMouseUp(int,int);</P><P>};</P><P>CRoundRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的實作幾乎和</FONT><FONT SIZE=2>Crectangle</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>相同,只不過它們呼叫不同的</FONT><FONT SIZE=2>API</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>罷了,</FONT><FONT SIZE=2>CRoundRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>是以</FONT><FONT SIZE=2>Canvas->RoundRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>來畫出圖形的。</P><P> </P></FONT><FONT SIZE=2><P>void CRoundRect::OnMouseMove(int x,int y)</P><P>{</P><P> m_pCanvas->Pen->Mode = pmXor;</P><P>	m_pCanvas->RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y,4,4);</P><P> m_ptMove.x = x;</P><P> m_ptMove.y = y;</P><P> m_pCanvas->RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y,4,4);</P><P> m_pCanvas->Pen->Mode = pmCopy;</P><P>}</P><P> </P><P>XX-03-07 CEllipse </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>類別定義及實作</FONT><FONT SIZE=2> </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>畫圓形的類別</P><P> </P><P>畫圓形的處理和畫矩形也大致相同,因為在</FONT><FONT SIZE=2>Windows</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>中是以包圍矩形來定義一個圓形,因此和</FONT><FONT SIZE=2>CRoundRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>相同的,我們只要改寫成畫圓函式即可。其馀我就不多說了。</P><P> </P></FONT><FONT SIZE=2><P>class CEllipse : public CShape</P><P>{</P><P>public:</P><P> POINT m_ptMove;</P><P>	 POINT	m_ptOrigin;</P><P>public:</P><P>		CEllipse(TCanvas* pCanvas):CShape(pCanvas)	{}</P><P> virtual ~CEllipse() 				{}</P><P>virtual void OnMouseMove(int,int);</P><P>virtual void OnMouseDown(int,int);</P><P>virtual void OnMouseUp(int,int);</P><P>};</P><P> </P><P>XX-03-08</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>小結</P><P> </P><P>以上就是此繪圖程式中所使用的各個物件的定義,此乃血統純正的</FONT><FONT SIZE=2>C++ </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>寫法的程式,不像</FONT><FONT SIZE=2>C++Builder</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>官方的范例是由</FONT><FONT SIZE=2>Delphi</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的范例修改而來,充滿了</FONT><FONT SIZE=2>Object Pascal</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的味道。</P><P> </P><P>若你對</FONT><FONT SIZE=2>C++ </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>尚不太熟悉的話,請你一定要細細領略以上的精神。因為它是</FONT><FONT SIZE=2>C++ </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>式的物件導向程式最基本且精要的精神所在,當你了解了以上的精神,你就可謂掌握了</FONT><FONT SIZE=2>C++ </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的封裝、繼承、及動態連結這叁把權仗的基本精神。</P><P> </P><P>至於</FONT><FONT SIZE=2>C++ </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>老手,以上的定義都是很自然就可以接受的。也許有人會質疑以上的物件定義并未考慮到物件的永續性</FONT><FONT SIZE=2> </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>(</FONT><FONT SIZE=2>Object Persistence</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>)。沒錯,不過這并不是我疏忽了,而是在本章的程式中圖形的存取是以</FONT><FONT SIZE=2>Timage</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>來存取,因此所有向量式的物件都已轉化成點陣圖了,自然不需考慮到物件的儲存問題。</P><P> </P><P>在後續章節,我還會再針對物件的永續性來做一討論。現在我們先就</FONT><FONT SIZE=2>TImage</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的點陣圖存取方式為平臺討論之。</P><P> </P><P>最後,在完成了物件的定義之後,我們再將程式根據物件導向的方式再加以改寫之。因為我目前尚未加入選擇物件的方法,所以我只能用預設物件型態的方式來展示程式的結果。</P><P> </P></FONT><FONT SIZE=2><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>表格建構函式,設定</FONT><FONT SIZE=2>m_bDraw</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>旗標初值</P></FONT><FONT SIZE=2><P>__fastcall TForm1::TForm1(TComponent* Owner)</P><P>	: TForm(Owner)</P><P>{</P><P>	m_bDraw = FALSE;</P><P>}</P><P> </P><P>//	Form</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的</FONT><FONT SIZE=2>OnCreate</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>事件處理函式。</FONT><FONT SIZE=2>Form</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>建立時引發。</P></FONT><FONT SIZE=2><P>//	1.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>設定筆的顏色及寬度。</P></FONT><FONT SIZE=2><P>//	2.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>產生一個</FONT><FONT SIZE=2>CLine</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>繪圖物件。</P></FONT><FONT SIZE=2><P>// </FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>注:你可以自行修改</FONT><FONT SIZE=2>CLine</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>成</FONT><FONT SIZE=2>CPolyline</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>、</FONT><FONT SIZE=2>CPolygon</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>、</FONT><FONT SIZE=2>CRect</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>等值。</P><P> </P></FONT><FONT SIZE=2><P>void __fastcall TForm1::FormCreate(TObject *Sender)</P><P>{</P><P>	Canvas->Pen->Color = clRed;</P><P> Canvas->Pen->Width = 2;</P><P> m_pObj = new CLine(Canvas);</P><P>}</P><P> </P><P>//	Form</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>的</FONT><FONT SIZE=2>OnClose</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>事件處理函式。</FONT><FONT SIZE=2>Form</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>關閉時引發。</P></FONT><FONT SIZE=2><P>//	1.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>殺掉繪圖物件。</P><P> </P></FONT><FONT SIZE=2><P>void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)</P></FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2><P>{</P><P>	</FONT><FONT SIZE=2>delete m_pObj;</P><P>}</P><P> </P><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>更改後的</FONT><FONT SIZE=2>OnMouseDown</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>物件處理函式。</P></FONT><FONT SIZE=2><P>//	1.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>將</FONT><FONT SIZE=2>m_bDraw</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>旗標設為</FONT><FONT SIZE=2> TRUE</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>。</P></FONT><FONT SIZE=2><P>//	2.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>呼叫繪圖物件的</FONT><FONT SIZE=2>OnMouseDown</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>函式。</P></FONT><FONT SIZE=2><P>void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,</P><P>	TShiftState Shift, int X, int Y)</P><P>{</P><P> m_bDraw = TRUE;</P><P> m_pObj->OnMouseDown(X,Y);</P><P>}</P><P> </P><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>更改後的</FONT><FONT SIZE=2>OnMouseMove</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>物件處理函式。</P></FONT><FONT SIZE=2><P>//	1.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>判斷</FONT><FONT SIZE=2>m_bDraw</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>旗標是否為</FONT><FONT SIZE=2> TRUE</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>。</P></FONT><FONT SIZE=2><P>//	2.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>若是則呼叫繪圖物件的</FONT><FONT SIZE=2>OnMouseMove</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>函式。</P><P> </P></FONT><FONT SIZE=2><P>void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,</P><P>	int X, int Y)</P><P>{</P><P>	if (m_bDraw)</P><P> 	m_pObj->OnMouseMove(X,Y);</P><P>}</P><P> </P><P>//	</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>更改後的</FONT><FONT SIZE=2>OnMouseUp</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>物件處理函式。</P></FONT><FONT SIZE=2><P>//	1.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>將</FONT><FONT SIZE=2>m_bDraw</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>旗標設為</FONT><FONT SIZE=2> FALSE</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>。</P></FONT><FONT SIZE=2><P>//	2.</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>若是則呼叫繪圖物件的</FONT><FONT SIZE=2>OnMouseUp</FONT><FONT FACE="新細明體" LANG="ZH-TW" SIZE=2>函式。</P><P> </P></FONT><FONT SIZE=2><P>void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,</P><P>	TShiftState Shift, int X, int Y)</P><P>{</P>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -