C++“視窗”程式設計啟蒙(之二)

迂者-賀利堅發表於2012-05-11

【摘要】本文適合已經完整學習了C++物件導向機制,但在開發視窗程式方面還是零基礎的同學。通過本文的引導進行實踐體驗,目的是消除同學們開發視窗程式的神祕感,為下一步的自學找到感覺。同時,能更深入地體會到程式設計基本功的根源所在,在今後能自覺地學好專業基礎課,而不是隻浮躁地追求開發平臺和表面的技能。文章最後給出進一步實踐的建議。

【相關博文】C++“視窗”程式設計啟蒙(之一),我的學生劉暢的報告點選開啟連結,對初用VC++6.0,以及對英文介面怕怕的童鞋,有參考價值;邵帥和辛彬自主嘗試了在VS2013下的開發,見點選開啟連結點選開啟連結


  學習程式已經到了C++程式設計的尾聲。同第一次體驗視窗不同,我們已經具備了相當的“經驗”,每週3-5個任務,近兩萬行的程式碼不是白做的。美中不足的是,我們面對的仍然是黑框框(儘管同學們已經會把黑框框改成各種顏色、字型的彩框框)。我們已經深刻領會了C++語言中的各種機制,並且可以將之用於各種應用場合。
  現在,我們將再次體驗視窗程式設計,看到自定義的類如何參與到實際的專案中來。因為學習了物件導向程式設計,我們還可以看到利用嚮導生成的程式原來也是建立在OOP的基礎的,程式中對話方塊、編輯框、按鈕等均是MFC中例的例項,MFC中提供的類是可以被使用者程式繼承來使用的。這就是軟體工程中強調的儘可能利用已有“類庫”的最生動的案例。
  閒言碎語不講了,先看這次體驗的案例——求三角形的面積。

  一、三角形類
  第5周實驗的任務一,我們已經設計過一個比較完整的三角形類,主要程式碼如下所示(main()函式和類的showMessage()成員函式就不寫了,這是給黑框框準備的):
class Triangle
{
public:
    Triangle(){a=1;b=1;c=1;}   //設計預設建構函式,即不指定引數時,預設各邊長為;
    Triangle(double x, double y, double z) {a=x; b=y; c=z;} //使用帶引數建構函式,即Triangle(doublex, double y, double z),三邊長在呼叫時由實參直接給出
    double perimeter(void);//計算三角形的周長
    double area(void);//計算並返回三角形的面積
private:
    double a,b,c;//三邊為私有成員資料
};
 
double Triangle::perimeter(void) 
{
     return (a +b + c); 
} 
 
