winodws編程基礎

一、瞭解Windows 內部機制
  Windows 是一個“基於事件的,消息驅動的”操作系統。
  在Windows下執行一個程序,只要用戶進行了影響窗口的動作(如改變窗口大小或移動、單擊鼠標等)該動作就會觸發一個相應的“事件”。系統每次檢測到一個事件時,就會給程序發送一個“消息”,從而使程序可以處理該事件。每個Windows 應用程序都是基於事件和消息的,而且包含一個主事件循環,它不停地、反覆地檢測是否有用戶事件發生。每次檢測到一個用戶事件,程序就對該事件做出響應,處理完再等待下一個事件的發生。
  Windows 下的應用程序不斷地重複這一過程,直至用戶終止程序,用代碼來描述實際上也就是一個消息處理過程的while循環語句。
  下面便簡單介紹一下與 Windows 系統密切相關的幾個基本概念:

  ⒈窗口:這是我要說的第一個概念。似乎是地球人都知道的事兒了,窗口是Windows本身以及Windows 環境下的應用程序的基本界面單位,但是很多人都誤以爲只有具有標題欄、狀態欄、最大化、最小化按鈕這樣標準的方框才叫窗口。其實窗口的概念很廣,例如按鈕和對話框等也是窗口哦,只不過是一種特殊的窗口罷了。
  從用戶的角度看,窗口就是顯示在屏幕上的一個矩形區域,其外觀獨立於應用程序,事實上它就是生成該窗口的應用程序與用戶間的直觀接口;從應用程序的角度看,窗口是受其控制的一部分矩形屏幕區。應用程序生成並控制與窗口有關的一切內容,包括窗口的大小、風格、位置以及窗口內顯示的內容等。用戶打開一個應用程序後,程序將創建一個窗口,並在那裏默默地等待用戶的要求。每當用戶選擇窗口中的選項,程序即對此做出響應。

  ⒉程序:通常說的程序都是指一個能讓計算機識別的文件,接觸得最多的便是.exe型的可執行文件,這個不難理解。

  ⒊進程:說到進程,學過《操作系統》的人都很清楚,所謂進程就是應用程序的執行實例(或稱一個執行程序)。需要注意的是:進程是程序動態的描述,而上面說到的程序是靜態的描述,兩者有本質的區別。舉個例子,從網上Down了一個瑞星殺毒軟件到C盤但沒有運行,那個.exe 可執行文件叫做程序,它是一個二進制碼的文件。一旦雙擊了exe文件圖標運行程序,那個“正在運行着的瑞星殺毒”便稱爲進程,它在雙擊的那一刻被系統創建,當你關機或者在任務欄的圖標上單擊鼠標右鍵選“退出”時,進程便消亡,徹底結束了生命。進程經歷了由“創建”到“消亡”的生命期,而程序自始至終存在於你的硬盤上,不管你的機器是否啓動。

  ⒋線程:線程是進程中的一個執行單元,同一個進程中的各個線程對應於一組CPU指令、一組CPU寄存器以及一堆棧。進程本來就具有動態的含義,然而實質上是通過線程來執行體現的,從這個意義上說,Windows 中進程的動態性意義已經不是很明顯了,只算是給程序所佔的資源劃定一個範圍而已(個人觀點,純屬個人理解,不必引起爭議!),真正具有動態性意義的是線程。以前在大二學習操作系統課的時候就有個同學跟筆者提起這點,筆者還跟他駁得面紅耳赤呢!現在想想,覺得很有道理,不得不佩服那位同學對Windows內部機制瞭解得如此清楚。
  之所以在此花那麼多的篇幅說線程,是因爲下面將要介紹到多線程編程技巧,如果不理解這點,那就很難應用到實踐上,希望大家明白。

  ⒌消息:我們幾乎做每一個動作都會產生一個消息,在用鼠標指點江山的今天,鼠標被移動會產生WM_MOUSEMOVE消息,鼠標左鍵被按下會產生WM_LBUTTONDOWN的消息,鼠標右鍵按下便產生WM_RBUTTONDOWN消息等等。所有的這些都可以通過GetMessage,SendMessage等函數得到,以後的操作中我們會經常接觸到這些函數。

  ⒍事件:何謂事件?從它的字面意思我們就可以明白它的含義,如在程序運行的過程中改變窗口的大小或者移動窗口等,都會觸發相應的“事件”。

  ⒎句柄:單單一個“柄”字便可以解釋它的意思了,我們天氣熱搖扇子的時候只要抓住扇柄便可以控制整個扇子的運動了,在程序中也差不多是這個意思。通常一個句柄就可以傳遞我們所要做的事情。有經驗的讀者肯定清楚,編寫程序總是要和各種句柄打交道的,句柄是系統用來標識不同對象類型的工具,如窗口、菜單等,這些東西在系統中被視爲不同類型的對象,用不同的句柄將他們區分開來。
  看看C++ 教材中是如何給句柄下定義的:“在Win32裏,句柄是指向一個無值型對象(void *)的指針,是一個4字節長的數據”。雖然我對它的本質是什麼還是很迷惑,但我知道句柄並不是一個真正意義上的指針。從結構上看,句柄的確是一個指針,儘管它沒有指向用於存儲某個對象的內存位置(很多書都這麼說,這正是我的迷惑所在),而實際上句柄指向的是一個包含了對該對象進行的引用的位置。在編程時,只要抓住了對象的句柄就可以對該對象進行操作了(我在《一個簡單木馬程序的編寫與僞裝策略》中說到的對QQ密碼的截獲就是要找到QQ登陸窗口的句柄後纔開始截密行動的)。下面再舉個例子來說明句柄的運用:編一個程序,使QQ登陸窗口的號碼框和密碼框均變黑,相關代碼及解釋:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
