第二部分 Windows編程、物件導向程式設計

來源:互聯網
上載者:User

http://www.cnblogs.com/inshion/archive/2009/01/10/1372887.html

2.1 Windows編程回顧
  提到Windows編程,簡單地說,就是調用WIndows API做Windows應用程式。比如畫個視窗,寫個菜單,放個按鈕,響應響應滑鼠之類的。基本上所有的相關入門教程,都會用以下這樣一個小例子,來示範一個最簡單的Windows應用:

//------------Start---------------
#include ...

//回呼函數
LRESULT   WndProc(){
  //switch msg
  ...
  WM_PAINT:
  OnPaint();
  ...
}

void OnPaint(){ //draw }

//入口
int WinMain(){
  //1:註冊視窗類別,並將該視窗的回呼函數調為WndProc
  //2:建立並顯示視窗
  //3:進入訊息迴圈

}


//------------End---------------

 
 從上面程式可以看出,正常的Windows程式編寫,都會有上述的1、2、3步。這樣一來,運行時一個Win表單就會誕生,並且源源不斷地接收系統和用
戶發給它的各種訊息,比如單擊、移動、關閉等。然後在此基礎上,我們就可以編寫自己的功能,比如每當單擊視窗的某一處就顯示一個圖片、每當使用者點關閉按
鈕,就彈出一個提示框,等等諸如此類的操作。這些功能都需要在WndProc的switch語句中添加。由此就產生了一個問題。
  “我是不是需要經常改動WndProc或者它所調用的函數(如OnPaint)的內容?”
 
 OK,一般說來,是這樣的。所以這會給開發造成很多麻煩,比如需要經常修改同一段代碼,又比如每建立一個應用程式,都要重複寫以上的那個結構…等等等
等。於是我們就鬱悶了,開始考慮怎麼才能來點兒一勞永逸的辦法,使得上述那樣3步可以固化下來,以後再要開發,只需要寫功能,不需要對已經寫好的東西再複
制或者修改了。幸運的是,物件導向的開發方法給了我們很好的解決方案。

2.2圖解程式結構
  結過分析,我們發現Window應用程式,一般都有著如下的結構。
  即入口WinMain通過一個全域的Application *
application來調用Application的InitInstance()方法,而Application::InitInstance()中
又調用Window::Create()方法。這樣一來,Window被建立,而系統、使用者訊息,如WM_PAINT之類的就可以傳由Window的相應
處理函數來處理。這樣一來,程式底層就完成了,簡單地說,這是一個沒有任何功能的,但是可以接受各種訊息的Windows應用。

  當我們想添加自己的功能時,只需要按照所示,分別繼承Application和Window類。並在WinMain執行之前讓全域的application指向MyApp的執行個體,這樣一來,新程式中所有的訊息就會轉到我們自己的MyWin類中來處理,我們就可以隨心所欲地添加自己的功能。

  到此,可能有人會有疑問:“在WinMain執行之前讓全域的application指向MyApp的執行個體”?WinMain不是程式入口嗎,怎麼能在它執行之前還能做別的操作?
  這個問題甚至不需要回答,如果有此疑問的,請運行下面這樣一段小程式,看看輸出就明白了,為什麼在WinMain之前還可以做很多很多操作:

Code 001
//------------Start---------------
#include <iostream>
using namespace std;

int main() {
    cout << "我是 main()中第一行,我總是會第一個輸出的吧! " << endl; // prints !!!Hello World!!!
    return 0;
}
class A{
public:
    A(){
        cout<<"哈哈,那可不一定,我就會比main()早執行哦~"<<endl;
    }
};
A a;
//--------------End---------------


2.3用對象封裝WindowsAPI
  物件導向編程的重點在於需要進行抽象。
  來看看上述的WIndows程式的建立過程,都是那樣3步,於是我們把它總結出來,寫成這樣幾個部分。
//----------------------------
class App{
  App(){ app = this; }
  init();//調用Window的create方法
  run();//3:進入訊息迴圈
  Window * MainWin;
}
App * app;
//----------------------------

//----------------------------
class Window{
  create();//1:註冊視窗類別,並將該視窗的回呼函數調為WndProc 2:建立並顯示視窗
  virtual WndProc();//將訊息映射到具體的處理函數 如WM_PAINT映射到OnPaint()
  virtual OnPaint();
  ...
}    
//----------------------------

//----------------------------
//入口
int WinMain(){
  app->init();
  app->run()
}
//----------------------------
  OK,這個結構是什麼意思?簡單地說,就是把應用程度做成一個類,視窗做成一個類。程式入口調用程式的init()方法,該方法會調用視窗的create()方法,最後調用程式的run()方法完成程式的載入。
  這樣做的好處是什嗎?
  回答是:可以完全不改動這些代碼,只需要添加新的代碼,並且新的代碼只需要關注自己新的功能,不需要知道訊息從哪來,往哪去就可以開發出我們自己的應用程式!
  為什麼可以這樣?
  舉例說明一下。(注意那個App的指標app,以及App建構函式中的app = this;,再看看那幾個virtual函數。)
  比如我們要建立自己的應用,可以寫一個如下的類:

//----------------------------
MyApp theApp;
  MyApp : public App{
  Window win;
  init(){ win.create(); MainWin = &win; }
}
//----------------------------

//----------------------------
MyWin: public Window{
  OnPaint();
  OnClose();
  ...
}
//----------------------------

  只要這樣,我們就可以在MyWin的OnXXXX()方法裡實現我們自己的功能,而前面編好的那幾個類,可以不做任何改動,就可以支撐起整個程式的程序呼叫,我們甚至不需要上面那些原始碼了,只需要將編譯好的庫和標頭檔引進來,就可以在其基礎上進行擴充。
 
 整個調用過程是,App的執行個體化由MyApp theApp;完成,由於App的建構函式中有app = 
this;,所以此時app指向的是MyApp的執行個體。當程式接收到訊息時,會通過WndProc找到對應的處理函數(比如WM_PAINT對應到
OnPaint()方法),此時會調用MainWin->OnPaint()。而由於MainWin的執行個體是MyApp::init()中產生的,
是MyWin的執行個體,而MyWin中將virtual的OnPaint()進行了重載,所以該調用會調到MyWin::OnPaint()方法。
  總結起來,這實際上完成了一個將WindowsAPI的過程封裝成C++類的過程,用類和對象架起了使用者調用與WindowsAPI之間的一座橋樑。這裡可以提一句關於MFC的話題,MFC所做的事情,就是這樣一個將WindowsAPI的過程封裝成C++類的過程,當然,它的結構更為嚴謹而複雜,考慮的事情也更多,遠不是一兩句話能說完,不過其思想與程式封裝完的入口,與上述過程如出一轍。
  至此,我們就清楚了如何用物件導向思想解決Windows程式的問題。在下一部分中,我將完整地給出一個C++程式(Eclipse+CDT),並且總結一些Eclipse中編譯運行之可能遇到的問題,用以完成這部分所描述的內容。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.