double Triangle::area(void) 
{
   double s =(a + b + c) / 2;   
    return sqrt(s * (s - a) * (s - b) * (s - c));  
}
  寫出這點程式碼已經是小case,後面運算子過載、繼承、多型、虛擬函式等真功夫還沒用呢!
  下面開發視窗版程式。和第一次的體驗不同,這次的平臺選用VS2008。、

  二、視窗程式的開發
  1、新建MFC應用程式

  選擇選單->檔案->新建,在“專案型別”中選擇“MFC”,右邊的“模板”中選“MFC應用程式”,然後在專案“名稱”處為專案命名,如圖1所示:

   (圖1)

  點選“確定”後,見圖2:

   (圖2)

  再點“下一步”,見圖3:

   (圖3)

  在“應用程式型別”部分,選擇“基於對話方塊”(我們熟悉的“記事本”是典型的單文件應用程式,多文件應用程式形如Word2003。這兩種應用在現實中更實用,但本文只體驗簡單的基於對話方塊的應用程式。)
  就本文的應用而言,可以點選“完成”了。不過做為體驗而言,你可以繼續“下一步”看看,不過在隨後的介面中,不要改變預設的選項。

  當最後點選“完成”之後,在出現的介面上就可以安排所需要的控制元件了。


  2、開發介面

  先認識一下如下的設計介面(圖4),再講如何在介面上安排控制元件。

   (圖4)

  圖中的(1)-(5)分別是(請將(2)和(3)點開看一看):
  (1)解決方案資源管理器:其中列出了組成專案的所有檔案,我們還將會加入自己寫的“標頭檔案”和“原始檔”;

  (2)類檢視:其中列出了專案中出現的所有類,可以檢視這些類的資料成員、成員函式,以及這些類的“基型別”。(建議一定要看一看,這對理解我們剛剛學過的抽象類的理解很有幫助。如下圖是逐級開啟CtriangleApp類的基類,最後檢視到頂級基類CObject的情形。~CObject()是個虛擬函式,是虛解構函式,準確地講,還是純虛擬函式,因而CObject是抽象類,回顧或複習我們在多型性和虛擬函式部分的內容,回顧當時提出的在軟體工程方面的考慮,……)

   (圖5)

  話題再回到圖4。
  (3)資源檢視:列出了專案中的對話方塊、圖示等資源。在其他型別的應用程式中,像選單、工具欄等也是作為資源出現的。應用程式開發過程需要編輯各種資源。當然,本文不將此作為體驗內容。
  (4)屬性:在設計中可以修改對話方塊、控制元件等物件的屬性(實則對應的就是物件的資料成員);
  (5)工具箱:其中包括了常見應用程式介面中需要的各種“控制元件”(深刻理解:控制元件是MFC中已經定義好的供人機互動使用的類,將控制元件“拖”到介面上的動作,將對應由類例項化出其一個物件。如:用於文字編輯的控制元件 來源於MFC中定義的CEdit類,在對話方塊中“放置”一個Edit Control控制元件,即是例項化一個CEdit類的物件。)

  在你開發程式的過程中,(1)-(5)是時時需要用到的部件。但是,有時介面上並不能找到。如果哪一個東東“失蹤”了,首先要看看整個介面,是否“停靠”在了哪個邊緣。另外,點選“檢視”選單,如圖6,你可以在這裡找到你的所需。

   (圖6)

  話題扯開了一些,下面接著進行設計。

  3、在介面上佈置控制元件

  回到圖4的介面,從“工具箱”中找到“Static Text”(靜態文字)控制元件,拖到對話方塊中;在“屬性”中,將Caption屬性改為“a”(理解:Caption為該類的一個資料成員),如圖7所示:

   (圖7)

  用相同的方法,加入其他必要的控制元件(用於輸入的編輯框控制元件Edit Control和按鈕控制元件Button),並刪除嚮導自動提供的其他控制元件後,結果如圖8所示:
   (圖8)
  提示一下,如果控制元件位置用滑鼠拖著老對不齊,在選單中有“格式”,其中的對齊工具可以幫忙(看看“對齊”)。
  接著要做的工作是,在應用程式中新增成員就是,並將之與各個編輯框“聯絡”起來。以a後面的那個編輯框為例:選中編輯框,點滑鼠右鍵,選“新增變數(B)…”,然後,出現了“新增成員變數嚮導”視窗,如圖9所示,將“類別”改為value,變數型別選作double,而變數名為m_a(或者你喜歡的其他識別符號)。
  (圖9)
  同樣的方法,對其餘幾個編輯框分別新增變數,變數名分別中m_b、m_c和m_area。
  為編輯框設定與之聯絡的變數的意義在於,編輯框中輸入的值將記錄在相應的變數中,我們通過變數,就可以訪問編輯框中輸入的值,也可以將計算得到的變數的值顯示到編輯框中。換句話說,搭建起了程式中用到的變數,和視窗中的控制元件之間的橋樑。
  在專案中加入使用者自定義程式碼後,我們再設定點選“求面積”後要執行的程式碼。

  4、寫入使用者自定義的程式碼
  需要將我們自己寫的善於三角形類的程式碼加入專案。
  在“(1)解決方案資源管理器”欄中,在“標頭檔案”處點選右鍵,選“新增->新建項”,在專案中加入一個標頭檔案(檔名如:MyTriangle.h),內容是類的宣告:
