亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

具體而微的繪圖程式-c++ Borland 入門

2019-11-17 04:59:43
字體:
來源:轉載
供稿:網友
在本章中我將為你示范如何在C++Builder中撰寫一個完整的繪圖程式。藉由這個程式的撰寫,你會更加了解C++Builder的 Canvas 繪圖精神,而在撰寫這個程式的同時,我們也可將相關的技術做一個整體的檢閱。此繪圖程式的執行結果如下:具體而微的繪圖程式-c++ Borland 入門(圖一)
點擊查看大圖
  在此程式中我會以循序漸進的方式一步一步地帶領你完成整個程式,基本上這個程式和C++Builder內附的范例程式有幾分類似,但我必須要說明的是:在 C++Builder中所附的范例程式是直接由原先在Delphi內以 Object Pascal 所撰寫的范例程式修改而成,所以有部份程式的寫法大為違反C++ 式物件導向精神,在邁入C++Builder 的新世紀之後,我們當然希望寫出的程式是『系出名門,血統純正』的C++ 式的物件導向程式。而這就是我在本章中希望帶領你完成的程式?!X-01 關於滑鼠事件(Mouse Event) 撰寫繪圖程式,首先要了解滑鼠事件,在Windows中定義了許多的滑鼠訊息(Message),而這些滑鼠訊息在BCB中就成為滑鼠事件了,為了要處理滑鼠事件,我們必須要選寫滑鼠事件處理程式: 在Windows中定義的滑鼠訊息列表WM_CAPTURECHANGEDWM_LBUTTONDBLCLKWM_LBUTTONDOWNWM_LBUTTONUPWM_MBUTTONDBLCLKWM_MBUTTONDOWNWM_MBUTTONUPWM_MOUSEACTIVATEWM_MOUSEMOVEWM_NCHITTESTWM_NCLBUTTONDBLCLKWM_NCLBUTTONDOWNWM_NCLBUTTONUPWM_NCMBUTTONDBLCLKWM_NCMBUTTONDOWNWM_NCMBUTTONUPWM_NCMOUSEMOVEWM_NCRBUTTONDBLCLKWM_NCRBUTTONDOWNWM_NCRBUTTONUPWM_RBUTTONDBLCLKWM_RBUTTONDOWNWM_RBUTTONUP表XX-01 Windows內滑鼠相關 Message?!‰m然在Windows作業系統中定義了非常多的訊息,但是在C++Builder 中已經把龐大的訊息系統作適度的簡化了,并且不再以訊息的方式存在,而改以事件 (Event)的處理方式,在本章的繪圖程式中,我們只要處理以下的幾個事件即可: OnMouseDown 滑鼠鍵按下事件OnMouseMove 滑鼠移動事件OnMouseUp 滑鼠鍵放開事件OnClick 任何滑鼠的點取 在此,你可以很明顯地發現,在C++Builder的事件中并未將左右滑鼠鍵分別定義,而是以合并處理的方式,因此在收到以上滑鼠事件時,若你要分辨左右滑鼠事件時,必須在事件處理程式中判定左右鍵?!【邆淞嘶镜幕笫录J知後,我們開始進行後續的程式探索吧! 為了讓你實際了解程式的細節,我希望將程式撰寫的步驟細節交代楚,在往下進行之前,我們先建立一個新的專案檔,并將其命名為 DrawMain,同時將Form的Color性質設為黑色(clBlack),以便直接在上面畫圖?!X-02滑鼠事件的處理 當C++ Builder應用程式偵測到物件滑鼠事件時,它會檢查你是否定義該物件相對應的滑鼠事件處理程式,然後呼叫該函數,將相關參數傳給它。以OnMouseDown事件為例,它的事件處理程式模版如下:void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){} 它總共接收了以下幾個參數:Sender 引發該事件的軟體元件。Button 表示滑鼠的按鍵。它的值可為mbLeft(左鍵),mbRight(右鍵),mbMiddle(中間鍵)。Shift 用以表示事件發生的同時Alt,Shift及Ctrl叁鍵的狀態。X,Y 用以表示事件發生時之座標位置。 在大多數的情況下,滑鼠事件的(X,Y)座標值是我們最為感愛好的項目,不過,有時候我們也需要靠Button鍵來判定滑鼠的按鍵,或是需要利用Shift來取得非凡鍵的狀態,而做一些額外的程式處理。 XX-02-01 OnMouseDown事件的處理 首先我們先以一個最基本的畫線程式來說明OnMouseDown事件的處理,當使用者按下滑鼠時,我們希望將筆移至事件發生時的坐標,因此我們可將程式寫成如下: void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){Canvas->MoveTo(X,Y);}XX-02-03 OnMouseUp事件的處理 同樣地,我們可以再為這個Form加上OnMouseUp的事件處理函式,在收到OnMouseUp事件時,由滑鼠點下的坐標,畫一條直線至現在的坐標。
 void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){Canvas->LineTo(X,Y);} 在寫完了以上兩個事件處理函式之後,我們就可以在Form上面作畫了,你可以用滑鼠在Form上面拖戈出一條條直線。其執行結果大致如圖XX-01: 具體而微的繪圖程式-c++ Borland 入門(圖二)圖XX-01XX-02-02 OnMouseMove事件的處理 在加上了OnMouseDown及OnMouseUp處理函式之後,我們只能畫出一條條直線,若是我們想要以滑鼠畫出不規則線段時,就必須再處理OnMouseMove事件,利用OnMouseMove事件,我們可以追縱到滑鼠移動的位置,簡單的OnMouseMove事件處理函式如下: void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift, int X,int Y){Canvas->LineTo(X,Y);} 此程式的意義即在於將滑鼠所經過的每個點,以線條連接起來,在加上OnMouseMove 事件處理函式之後,它的執行結果會變成圖XX-02:具體而微的繪圖程式-c++ Borland 入門(圖三)圖XX-02XX-02-03 滑鼠的處理的加強 前面的程式對於滑鼠的移動處理有部份考慮的不夠周詳,因為它在滑鼠移動時不分青紅皂白就將線畫在螢慕上,造成螢幕上的線條混亂,這并不是正規的處理方法,正確的處理方法應該如下: (1) 滑鼠鍵按下時,將記錄滑鼠按下的旗標設為True.同時將該點記錄下來,謂之原點。
  1. 滑鼠移動時,判定滑鼠按下的旗標是否設為 True,若為 True,則移動至原點,并畫一條由原點至目前所在點的線。同時更新原點位置至目前所在之點。
  2. 滑鼠放開時,將記錄滑鼠按下的旗標設為False。
 以下就是關於叁個滑鼠事件的處理程式碼?!?/ 滑鼠按下的事件處理函式// 1. 將旗標設為True// 2. 記錄原點位置void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){m_bDraw = TRUE;m_nOrgX=X;m_nOrgY=Y;} // 滑鼠移動的事件處理函式// 1. 判定旗標是否為True。若是則進行以下動作。// 2. 移動至原點。// 3. 畫一條由原點至目前所在點的線條。// 4. 更改原點位置?!oid __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,int X, int Y){if (m_bDraw){Canvas->MoveTo(m_nOrgX,m_nOrgY);Canvas->LineTo(X,Y);m_nOrgX = X;m_nOrgY = Y;}} // 滑鼠放開的事件處理函式// 1. 判定旗標是否為True。若是則進行以下動作。// 1. 將旗標設為 False。// 2. 畫線并記錄原點位置(非必要)。void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){if (m_bDraw){m_bDraw=FALSE;Canvas->MoveTo(m_nOrgX,m_nOrgY);Canvas->LineTo(X,Y);m_nOrgX = X;m_nOrgY = Y;}} 將滑鼠事件處理函式做以上的修改之後,我們就完成了一個基本的涂鴉程式的雛形了。我將此表格的背景設為黑色,筆的狀態設為2單位寬度的紅色筆,就得到以下的輸出結果: 具體而微的繪圖程式-c++ Borland 入門(圖四) XX-03 繪圖物件的定義 至目前為止,我們已經完成了一個簡單的涂鴉程式,接下來,我希望將程式擴充為一個一般的繪圖程式,它必須具備基本的畫線、畫圓、畫方等功能。為了要實作出這些功能,我們必須先定義我們的繪圖物件?!X-03-01 繪圖物件之始CShape class CShape
{PRotected:TCanvas* m_pCanvas;TColor m_Color;int m_nWidth;public:CShape(TCanvas* pCanvas) {m_pCanvas = pCanvas;}virtual ~CShape() {}virtual void OnMouseMove(int,int)=0;virtual void OnMouseDown(int,int)=0;virtual void OnMouseUp(int,int)=0;}; 我們首先定義一個CShape類別,它是所有繪圖物件之始,也因此它定義了一個繪圖物件的基本行為。在此繪圖程式中我希望它可以處理叁個不同的滑鼠事件并加以處理之,所以我在CShape中定義了叁個相對應的成員函式,而且它們都是純虛擬函式,表示所有繼續自CShape的類別都必須改寫此叁個成員函式。 (關於物件導向的關念請參閱 <必要的C++ 基礎章節> 或是相關書籍,在此盡作簡短的解釋)。這叁個函式名稱稱如下: virtual void OnMouseMove(int,int)=0;virtual void OnMouseDown(int,int)=0;virtual void OnMouseUp(int,int)=0; 另外我們再定義一般性的繪圖物件都會用到的基本特性,如顏色及線條寬度,再加上繪圖時所需要的 Canvas,如此就組成了CShape的類別定義: TCanvas* m_pCanvas; // 繪圖所需的CanvasTColor m_Color; // 顏色int m_nWidth; // 寬度 至於CShape的解構函式為何也設成virtual呢?這關系到繼續物件的毀滅方法。若是基礎類別的解構函式沒有定義成虛擬函式時,會造成特定情況下,子類別的解構函式沒有被呼叫到的情形:如: CLine *pLine = new Line;CShape* pShape=pLIne;delete pShape; 上述的例子因為CLine為CShape的子類別,因此可以直接將pShape指標指向pLine,然而在後面delete pShape時,若是pShape的解構函式不為虛擬函式,會造成pLine的解構函式不被呼叫到。這是一般C++ 程式設計時很輕易犯的錯誤?!∥覀兛梢詫⒁陨系慕涷灧▌t歸納成一個原則,即是:只要該類別有可能被繼續,就必須將其解構函式設為虛擬函式。如此就有了以下的定義了: CShape(TCanvas* pCanvas) {m_pCanvas = pCanvas;}virtual ~CShape() {} CShape的建構函式必須傳入Canvas以便繪圖,而解構函式則不做任何事,只將其定義為虛擬函式?!X-03-02 CLine類別定義及實作 畫直線的類別 class CLine : public CShape{public:POINT m_ptMove;POINT m_ptOrigin;public:CLine(TCanvas* pCanvas):CShape(pCanvas) {}virtual ~CLine() {}virtual void OnMouseMove(int,int);virtual void OnMouseDown(int,int);virtual void OnMouseUp(int,int);}; 我們將CLine定義為一個畫直線的類別,而我們希望在畫直線時可以在拖弋滑鼠時將原先的線條擦去,并畫出新的線,因此我們必須宣告兩個點來記載滑鼠按下的點及上次的點以便擦去原來的線條。以下就是CLine對於叁個滑鼠事件的處理函式: // 滑鼠按下的事件處理函式// 1. 設定原點及上個啟始點為目前所在點。// 2. 移動至目前所在點。void CLine::OnMouseDown(int x,int y){m_ptOrigin.x = m_ptMove.x = x;m_ptOrigin.y = m_ptMove.y = y;m_pCanvas->MoveTo(x,y);} // 滑鼠移動事件處理函式// 1.將畫筆模式設為XOR模式,以便擦去上一條線。// 2.擦去原來的線(以XOR模式再畫一次就會擦去了)// 3.在目前的位置畫出一條新線。// 4.更新坐標并改變畫筆模式。void CLine::OnMouseMove(int x,int y){m_pCanvas->Pen->Mode = pmXor;m_pCanvas->MoveTo(m_ptOrigin.x,m_ptOrigin.y);m_pCanvas->LineTo(m_ptMove.x,m_ptMove.y);m_pCanvas->MoveTo(m_ptOrigin.x,m_ptOrigin.y);m_pCanvas->LineTo(x,y);m_ptMove.x = x;m_ptMove.y = y;m_pCanvas->Pen->Mode = pmCopy;} // 滑鼠放開事件處理函式// 1.畫出原點至目前點的直線。void CLine::OnMouseUp(int x,int y){
m_pCanvas->MoveTo(m_ptOrigin.x,m_ptOrigin.y);m_pCanvas->LineTo(x,y);} 這就是畫直線類別的定義及實作內容。 XX-03-03 CPolyline類別定義及實作 畫隨意線的類別 class CPolyline : public CShape{public:POINT m_ptOrigin;public:CPolyline(TCanvas* pCanvas):CShape(pCanvas) {}virtual ~CPolyline() {}virtual void OnMouseMove(int,int);virtual void OnMouseDown(int,int);virtual void OnMouseUp(int,int);}; CPolyline類別其實和我們前面所寫的涂鴉程式的行為模式極為類似,所以我就簡單帶過好了。void CPolyline::OnMouseDown(int x,int y){m_ptOrigin.x = x;m_ptOrigin.y = y;m_pCanvas->MoveTo(x,y);} void CPolyline::OnMouseMove(int x,int y){m_pCanvas->LineTo(x,y);} void CPolyline::OnMouseUp(int x,int y){m_pCanvas->LineTo(x,y);} XX-03-04 CPolygon類別定義及實作 畫多邊形的類別 class CPolygon : public CPolyline{public:CPolygon(TCanvas* pCanvas):CPolyline(pCanvas){}virtual ~CPolygon() {}virtual void OnMouseUp(int,int);}; CPolygon是CPolyline的子類別,其差別僅在於它會將首尾兩點連接,使其成為一個多邊形,因此我們就直接由CPolyline繼續而來,只改寫其OnMouseUp成員函式即可?!oid CPolygon::OnMouseUp(int x,int y){m_pCanvas->MoveTo(m_ptOrigin.x,m_ptOrigin.y);m_pCanvas->LineTo(x,y);} XX-03-05 CRectangle類別定義及實作 畫矩形的類別 class CRectangle : public CShape{public:POINT m_ptMove;POINT m_ptOrigin;public:CRectangle(TCanvas* pCanvas):CShape(pCanvas) {}virtual ~CRectangle() {}virtual void OnMouseMove(int,int);virtual void OnMouseDown(int,int);virtual void OnMouseUp(int,int);}; 畫矩形類別其實和畫線類別有些類似,它們同樣必須記載上次滑鼠移動的點,并擦掉原來的圖形畫出新的圖形,所以我只針對其相異的部份加以說明之: // 滑鼠移動事件處理函式// 原理和CLine類似,只不過改成畫矩形。void CRectangle::OnMouseMove(int x,int y){m_pCanvas->Pen->Mode = pmXor;m_pCanvas->Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y);m_ptMove.x = x;m_ptMove.y = y;m_pCanvas->Rectangle(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y);m_pCanvas->Pen->Mode = pmCopy;} XX-03-06 CRoundRect類別定義及實作 畫圓矩形的類別 class CRoundRect : public CShape{public:POINT m_ptMove;POINT m_ptOrigin;public:CRoundRect(TCanvas* pCanvas):CShape(pCanvas) {}virtual ~CRoundRect() {}virtual void OnMouseMove(int,int);virtual void OnMouseDown(int,int);virtual void OnMouseUp(int,int);};CRoundRect的實作幾乎和Crectangle相同,只不過它們呼叫不同的API罷了,CRoundRect是以Canvas->RoundRect來畫出圖形的?!oid CRoundRect::OnMouseMove(int x,int y)
{m_pCanvas->Pen->Mode = pmXor;m_pCanvas->RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y,4,4);m_ptMove.x = x;m_ptMove.y = y;m_pCanvas->RoundRect(m_ptOrigin.x,m_ptOrigin.y,m_ptMove.x,m_ptMove.y,4,4);m_pCanvas->Pen->Mode = pmCopy;} XX-03-07 CEllipse 類別定義及實作 畫圓形的類別 畫圓形的處理和畫矩形也大致相同,因為在Windows中是以包圍矩形來定義一個圓形,因此和CRoundRect相同的,我們只要改寫成畫圓函式即可。其馀我就不多說了?!lass CEllipse : public CShape{public:POINT m_ptMove;POINT m_ptOrigin;public:CEllipse(TCanvas* pCanvas):CShape(pCanvas) {}virtual ~CEllipse() {}virtual void OnMouseMove(int,int);virtual void OnMouseDown(int,int);virtual void OnMouseUp(int,int);}; XX-03-08小結 以上就是此繪圖程式中所使用的各個物件的定義,此乃血統純正的C++ 寫法的程式,不像C++Builder官方的范例是由Delphi的范例修改而來,布滿了Object Pascal的味道?!∪裟銓++ 尚不太熟悉的話,請你一定要細細領略以上的精神。因為它是C++ 式的物件導向程式最基本且精要的精神所在,當你了解了以上的精神,你就可謂把握了C++ 的封裝、繼續、及動態連結這叁把權仗的基本精神。 至於C++ 老手,以上的定義都是很自然就可以接受的。也許有人會質疑以上的物件定義并未考慮到物件的永續性 (Object Persistence)。沒錯,不過這并不是我疏忽了,而是在本章的程式中圖形的存取是以Timage來存取,因此所有向量式的物件都已轉化成點陣圖了,自然不需考慮到物件的儲存問題。 在後續章節,我還會再針對物件的永續性來做一討論?,F在我們先就TImage的點陣圖存取方式為平臺討論之?!∽钺幔谕瓿闪宋锛亩x之後,我們再將程式根據物件導向的方式再加以改寫之。因為我目前尚未加入選擇物件的方法,所以我只能用預設物件型態的方式來展示程式的結果。 // 表格建構函式,設定m_bDraw旗標初值__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner){m_bDraw = FALSE;} // Form的OnCreate事件處理函式。Form建立時引發。// 1.設定筆的顏色及寬度。// 2.產生一個CLine繪圖物件。// 注:你可以自行修改CLine成CPolyline、CPolygon、CRect等值?!oid __fastcall TForm1::FormCreate(TObject *Sender){Canvas->Pen->Color = clRed;Canvas->Pen->Width = 2;m_pObj = new CLine(Canvas);} // Form的OnClose事件處理函式。Form關閉時引發。// 1.殺掉繪圖物件?!oid __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action){delete m_pObj;} // 更改後的OnMouseDown物件處理函式。// 1.將m_bDraw旗標設為 TRUE。// 2.呼叫繪圖物件的OnMouseDown函式。void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y){m_bDraw = TRUE;m_pObj->OnMouseDown(X,Y);} // 更改後的OnMouseMove物件處理函式。// 1.判定m_bDraw旗標是否為 TRUE。// 2.若是則呼叫繪圖物件的OnMouseMove函式?!oid __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,int X, int Y){if (m_bDraw)m_pObj->OnMouseMove(X,Y);} // 更改後的OnMouseUp物件處理函式。// 1.將m_bDraw旗標設為 FALSE。// 2.若是則呼叫繪圖物件的OnMouseUp函式?!oid __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y){m_bDraw = FALSE;m_pObj->OnMouseUp(X,Y);} 瞧!這就是更改後的程式,是不是變得格外簡潔呢?除此之外,它最大的優點在於,無論我們日後加入了多少繪圖物件,你都不需再修改以上程式中關於繪圖物件的處理部份,只要再自行增加一個物件宣告即可。和原先Borland公司產品內附由Object Pascal修改而來的范例,它的C++ 血統純正多了。而且若是日後你想要將其修改成為一個物件式的繪圖系統,也只需要很簡單的修改而已?!『冒?!讓我們先檢閱現在的成果?!?IMG height=391 alt="具體而微的繪圖程式-c++ Borland 入門(圖五)" src="http://www.knowsky.com/UploadFiles/20080308/2008381439265677805.gif" width=516 border=0>圖XX-04 CLine繪圖物件范例。具體而微的繪圖程式-c++ Borland 入門(圖六)圖XX-05 CPolyline繪圖物件范例(將程式改成new CPolyline) XX-04 工具列(ToolBar)的使用 到目前為止我們已經將所有繪圖物件定義完成,因此理論上你的程式應該可以畫出各種不同的繪圖物件了。但是前面我提到,目前我們尚未將繪圖物件的選擇功能實作出來,因此我們是以直接修改程式的方式來繪制不同的圖形。這是為了說明方便的權宜之計?!≡谝话愕睦L圖程式中都是以工具列的方式來實作出繪圖功能的切換功能,如Windows 95內的小畫家即是一典型例子。因此接下來我就為你說明在C++ Builder中實作出工具列的方法?!?IMG height=400 alt="具體而微的繪圖程式-c++ Borland 入門(圖七)" src="http://www.knowsky.com/UploadFiles/20080308/2008381439275077807.gif" width=524 border=0>圖XX-06小畫家使用的工具列 在C++ Builder中實作工具列的方式和其他的程式如Visual C++,Borland C++ 不同。後兩者都是直接使用Windows 95內建的工具列型別來達到此功能。然而在C++ Builder中因為有一種更為簡單且直接的方式來做到,因此就不采用上述作法 (當然C++ Builder也可以用Windows 95內建的ToolBar型別,只是用法較為復雜。)?!∧屈N在C++ Builder中是如何來實作出工具列呢?說穿了其實很簡單:那就是利用TPanel和TSpeedButton。 CPanel是一個多功能的容器元件,因此我們可以用它來做為工具列的平臺,使用CPanel是因為它是少數幾個可做為容器元件的元件,所以它會自動調整置於其上的軟體元件的位置,因此很適合做為放置工具列的平臺?!∽ⅲ涸贑++ Builder的程式模式中大量使用TPanel來做為容器元件。它除了可以做為ToolBar的平臺外,另外如狀態列 (StatusBar)也可以用它來完成,而且它也可以用來做為畫面分割的工具,來達成在MFC中類似分割視窗(Splitter Window)效果。 TSpeedButton快速按鈕元件在功能上本來就和工具列有幾分類似,現在我們可以將相同屬性的快速按鈕元件整合在一個TPanel中即可完成我們所要的工具列了?!∽钺嵛以賹⒐ぞ吡械淖鞣ò床烤桶嘣斒鲋骸?1) 在表格上加入TPanel元件。
  1. 設定TPanel的Align性質為 alTop。因為我們希望工具列置於表格上方,所以將它設定為浮貼於表格的上方。如此一來當表格大小改變時,工具列的寬度為跟著改變,而高度則維持原先的高度。
  2. 將TSpeedButton加入TPanel原件上。
 你可以在表格中加入多個上述的工具列,它們會依序自動排列於表格的上方,因此你不需費心去處理這些額外的動作?!X-04-01 TSpeedButton 元件解析及設定 ToolBar的幾個基本要素是:(1) 代表該功能的圖形。(2) 可依狀況切換其狀態。
  1. 當使用者點取該功能時,必須執行該功能。
 我們來看看TSpeedButton如何達到以上的要求?!∈紫龋琓SpeedButton具備Glyph性質,可以指定其圖形,所以第一個要求不成問題,再來TSpeedButton具備以下叁種狀態: 
  • 一般按鈕的功能。
  • 可以除能/致能。
  • 具備群組特性。(也就是說同一群組的TSpeedButton會互相影響,因此可輕易做出互斥的功能,以繪圖程式為例,一次只能使用一種工具,因此當使用者選取工具時,除了被選取的工具之外,其他的工具應該都呈浮起狀態)
 由上可知,TSpeedButton確實是實作ToolBar的適當人選。 XX-04-02將SpeedButton加入ToolBar 依照我們先前的需求,我們需要一個可以切換繪圖工具的工具列,因此我們就照前面所說的方式來完成它。 具體而微的繪圖程式-c++ Borland 入門(圖八)圖XX-07工具列 圖XX-07就是我所加入的SpeedButton,除此之外還有幾個程序必須完成
  • 為SpeedButton命名。取一個有意義的名字。
  • 依需要設定其高度及位置。
  • 設定圖形。
  • 設定SpeedButton狀態初值。
  • 設定群組特性。