HWND hCurWindow,HC,HE;//定義三個窗口句柄變量,hCurWindow用於存放QQ用戶登陸窗口的句柄,HC、HE分別存放號碼框和密碼框的句柄。
if((hCurWindow= FindWindow(NULL,"QQ用戶登錄"))!=0||(hCurWindow=FindWindow(NULL,"OICQ用戶登錄"))!=0)
{//很明顯,調用FindWindow()函數去獲得QQ登陸窗口的句柄
String str;
str.sprintf("0x%x",hCurWindow);
}
TCHAR wClassName[255];//類名變量
HC=GetWindow(hCurWindow, GW_CHILD);//得到號碼框的句柄
HE=GetWindow(HC, GW_HWNDNEXT);//接着得到密碼框的句柄
GetClassName(HE, wClassName, sizeof(wClassName));//得到類名
GetClassName(HC, wClassName, sizeof(wClassName));//得到類名
EnableWindow(HE,false);//使窗口失效
EnableWindow(HC,false);//使窗口失效
}
  以上代碼在C++ Builder下編譯通過,只要運行次程序,QQ登陸窗口的號碼框和密碼框馬上變黑色,如圖1所示,無非是EnableWindow()函數所起的作用。

圖1
  你還可以添加一個Timer控件,將上面的代碼copy到void __fastcall TForm1::Timer1Timer(TObject *Sender)函數中,並在後邊加上這一句代碼:
SendMessage(hCurWindow,WM_CLOSE,0,0); 使QQ一啓動就關閉,讓別人永遠也用不了QQ,挺有趣兒的哦,(請參考光盤內的程序一)

  ⒏API與SDK:API是英文 Application Programming Interface 的簡稱,意爲“應用程序接口”,泛指系統爲應用程序提供的一系列接口函數。其實質是程序內的一套函數調用,在編程的時候可以直接調用,而不必知道其內部實現的過程,只知道它的原型和返回值就可以了,此外,手頭經常放着一本“Windows API大全”之類的書也是必不可少的,不然你根本不知道哪些API是幹什麼用的,瞎編也編不出什麼東西來。在後面我們會介紹調用API編程的例子,調用API編程工作雖然煩瑣,但由於API函數都被封裝在dll庫裏,程序只有在運行的時候才調用的,因此程序的體積小而且運行效率高。
  SDK是英文 Software Development Kit 的縮寫,指“軟件開發工具包”,在防火牆的設計中就經常涉及到SDK。
  有關基本的概念就談這些,那些C/C++的基本語法、什麼是面向對象等知識請大家查閱相關的書,此類書籍各大書店已汗牛充棟,不再多敘。下面直接談談語種和編程工具的選擇問題,這也是初學者們最迷惑的問題。

  二、編程語言以及工具的選擇:
  從上面的介紹我們對Windows 有了進一步的瞭解,現在就該開始行動了,選擇要學的語言和工具是第一步,而且是非常重要的一步工作,筆者建議一切以簡單、易接受爲原則,不然你會自信心大減的,何必偏要跟自己過不去自討苦喫呢?
  在開始的時候很多人都感到迷惑,目前的編程語言那麼多,有c、c++、c#、java、彙編、html等等,究竟學哪些好呢?最開始我該學什麼呢?甚至有人將vc、c++ builder也列爲兩種不同的語言!這些都是對編程語言缺乏瞭解造成的。筆者開始的時候也犯過同樣的錯誤,曾經給自己寫過一份計劃書:先學c語言,接着學c++、c#、java、彙編、vb、vc、c++ builder……,哪一種語言用多少時間去專攻等等,現在回想起來覺得多麼的可笑!只要學得精,一門就夠了。從實用的角度來講,C++ 是最好的選擇(個人意見,其實每一種語言都很好),而VC和C++ Builder是其相應開發工具的兩大主流,筆者極力推薦初學者使用C++ Builder,因爲很容易上手,如果一下子就用VC的話,也許會打擊你的自信心:)。
  三、談談促進編程能力提高的兩個途徑
  如果你是一個黑客技術的狂熱者的話,到雅虎去搜索黑客教程的時候就會發現,很多的中文教程在談到如何進行黑客編程時,十有八九都會介紹以下兩大最佳途徑:一、讀程序;二、寫程序,並且都提出了教程作者的看法,下面我想談談這方面的個人觀點。
  ⒈讀程序:我將讀程序放在前面是有原因的。在你沒有閱讀過一份完整的源代碼之前,你別指望能寫出有多好的程序來!這是對每一位初學者的忠告也是警告,而且必須具備一定的語言基礎知識,這裏的基礎知識主要是指語法知識,最起碼要能讀懂別人的程序的每一行意思。有沒有程序的設計思想,在這個時期並不重要,只要具備一定的語法基礎就可以了,思想可以通過閱讀完別人的源程序後分析得來。
  記得在大一學習C語言的時候,我們都很重視語法的學習,整天都看教材、做練習,而且趕在老師的講課前預習,課後又複習鞏固,將一些語法點記得滾瓜爛熟,可後來一到做課程設計的時候,坐在電腦面前簡直是老鼠拖雞蛋—無從下手了,而且不斷的問自己:“我平時的努力哪去了?語法都會了呀,怎麼還是做不出程序來?”相信很多人都像筆者以前那樣,錯誤地以爲學會了語法就等於掌握了編程。