class Triangle
{
public:
    Triangle(){a=1;b=1;c=1;}  
    Triangle(double x, double y, double z) {a=x; b=y; c=z;} 
    double area(void);
private:
    double a,b,c;
};
  加入標頭檔案的介面如圖10所示:
   (圖10)
  再在“原始檔”處點選右鍵,選“新增->新建項”,在專案中加入一個原始檔(檔名如:MyTriangle.cpp),內容是類中成員函式的實現(加入#include stdafx.h的理由可以暫時忽略,其他兩個包含檔案應該懂):
#include "stdafx.h"
#include <Cmath>
#include "MyTriangle.h"
double Triangle::area(void) 
{ 
    double s =(a + b + c) / 2;   
    return sqrt(s * (s - a) * (s - b) * (s - c));  
}
  將類的宣告放在標頭檔案中,而實現的程式碼分放在另一個原始檔中,是專案開發中的一般做法,要學會和習慣於這樣做。顯然,本例中這麼一點程式碼就佔一個檔案顯得誇張了。
  請體會:對一個應用而言,這些使用者自定義的程式碼是核心。用術語講,叫做“業務邏輯”。

  5、最後衝刺
  在圖8所示的介面上,選擇“求面積”按鈕並雙擊滑鼠,出現了下面的視窗(圖11)
   (圖11)
  此處,需要輸入當點選按鈕後要執行的程式碼。輸入後的程式碼是:
void CtriangleDlg::OnBnClickedButton1()
{
	// TODO: 在此新增控制元件通知處理程式程式碼
	UpdateData();   //將把介面上各控制元件輸入的值“捕獲”到與之關聯的變數中
	Triangle t1(m_a,m_b,m_c);  //定義三角形物件
	m_area=t1.area();    //求面積
	UpdateData(FALSE);   //用m_area的值更新介面上對應的控制元件的值並實現顯示
}
  另外,在triangleDlg.cpp的開始處要寫入“#include"MyTriangle.h"”,這個你應該懂,也要懂。
  最後,執行的結果如圖12所示:
   (圖12)

  三、依葫蘆畫瓢
  【任務0】隨著閱讀,重現上面的案例;
  【任務1】在以上示例基礎,為應用程式增加求周長的功能;
  【任務2】參考第8周任務3,設計分數類,並開發一個視窗式程式,可以完成分數的四則運算。可供參考的一個介面如圖13:
   (圖13)

  四、進一步的回味
  1、修改控制元件屬性
  在應用開發中,常需要改變控制元件的屬性,以達到設計目的。建議將每類控制元件的屬性都看一看,將能夠理解的學會使用。
  例如,用於顯示面積的編輯框只起顯示作用,不會用於輸入,可以將其Disabled屬性設為true,如圖所示。在圖14中,可以發現屬性視窗部分的下方,顯示對每種控制元件屬性的含義,這是在學習中可以利用的有利條件。
   (圖14)
  作為練習,試一下將顯示面積的編輯框控制元件的Visible設定為false;Password設定為true,執行程式做些體會。


  2、理解程式碼及MFC

  請將專案中由嚮導自動生成的各個檔案瀏覽一下,你將會發現我們確實已經學過了其中所包含的機制。
  以triangleDlg.h為例,定義的是CtriangleDlg 對話方塊。程式碼如下所示:
class CtriangleDlg : public CDialog
{
// 構造
public:
	CtriangleDlg(CWnd* pParent = NULL);	// 標準建構函式
// 對話方塊資料
	enum { IDD = IDD_TRIANGLE_DIALOG };
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支援
// 實現
protected:
	HICON m_hIcon;
	// 生成的訊息對映函式
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedButton1();
	double m_a;
	double m_b;
	double m_c;
	double m_area;
};
  從程式碼中可以看到,這個應用程式中定義的CtriangleDlg類繼承了CDialog類,其中的建構函式、虛擬函式等機制都有體現。還有,設定的m_a等幾個變數,都是這個類的資料成員,而OnBnClickedButton1()為這個類的成員函式。
  再對照triangleDlg.cpp閱讀,可以看到這個派生的類是如何實現的。
  如果說閱讀中的障礙,就是其中DoDataExchange等函式了。這些是在基類CDialog類,甚至CDialog類的基類中定義的了。這需要在長期的學習中,深入瞭解MFC及其機制。尤其是,理解和運用Windows程式設計中的訊息機制。
  關於MFC中類的體系,可看圖15。其中本文初步體驗過的類,已經用紅圈標註。


  (圖15)

  進一步要看的書,包括Windows程式設計、MFC方面的書籍。還有不少書是基於VC++6.0或VS2008、VS2010等的案例開發教程,也可以作為閱讀和實踐的選擇。


  五、結語

  看一個業界大牛的介面:

  

   對一個產品而言,儘管UI(使用者介面)非常重要,影響著產品的使用體驗,甚至決定著產品的成敗(想想蘋果的產品)。對學習技術的同學,介面、視窗並非應用的核心,核心仍在技術基礎,需要優先解決程式設計能力的問題。在此基礎上,再掌握開發平臺。
   這是應用開發者要走的路。


【相關博文】

C++“視窗”程式設計啟蒙 (之一)

尋找Bug記實:一個多重繼承程式的查錯

關於抄不抄作業的討論 

開放開發平臺小全 

函式返回值是否使用引用型別的問題:理解引用、返回值 

使用常物件——為共用資料加裝一個名為const的玻璃罩 

開發經驗和屁股的關係

大一學生C++部落格地址




=================== 迂者 賀利堅 CSDN部落格專欄=================
|== IT學子成長指導專欄 專欄文章的分類目錄(不定期更新) ==|
|== C++ 課堂線上專欄  賀利堅課程教學連結(分課程年級) ==|
|== 我寫的書——《逆襲大學——傳給IT學子的正能量》    ==|
===== 為IT菜鳥起飛鋪跑道,和學生一起享受快樂和激情的大學 =====




相關文章