◎ 設定事件處理函式?!peedButton的命名原則和一般變數的命名原則相同,簡單明了就好。以本程式為例,我們就可以LineButton、RectangleButton等名字命名之。命名時只要改變SpeedButton的Name性質即可?!≈领对O定圖形,只要先選取該SpeedButton,然後至物件檢視器點取Glyph性質,然後將欲選取的點陣圖Load進來,即可完成設定圖形的程序了?!?IMG height=248 alt="具體而微的繪圖程式-c++ Borland 入門(圖九)" src="http://www.knowsky.com/UploadFiles/20080308/2008381439295377809.gif" width=287 border=0>圖XX-08 Glyph圖形之選取?!≡O定狀態初值:由於我們希望本程式執行的初始值是使用CLine元件,因此我將LineButton的Down屬性為True,其馀則為 False。具體而微的繪圖程式-c++ Borland 入門(圖十)圖XX-09選取後的狀態 設定群組特性:群組特性是SpeedButton用以實作出ToolBar的重要功能之一。我們可以將一群SpeedButton設為同一群組,如此一來在此一群組的SpeedButton就具備了互斥特性,也就是說在任何一個SpeedButton按下時,會導致其他的SpeedButton浮起。此為實作ToolBar的必備條件,而利用SpeedButton可以輕易達成此目的。 設定群組特性其實很簡單,只要把該群組的SpeedButton的GroupIndex性質設為相同數字即可,在此例中我們希望將所有繪圖工具列按鈕設為同一群組,因此我把該相關工具的GroupIndex性質都設為1?!×硗猓嘈拍阋呀洶l現在上面的工具列中,除了前面所談到的繪圖工具之外,我還多加了兩個額外的SpeedButton ,它們是用來設定筆及筆刷的工具。在此例中,我們是以它來叫出另外兩個設定筆及筆刷的工具列,因此它必須具備所謂Toggle On/Off的開關功能。也就是類似CheckBox的功能。 SpeedButton也可輕易達到以上的要求,只要設定該SpeedButton的AllowAllUp屬性為True即可以做到此功能?!∽钺嵛覀儽仨殞⒃O定筆及筆刷的兩個SpeedButton,PenButton及BrushButton的GroupIndex分別設為 2、3,如此才不會和繪圖工具的SpeedButton的群組特性相干擾?!X-05工具列的事件處理函式 完成的工具列的設定之後,接著我們要設定工具列的處理函式,由於此工具列是用來切換繪圖工具的,因此我們只要處理SpeedButton的OnClick事件,再分別根據不同的事件做處理即可?!≡诖死?,OnClick的事件處理函式其很簡單,只要刪除原來使用的繪圖工具物件,再重新啟始一個新的繪圖工具即可?!?/---------------------------------------------------------------------void __fastcall TGraphEx::LineButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CLine(Canvas);}//---------------------------------------------------------------------void __fastcall TGraphEx::PolylineButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CPolyline(Canvas);}//---------------------------------------------------------------------void __fastcall TGraphEx::PolygonButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CPolygon(Canvas);}//---------------------------------------------------------------------void __fastcall TGraphEx::RectangleButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CRectangle(Canvas);}//---------------------------------------------------------------------void __fastcall TGraphEx::EllipseButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CEllipse(Canvas);}//---------------------------------------------------------------------void __fastcall TGraphEx::RoundRectButtonClick(TObject *Sender){delete m_pObj;m_pObj = new CRoundRect(Canvas);}//---------------------------------------------------------------------
 在完成了以上的設定之後,此程式就具備了利用繪圖工具列來切換繪圖工具的功能。具體而微的繪圖程式-c++ Borland 入門(圖十)圖XX-10具備繪圖工具列的繪圖程式范例。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲丝袜一区在线| 国产精品www网站| 欧美一级视频在线观看| 91av在线不卡| 久热99视频在线观看| 亚洲激情第一页| 国产精品日韩在线播放| 日韩**中文字幕毛片| 亚洲精品色婷婷福利天堂| 亚洲免费视频一区二区| 久久久亚洲成人| 精品毛片网大全| 91在线中文字幕| 久久免费高清视频| 日韩精品在线视频观看| 麻豆成人在线看| 国产欧美精品xxxx另类| 日韩视频第一页| 2019中文字幕在线免费观看| 欧美中文字幕视频在线观看| 国产成人精品一区二区在线| 激情亚洲一区二区三区四区| 精品国产一区二区三区久久| 欧美日韩国产激情| 成人免费高清完整版在线观看| 日韩中文有码在线视频| 久久久久久久久久久av| 欧美国产在线电影| 国产日韩欧美综合| 日本精品一区二区三区在线| 欧美精品一二区| 萌白酱国产一区二区| 欧美香蕉大胸在线视频观看| 国产日韩在线观看av| 欧美乱大交xxxxx另类电影| 日韩中文字幕在线| 热re99久久精品国产66热| 91色视频在线导航| 九色成人免费视频| 久久久成人精品视频| 亚洲欧美在线磁力| 久久久中精品2020中文| 一区二区三区 在线观看视| 国产日韩在线一区| 日韩精品免费一线在线观看| 一区二区在线视频播放| 精品国产欧美一区二区五十路| 国产在线观看不卡| 亚洲精品午夜精品| 久久久精品999| 热99在线视频| 成人在线激情视频| 国产亚洲欧美一区| 国产在线日韩在线| 国产精品久久久久久久7电影| 欧美性生交大片免网| 精品亚洲一区二区三区在线播放| 色哟哟亚洲精品一区二区| 亚洲丝袜在线视频| 国产99视频在线观看| 韩国19禁主播vip福利视频| 欧美日韩一区二区在线播放| 欧美俄罗斯性视频| 日本亚洲欧洲色| 欧美黄色三级网站| www.99久久热国产日韩欧美.com| 精品欧美aⅴ在线网站| 精品福利在线视频| 亚洲精品之草原avav久久| 色综合伊人色综合网站| 欧美激情二区三区| 国产视频欧美视频| 在线视频欧美日韩| 中文字幕日韩av电影| 疯狂欧美牲乱大交777| 国产精品视频精品视频| 91av免费观看91av精品在线| 日韩在线小视频| 成人中文字幕在线观看| 亚洲最新av在线| 久久久国产一区二区三区| 欧美日韩成人黄色| 国产精品成熟老女人| 欧美视频专区一二在线观看| 日本欧美一级片| 国产精品video| 欧美另类极品videosbest最新版本| 中文字幕国产精品久久| 国产原创欧美精品| 2019日本中文字幕| 亚洲男人第一av网站| 日韩欧美在线字幕| 亚洲综合在线中文字幕| 岛国av午夜精品| 久久久精品国产亚洲| 日韩欧美高清在线视频| 国产精品高潮呻吟久久av黑人| 欧美午夜www高清视频| 久久精品视频中文字幕| 福利精品视频在线| 色婷婷av一区二区三区在线观看| 日韩一区二区久久久| 91在线观看免费高清| 国产精品亚洲综合天堂夜夜| 亚洲第一页中文字幕| 亚洲japanese制服美女| 欧美一区二区三区免费观看| 亚洲高清免费观看高清完整版| 色多多国产成人永久免费网站| 亚洲在线视频观看| 亚洲精品中文字| 成人免费视频a| 日韩成人小视频| 欧美日韩国产第一页| 78m国产成人精品视频| 日韩成人在线视频| 亚洲在线免费观看| 亚洲国产欧美一区二区三区同亚洲| 国产手机视频精品| 韩国一区二区电影| 欧美亚洲午夜视频在线观看| 中文字幕成人精品久久不卡| 欧洲永久精品大片ww免费漫画| 亚洲女性裸体视频| 成人免费在线视频网址| 国产精品久久久久久久天堂| 欧美精品video| 色噜噜狠狠狠综合曰曰曰| 亚洲精品少妇网址| 国产欧美在线播放| 久久亚洲精品网站| 国产成人精品久久| 欧美另类69精品久久久久9999| 午夜精品在线观看| 欧美极品在线视频| 久久国产精品久久久久久久久久| 97国产suv精品一区二区62| www.欧美视频| 国产不卡在线观看| 久久人人爽亚洲精品天堂| 国内精品久久久久伊人av| 日本欧美爱爱爱| 亚洲天堂精品在线| 国产主播在线一区| 国内精品模特av私拍在线观看| 97久久久免费福利网址| 中文字幕最新精品| 国产精品美女久久久免费| 欧美午夜精品久久久久久久| 亚洲免费视频网站| 日韩精品在线视频| 欧美日韩在线影院| 欧美一级免费视频| 亚洲欧洲黄色网| 成人免费xxxxx在线观看| 日韩精品免费在线播放| 亚洲精品久久久久中文字幕二区| 久久久成人精品| 美女久久久久久久久久久| 成人综合国产精品| 日本久久久久亚洲中字幕| 最近2019中文字幕大全第二页| 综合网日日天干夜夜久久| 亚洲男人天堂九九视频|