編程的能力包括經驗、技巧、耐心等幾個因素,而並非想象中的那樣簡單,更不要以爲編程就是簡簡單單的寫程序!
  其實學一門語言並不需要刻意去記那些條條框框的語法,在看代碼的時候,遇到了不明白的地方再去查相關的資料,一點一點補充基礎知識再配合源程序的思路,這時的理解纔是最深刻的,我可以肯定地說,這個時候對語法的接受程度絕對比你剛開始時的死記要強!
  讀程序也不能單純地讀,要真正做到“俯而讀,昂而思”。好的代碼是百讀不厭的,比如Shotgun的那道構造洪水Ping攻擊的代碼,我至少讀了20遍。筆者喜歡將從網上搜集來的代碼打印到紙上(儘管學校的打印費貴得要命,打一份代碼就得花去十幾塊甚至幾十塊大洋~~~),然後邊看邊做好眉批,遇到一個新函數記下它的功能,一些忘記了的知識在旁邊標出來,還可以寫上對程序的看法等等。特別是遇到了一些新的API函數,最好標出來,對你以後編程的時候也許會用得着,最後別忘了分析一下程序的思路,這樣對你以後編寫類似的程序很有幫助的。

  ⒉寫程序:問題可談到點子上了,學那麼多語言,讀那麼多程序最終還不是爲了寫程序,做出適合需要的軟件來?“君子性非異也,善加於物也”,筆者認爲一切從借鑑開始,先是修改別人的程序,等到有了一定的程度再寫出屬於自己的程序。
  剛開始寫程序,不要奢望一下子寫出很出色的程序來,“萬丈高樓平底起”,編程貴在動手,只要你動手去寫了,就算只有一句“printf(“Hello!”);”也是一次進步!此外,還要依照自身的能力循序漸進地寫,開始的時候寫一點功能簡單的、篇幅短小的代碼,力求簡潔、完整,“麻雀雖小,但五臟俱全”,然後在此基礎上進行擴充,一點一點添加功能,下面筆者摘錄一位國內一流編程高手、“豪傑超級解霸”的作者梁肇新的編程心得,請大家看看一個成功的程序員是如何寫程序的,希望對廣大菜鳥有所啓發:
  寫程序的方法:在Win98的環境中,先寫主幹,用最少的代碼實現最基本的功能。然後一點點添加功能,每加一點都要調試。儘量少用動態分配、全局變量。充分利用操作系統直接提供的API。在Win98下調試通過之後,再在Win95下調試通過,然後是Win97,WindowsME,WinNT4.0。這樣才能寫出穩定、快速的程序。
  給程序員的建議:1、不要急於求成,這樣往往欲速不達。2、不要什麼東西都想學,什麼都沒掌握。3、每天都要自我總結,分析自己的錯誤率和廢碼率,不斷加強自我管理。4、代碼格式很重要。代碼要規範、嚴謹,效率要高。5、不要盲從簡單的開發工具(這點筆者不是很同意,最起碼要有一定的功底的人才敢這麼說)。6、有了成果要公開,不要捨不得,不然很快會過時的(以上兩段摘自《程序員》增值合訂本2001.上冊P18,請讀者前往參考)。

參考書籍:
《Windows C 程序設計》,清華大學出版社
《超級解霸梁肇新》,《程序員》合訂本  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章