青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

使用API寫Windows程序

一 先來看個簡單實例:
#include?"windows.h"?

int?WINAPI?WinMain?(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,?PSTR?szCmdLine,?int?iCmdShow)?

{?

  MessageBox?(NULL,?TEXT?(
"你好,歡迎來到VC之路"),?TEXT?("歡迎"),?0)?;?

  
return?0?;?

}
?

第一個參數(shù):應用程序的當前實例句柄。

第二個參數(shù):應用程序的前一個實例句柄,別管它,對于Win32位而言,它一般是NULL.

第三個參數(shù):指向任何傳給程序的命令行參數(shù)。PSTR代表"指向字符串的指針"。

第四個參數(shù):它告訴應用程序如何初始化窗口,如最大化,最小化等狀態(tài)。

WinMain()所起的作用:初始化,展示,銷毀應用程序等。

MessageBox(),如果大家在windows下編程,這是一個很常用的API,不用我費話了吧!

二 消息機制

#include?"stdafx.h"?//注意,這個向導產(chǎn)生的頭文件不能去掉?

#include?
<windows.h>


LRESULT?CALLBACK?WndProc?(HWND,?UINT,?WPARAM,?LPARAM)?;

?

int?WINAPI?WinMain?(HINSTANCE?hInstance,?HINSTANCE?hPrevInstance,

????????????????????PSTR?szCmdLine,?
int?iCmdShow)

{

?????
static?TCHAR?szAppName[]?=?TEXT?("HelloWin")?;

?????HWND?????????hwnd?;

?????MSG??????????msg?;

?????WNDCLASS?????wc?;

?

?????wc.style?????????
=?CS_HREDRAW?|?CS_VREDRAW?;

?????wc.lpfnWndProc???
=?WndProc?;

?????wc.cbClsExtra????
=?0?;

?????wc.cbWndExtra????
=?0?;

?????wc.hInstance?????
=?hInstance?;

?????wc.hIcon?????????
=?LoadIcon?(NULL,?IDI_APPLICATION)?;

?????wc.hCursor???????
=?LoadCursor?(NULL,?IDC_ARROW)?;

?????wc.hbrBackground?
=?(HBRUSH)?GetStockObject?(WHITE_BRUSH)?;

?????wc.lpszMenuName??
=?NULL?;

?????wc.lpszClassName?
=?szAppName?;

?


?????
if?(!RegisterClass?(&wc))

?????
{

??????????MessageBox?(NULL,?TEXT?(
"This?program?requires?Windows?NT!"),?

??????????????????????szAppName,?MB_ICONERROR)?;

??????????
return?0?;

?????}


?????hwnd?
=?CreateWindow?(szAppName,??????????????????//?window?class?name

??????????????????????????TEXT?(
"歡迎你的到來!"),?//?window?caption

??????????????????????????WS_OVERLAPPEDWINDOW,????????
//?window?style

??????????????????????????CW_USEDEFAULT,??????????????
//?initial?x?position

??????????????????????????CW_USEDEFAULT,??????????????
//?initial?y?position

??????????????????????????CW_USEDEFAULT,??????????????
//?initial?x?size

??????????????????????????CW_USEDEFAULT,??????????????
//?initial?y?size

??????????????????????????NULL,???????????????????????
//?parent?window?handle

??????????????????????????NULL,???????????????????????
//?window?menu?handle

??????????????????????????hInstance,??????????????????
//?program?instance?handle

??????????????????????????NULL)?;?????????????????????
//?creation?parameters

?????

?????ShowWindow?(hwnd,?iCmdShow)?;

?????UpdateWindow?(hwnd)?;

?????

?????
while?(GetMessage?(&msg,?NULL,?0,?0))

?????
{

??????????TranslateMessage?(
&msg)?;

??????????DispatchMessage?(
&msg)?;

?????}


?????
return?msg.wParam?;

}


?

?

LRESULT?CALLBACK?WndProc?(HWND?hwnd,?UINT?message,?WPARAM?wParam,?LPARAM?lParam)

{

?????HDC?????????hdc?;

?????PAINTSTRUCT?ps?;

?????RECT????????rect?;

?????

?????
switch?(message)

?????
{

????

?????
case?WM_PAINT:

??????????hdc?
=?BeginPaint?(hwnd,?&ps)?;

??????????

??????????GetClientRect?(hwnd,?
&rect)?;

??????????

??????????DrawText?(hdc,?TEXT?(
"你好,歡迎你來到VC之路!"),?-1,?&rect,

????????????????????DT_SINGLELINE?
|?DT_CENTER?|?DT_VCENTER)?;

??????????EndPaint?(hwnd,?
&ps)?;

??????????
return?0?;

??????????

?????
case?WM_DESTROY:

??????????PostQuitMessage?(
0)?;

??????????
return?0?;

?????}


?????
return?DefWindowProc?(hwnd,?message,?wParam,?lParam)?;

}



Windows編程的特點:

C語言編程至少有一個主程序,其名字是main()。Windows程序則至少兩個主程序,一個是WinMain(),

int WINAPI WinMain(

          HINSTANCE hInstance,   // handle to current instance

          HINSTANCE hPrevInstance,  // handle to previous instance

          LPSTR lpCmdLine,     // command line

          int nCmdShow     // show state

         );

另一個是窗口過程函數(shù)WndProc,它的函數(shù)原型為:

long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);

Windows應用程序的編程就圍繞這兩個部份進行的。其中WinMain函數(shù)為應用程序的入口點,它的名字一定要是WinMain。

在Windows中,應用程序通過要求Windows完成指定操作,而承擔這項通信任務的API函數(shù)就是Windows的相應窗口函數(shù)WndProc。在dos里,程序能直接控制事件的發(fā)生順

序,結果等。而在Windows里,應用程序不直接調用任何窗口函數(shù),而是等待Windows調用窗口函數(shù),請求完成任務或返回信息。為保證Windows調用這個窗口函數(shù),這個函

數(shù)必須先向Windows登記,然后在Windows實施相應操作時回調,所以窗口函數(shù)又稱為回調函數(shù)。WndProc是一個主回調函數(shù),Windows至少有一個回調函數(shù)。

回調函數(shù)WndProc在哪里定義的呢,請看這個語句:wc.lpfnWndProc = WndProc .

我把這個程序支解為四塊:
(一)建立,注冊窗口類.
(二)創(chuàng)建窗口.
(三)顯示和更新窗口.
(四)創(chuàng)建消息循環(huán).
(五)終止應用程序.
(六)窗口過程.
(七)處理消息.


(一)注冊窗口類:

(1)建立窗口類

WinMain()是程序的入口,它相當于一個中介人的角色,把應用程序(指小窗口)介紹給windows.首要的一步是登記應用程序的窗口類.

窗口種類是定義窗口屬性的模板,這些屬性包括窗口式樣,鼠標形狀,菜單等等,窗口種類也指定處理該類中所有窗口消息的窗口函數(shù).只有先建立窗口種類,才能根據(jù)窗口種類來創(chuàng)建Windows應用程序的一個或多個窗口.創(chuàng)建窗口時,還可以指定窗口獨有的附加特性.窗口種類簡稱窗口類,窗口類不能重名.在建立窗口類后,必須向Windows登記.

建立窗口類就是用WNDCLASS結構定義一個結構變量,在這個程序中就是指WNDCLASS wc ;然后用自己設計的窗口屬性的信息填充結構變量wc的域.

要WinMain登記窗口類,首先要填寫一個WNDCLASS結構,其定義如下所示:

   typedef struct _WNDCLASSA

   {

     UINT style ;         //窗口類風格

     WNDPROC lpfnWndProc ;    //指向窗口過程函數(shù)的指針

     int cbClsExtra ;       //窗口類附加數(shù)據(jù)

     int cbWndExtra ;       //窗口附加數(shù)據(jù)

     HINSTANCE hInstance ;    //擁有窗口類的實例句柄

     HICON hIcon ;        //最小窗口圖標

     HCURSOR hCursor ;      //窗口內使用的光標

     HBRUSH hbrBackground ;   //用來著色窗口背景的刷子

     LPCSTR lpszMenuName ;    //指向菜單資源名的指針

     LPCSTR lpszClassName ;   // 指向窗口類名的指針

   }

在VC6.0里面,把光標定位在WNDCLASS上,按F1,即可啟動MSDN,在MSDN里你可看到這個結構原形.在下節(jié)講解這些參數(shù)在本程序中的具體用法.

(2)注冊窗口類

(1)第一個參數(shù):成員style控制窗口的某些重要特性,在WINDOWS.H中定義了一些前綴為CS的常量,在程序中可組合使用這些常量.也可把sytle設為0.本程序中為wc.style = CS_HREDRAW | CS_VREDRAW,它表示當窗口的縱橫坐標發(fā)生變化時要重畫整個窗口。你看:無論你怎樣拉動窗口的大小,那行字都會停留在窗口的正中部,而假如把這個參數(shù)設為0的話,當改動窗口的大小時,那行字則不一定處于中部了。

(2)第二個參數(shù):lpfnWndProc包括一個指向該窗口類的消息處理函數(shù)的指針,此函數(shù)稱為窗口過程函數(shù)。它將接收Windows發(fā)送給窗口的消息,并執(zhí)行相應的任務。其原型為:

long FAR PASCAL WndProc(HWND ,unsigned,WORD,LONG);并且必須在模快定義中回調它。WndProc是一個回調函數(shù)(見第五節(jié)),如果暫時無法理解這個模糊的概念意味著什么,可先放過,等到講消息循環(huán)時再詳談。

(3)第三,四個參數(shù):cbWndExtra域指定用本窗口類建立的所有窗口結構分配的額外字節(jié)數(shù)。當有兩個以上的窗口屬于同一窗口類時,如果想將不同的數(shù)據(jù)和每個窗口分別相對應。則使用該域很有用。這般來講,你只要把它們設為0就行了,不必過多考慮。

(4)第五個參數(shù):hInstance域標識應用程序的實例hInstance,當然,實例名是可以改變的。wc.hInstance = hInstance ;這一成員可使Windows連接到正確的程序。

(5)第六個參數(shù):成員hIcon被設置成應用程序所使用圖標的句柄,圖標是將應用程序最小化時出現(xiàn)在任務欄里的的圖標,用以表示程序仍駐留在內存中。Windows提供了一些默認圖標,我們也可定義自己的圖標,VC里面專有一個制作圖標的工具。

(6)第七個參數(shù): hCursor域定義該窗口產(chǎn)生的光標形狀。LoadCursor可返回固有光標句柄或者應用程序定義的光標句柄。IDC_ARROW表示箭頭光標.

(7)第八個參數(shù):wc.hbrBackground域決定Windows用于著色窗口背景的刷子顏色,函數(shù)GetStockObject返回窗口的顏色,本程序中返回的是白色,你也可以把它改變?yōu)榧t色等其他顏色.試試看

(8)第九個參數(shù):lpszMenuName用來指定菜單名,本程序中沒有定義菜單,所以為NULL。

(9)第十個參數(shù):lpszClassName指定了本窗口的類名。

當對WNDCLASS結構域一一賦值后,就可注冊窗口類了,在創(chuàng)建窗口之前,是必須要注冊窗口類的,注冊窗口類用的API函數(shù)是RegisterClass,注冊失敗的話,就會出現(xiàn)一個對話框如程序所示,函數(shù)RegisterClass返回0值,也只能返回0值,因為注冊不成功,程序已經(jīng)不能再進行下去了。

在本程序中注冊窗口類如下:

if (!RegisterClass (&wc)) {

       MessageBox (NULL, TEXT ("This program requires Windows NT!"),

               szAppName,MB_ICONERROR) ;

       return 0 ;

             }

(二)創(chuàng)建窗口

注冊窗口類后,就可以創(chuàng)建窗口了,本程序中創(chuàng)建窗口的有關語句如下:

 hwnd = CreateWindow (szAppName,   ????????????????? // window class name

????????????????????????? TEXT ("歡迎你的到來!"),    // window caption

????????????????????????? WS_OVERLAPPEDWINDOW,??????? // window style

????????????????????????? CW_USEDEFAULT,????????????? // initial x position

????????????????????????? CW_USEDEFAULT,????????????? // initial y position

????????????????????????? CW_USEDEFAULT,????????????? // initial x size

????????????????????????? CW_USEDEFAULT,????????????? // initial y size

????????????????????????? NULL,?????????????????????? // parent window handle

????????????????????????? NULL,?????????????????????? // window menu handle

????????????????????????? hInstance,????????????????? // program instance handle

????????????????????????? NULL) ;???????????????????? // creation parameters

參數(shù)1:登記的窗口類名,這個類名剛才咱們在注冊窗口時已經(jīng)定義過了。

參數(shù)2:用來表明窗口的標題。

參數(shù)3: 用來表明窗口的風格,如有無最大化,最小化按紐啊什么的。

參數(shù)4,5: 用來表明程序運行后窗口在屏幕中的坐標值。

參數(shù)6,7: 用來表明窗口初始化時(即程序初運行時)窗口的大小,即長度與寬度。

參數(shù)8: 在創(chuàng)建窗口時可以指定其父窗口,這里沒有窗口則參數(shù)值為0。

參數(shù)9: 用以指明窗口的菜單,菜單以后會講,這里暫時為0。

最后一個參數(shù)是附加數(shù)據(jù),一般都是0。

CreateWindow()的返回值是已經(jīng)創(chuàng)建的窗口的句柄,應用程序使用這個句柄來引用該窗口。如果返回值為0,就應該終止該程序,因為可能某個地方出錯了。如果一個程序創(chuàng)建了多個窗口,則每個窗口都有各自不同的句柄.

(三)顯示和更新窗口

???? API函數(shù)CreateWindow創(chuàng)建完窗口后,要想把它顯示出現(xiàn),還必須調用另一個API函數(shù)ShowWindows.形式為:

ShowWindow (hwnd, iCmdShow);

其第一個參數(shù)是窗口句柄,告訴ShowWindow()顯示哪一個窗口,而第二個參數(shù)則告訴它如何顯示這個窗口:最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),還是最大化(SW_SHOWMAXIMIZED)。WinMain在創(chuàng)建完窗口后就調用ShowWindow函數(shù),并把iCmdShow參數(shù)傳送給這個窗口。你可把iCmdShow改變?yōu)檫@些參數(shù)試試。

WinMain()調用完ShowWindow后,還需要調用函數(shù)UpdateWindow,最終把窗口顯示了出來。調用函數(shù)UpdateWindow將產(chǎn)生一個WM_PAINT消息,這個消息將使窗口重畫,即使窗口得到更新.

(四)創(chuàng)建消息循環(huán)

主窗口顯示出來了,WinMain就開始處理消息了,怎么做的呢?

Windows為每個正在運行的應用程序都保持一個消息隊列。當你按下鼠標或者鍵盤時,Windows并不是把這個輸入事件直接送給應用程序,而是將輸入的事件先翻譯成一個消息,然后把這個消息放入到這個應用程序的消息隊列中去。應用程序又是怎么來接收這個消息呢?這就講講消息循環(huán)了。

應用程序的WinMain函數(shù)通過執(zhí)行一段代碼從她的隊列中來檢索Windows送往她的消息。然后WinMain就把這些消息分配給相應的窗口函數(shù)以便處理它們,這段代碼是一段循環(huán)代碼,故稱為"消息循環(huán)"。這段循環(huán)代碼是什么呢?好,往下看:

在咱們的第二只小板凳中,這段代碼就是:

......

MSG msg; //定義消息名

while (GetMessage (&msg, NULL, 0, 0))

???? {

????????? TranslateMessage (&msg) ; //翻譯消息

????????? DispatchMessage (&msg) ; //撤去消息

???? }

???? return msg.wParam ;

MSG結構在頭文件中定義如下:

typedef struct tagMSG

{

HWND hwnd;

UINT message;

WPARAM wParam;

LPARAM lParam;

DWORD time;

POINT pt;

} MSG, *PMSG;

MSG數(shù)據(jù)成員意義如下:

參數(shù)1:hwnd是消息要發(fā)送到的那個窗口的句柄,這個窗口就是咱們用CreateWindows函數(shù)創(chuàng)建的那一個。如果是在一個有多個窗口的應用程序中,用這個參數(shù)就可決定讓哪個窗口接收消息。

參數(shù)2:message是一個數(shù)字,它唯一標識了一種消息類型。每種消息類型都在Windows文件中定義了,這些常量都以WM_開始后面帶一些描述了消息特性的名稱。比如說當應用程序退出時,Windows就向應用程序發(fā)送一條WM_QUIT消息。

參數(shù)3:一個32位的消息參數(shù),這個值的確切意義取決于消息本身。

參數(shù)4:同上。

參數(shù)5:消息放入消息隊列中的時間,在這個域中寫入的并不是日期,而是從Windows啟動后所測量的時間值。Windows用這個域來使用消息保持正確的順序。

參數(shù)6:消息放入消息隊列時的鼠標坐標.

消息循環(huán)以GetMessage調用開始,它從消息隊列中取出一個消息:

GetMessage(&msg,NULL,0,0),第一個參數(shù)是要接收消息的MSG結構的地址,第二個參數(shù)表示窗口句柄,NULL則表示要獲取該應用程序創(chuàng)建的所有窗口的消息;第三,四參數(shù)指定消息范圍。后面三個參數(shù)被設置為默認值,這就是說你打算接收發(fā)送到屬于這個應用程序的任何一個窗口的所有消息。在接收到除WM_QUIT之外的任何一個消息后,GetMessage()都返回TRUE。如果GetMessage收到一個WM_QUIT消息,則返回FALSE,如收到其他消息,則返回TRUE。因此,在接收到WM_QUIT之前,帶有GetMessage()的消息循環(huán)可以一直循環(huán)下去。只有當收到的消息是WM_QUIT時,GetMessage才返回FALSE,結束消息循環(huán),從而終止應用程序。 均為NULL時就表示獲取所有消息。

消息用GetMessage讀入后(注意這個消息可不是WM_QUIT消息),它首先要經(jīng)過函數(shù)TranslateMessage()進行翻譯,這個函數(shù)會轉換成一些鍵盤消息,它檢索匹配的WM_KEYDOWN和WM_KEYUP消息,并為窗口產(chǎn)生相應的ASCII字符消息(WM_CHAR),它包含指定鍵的ANSI字符.但對大多數(shù)消息來說它并不起什么作用,所以現(xiàn)在沒有必要考慮它。

下一個函數(shù)調用DispatchMessage()要求Windows將消息傳送給在MSG結構中為窗口所指定的窗口過程。我們在講到登記窗口類時曾提到過,登記窗口類時,我們曾指定Windows把函數(shù)WindosProc作為咱們這個窗口的窗口過程(就是指處理這個消息的東東)。就是說,Windows會調用函數(shù)WindowsProc()來處理這個消息。在WindowProc()處理完消息后,代碼又循環(huán)到開始去接收另一個消息,這樣就完成了一個消息循環(huán)。

(五)終止應用程序:

Windows是一種非剝奪式多任務操作系統(tǒng)。只有的應用程序交出CPU控制權后,Windows才能把控制權交給其他應用程序。當GetMessage函數(shù)找不到等待應用程序處理的消息時,自動交出控制權,Windows把CPU的控制權交給其他等待控制權的應用程序。由于每個應用程序都有一個消息循環(huán),這種隱式交出控制權的方式保證合并各個應用程序共享控制權。一旦發(fā)往該應用程序的消息到達應用程序隊列,即開始執(zhí)行GetMessage語句的下一條語句。

當WinMain函數(shù)把控制返回到Windows時,應用程序就終止了。應用程序的啟動消息循環(huán)前要檢查引導出消息循環(huán)的每一步,以確保每個窗口已注冊,每個窗口都已創(chuàng)建。如存在一個錯誤,應用程序應返回控制權,并顯示一條消息。

但是,一旦WinMain函數(shù)進入消息循環(huán),終止應用程序的唯一辦法就是使用PostQuitMessage把消息WM_QUIT發(fā)送到應用程序隊列。當GetMessage函數(shù)檢索到WM_QUIT消息,它就返回NULL,并退出消息外循環(huán)。通常,當主窗口正在刪除時(即窗口已接收到一條WM_DESTROY消息),應用程序主窗口的窗口函數(shù)就發(fā)送一條WM_QUIT消息。

雖然WinMain指定了返回值的數(shù)據(jù)類型,但Windows并不使用返回值。不過,在調試一應用程序時,返回值地有用的。通常,可使用與標準C程序相同的返回值約定:0表示成功,非0表示出錯。PostQuitMessage函數(shù)允許窗口函數(shù)指定返回值,這個值復制到WM_QUIT消息的wParam參數(shù)中。為了的結束消息循環(huán)之后返回這個值,我們的第二只小板凳中使用了以下語句:

return msg.wParam ;//表示從PostQuitMessage返回的值

例如:當Windows自身終止時,它會撤消每個窗口,但不把控制返回給應用程序的消息循環(huán),這意味著消息循環(huán)將永遠不會檢索到WM_QUIT消息,并且的循環(huán)之后的語句也不能再執(zhí)行。Windows的終止前的確發(fā)送一消息給每個應用程序,因而標準C程序通常會的結束前清理現(xiàn)場并釋放資源,但Windows應用程序必須隨每個窗口的撤消而被清除,否則會丟失一些數(shù)據(jù)。

(六)窗口過程,窗口過程函數(shù)

如前所述,函數(shù)GetMessage負責從應用程序的消息隊列中取出消息,而函數(shù)DispatchMessage()要求Windows將消息傳送給在MSG結構中為窗口所指定的窗口過程。然后出臺的就是這個窗口過程了,這個窗口過程的任務是干什么呢?就是最終用來處理消息的,就是消息的處理器而已,那么這個函數(shù)就是WindowProc,在Visual C++6.0中按F1啟動MSDN,按下面這個路徑走下來:

PlatForm SDK-->User Interface services-->Windows user Interface-->Windowing-->Window Procedures-->Window Procedure Reference-->Windows Procedure Functions-->WindowProc

啊,太累了,不過我們終于的MSDN中找到了這個函數(shù),前幾次我講解這些API函數(shù)的時候,都是的知道的情況下搜索出來的,所以沒有詳細給出每個函數(shù)的具體位置,而這次我卻是一點點去找的,還好,沒被累死,體會到MSDN的龐大了吧,不過我用的是MSDN2000,是D版的,三張光盤裝。你用的MSDN如果按這個路徑走下去的話,可能會找不到,不過我想大致也是在這個位置了,找找看!!!

LRESULT CALLBACK WindowProc

(

HWND hwnd, // handle to window

UINT uMsg, // message identifier

WPARAM wParam, // first message parameter

LPARAM lParam // second message parameter

);

這個函數(shù)我們的第二只小板凳里被我們稱為WndProc.

下面講解:

不知你注意到了沒有,這個函數(shù)的參數(shù)與剛剛提到的GetMessage調用把返回的MSG結構的前四個成員相同。如果消息處理成功,WindowProc的返回值為0.

Windows的啟動應用程序時,先調用WinMain函數(shù),然后調用窗口過程,注意:在我們的這個程序中,只有一個窗口過程,實際上,也許有不止一個的窗口過程。例如,每一個不同的窗口類都 有一個與之相對應的窗口過程。無論Windows何時想傳遞一個消息到一窗口,都將調用相應的窗口過程。當Windows從環(huán)境,或從另一個應用程序,或從用戶的應用程序中得到消息時,它將調用窗口過程并將信息傳給此函數(shù)。總之,窗口過程函數(shù)處理所有傳送到由此窗口類創(chuàng)建的窗口所得到的消息。并且窗口過程有義務處理Windows扔給它的任何消息。我們在學習Windows程序設計的時候,最主要的就是學習這些消息是什么以及是什么意思,它們是怎么工作的。

令我們不解的是,在程序中我們看不出來是哪一個函數(shù)在調用窗口過程。它其實是一個回調函數(shù).前面已經(jīng)提到,Windows把發(fā)生的輸入事件轉換成輸入消息放到消息隊列中,而消息循環(huán)將它們發(fā)送到相應的窗口過程函數(shù),真正的處理是在窗口過程函數(shù)中執(zhí)行的,在Windows中就使用了回調函數(shù)來進行這種通信。

回調函數(shù)是輸出函數(shù)中特殊的一種,它是指那些在Windows環(huán)境下直接調用的函數(shù)。一個應用程序至少有一個回調函數(shù),因為在應用程序處理消息時,Windows調用回調函數(shù)。這種回調函數(shù)就是我們前面提到的窗口過程,它對對應于一個活動的窗口,回調函數(shù)必須向Windows注冊,Windows實施相應操作即行回調。

每個窗口必須有一個窗口過程與之對應,且Windows直接調用本函數(shù),因此,窗口函數(shù)必須采用FAR PASCAL調用約定。在我們的第二只小板凳中,我們的窗口函數(shù)為WndProc,必須注意這里的函數(shù)名必須是前面注冊的窗口類時,向域wc.lpfnWndProc所賦的WndProc。函數(shù)WndProc就是前面定義的窗口類所生成的所有窗口的窗口函數(shù)。

在我們的這個窗口函數(shù)中,WndProc處理了共有兩條消息:WM_PAINTWM_DESTROY.

窗口函數(shù)從Windows中接收消息,這些消息或者是由WinMain函數(shù)發(fā)送的輸入消息,或者是直接來自Windows的窗口管理消息。窗口過程檢查一條消息,然后根據(jù)這些消息執(zhí)行特定的動作未被處理的消息通過DefWindowProc函數(shù)傳回給Windows作缺海上處理。

可以發(fā)送窗口函數(shù)的消息約有220種,所有窗口消息都以WM_開頭,這些消息在頭文件中被定義為常量。引起Windows調用窗口函數(shù)的原因有很多,,如改變窗口大小啊,改變窗口在屏幕上的位置啊什么的。
(七)處理消息

窗口過程處理消息通常以switch語句開始,對于它要處理的每一條消息ID都跟有一條case語句。大多數(shù)windows proc都有具有下面形式的內部結構:

switch(uMsgId)

{

case WM_(something):

//這里此消息的處理過程

return 0;

case WM_(something else):

//這里是此消息的處理過程

ruturn 0;

default:

//其他消息由這個默認處理函數(shù)來處理

return DefWindowProc(hwnd,uMsgId,wParam,lParam);

}

在處理完消息后,要返回0,這很重要-----它會告訴Windows不必再重試了。對于那些在程序中不準備處理的消息,窗口過程會把它們都扔給DefWindowProc進行缺省處理,而且還要返回那個函數(shù)的返回值。在消息傳遞層次中,可以認為DefWindowProc函數(shù)是最頂層的函數(shù)。這個函數(shù)發(fā)出WM_SYSCOMMAND消息,由系統(tǒng)執(zhí)行Windows環(huán)境中多數(shù)窗口所公用的各種通用操作,例如,畫窗口的非用戶區(qū),更新窗口的正文標題等等等等。

再提示一下,以WM_的消息在Windows頭文件中都被定義成了常量,如WM_QUIT=XXXXXXXXXXX,但我們沒有必要記住這個數(shù)值,也不可能記得住,我們只要知道WM_QUIT就OK了。

在第二只小板凳中我們只讓窗口過程處理了兩個消息:一個是WM_PAINT,另一個是WM_DESTROY,先說說第一個消息---WM_PAINT.

關于WM_PAINT:

無論何時Windows要求重畫當前窗口時,都會發(fā)該消息。也可以這樣說:無論何時窗口非法,都必須進行重畫。 哎呀,什么又是"非法窗口"?什么又是重畫啊?你這人有沒有完,嗯?

稍安勿燥,我比你還煩呢?我午飯到現(xiàn)在還沒吃呢!你有點耐心,來點專業(yè)精神好不好???我開始在MSDN里面找有關這個方面的內容了,別急,我找找看:

Platform SDK-->Graphics and Multimedia Services-->Windows GDI-->Painting and Drawing-->Using the WM_PAINT Message-----終于找到了。

下面是一大套理論:

讓我們把Windows的屏幕想像成一個桌面,把一個窗口想像成一張紙。當我們把一張紙放到桌面上時,它會蓋住其他的紙,這樣被蓋住的其他紙上的內容都看不到了。但我們只要把這張紙移開,被蓋住的其他紙上的內容就會顯示出來了---這是一個很簡單的道理,誰都明白。

對于我們的屏幕來說,當一個窗口被另一窗口蓋住時,被蓋住的窗口的某些部分就看不到了,我們要想看到被蓋住的窗口的全部面貌,就要把另一個窗口移開,但是當我們移開后,事情卻起了變化-----很可能這個被蓋住的窗口上的信息被擦除了或是丟失了。當窗口中的數(shù)據(jù)丟失或過期時,窗口就變成非法的了---或者稱為"無效"。于是我們的任務就來了,我們必須考慮怎樣在窗口的信息丟失時"重畫窗口"--使窗口恢復成以前的那個樣子。這也就是我們在這第二只小板凳中調用UpdateWindow的原因。

你忘記了嗎?剛才我們在(三)顯示和更新窗口中有下面的一些文字:

WinMain()調用完ShowWindow后,還需要調用函數(shù)UpdateWindow,最終把窗口顯示了出來。調用函數(shù)UpdateWindow將產(chǎn)生一個WM_PAINT消息,這個消息將使窗口重畫,即使窗口得到更新.---這是程序第一次調用了這條消息。

為重新顯示非法區(qū)域,Windows就發(fā)送WM_PAINT消息實現(xiàn)。要求Windows發(fā)送WM_PAINT的情況有改變窗口大小,對話框關閉,使用了UpdateWindows和ScrollWindow函數(shù)等。這里注意,Windows并非是消息WM_PAINT的唯一來源,使用InvalidateRect或InvalidateRgn函數(shù)也可以產(chǎn)生繪圖窗口的WM_PAINT消息......

通常情況下用BeginPaint()來響應WM_PAINT消息。如果要在沒有WM_PAINT的情況下重畫窗口,必須使用GetDC函數(shù)得到顯示緩沖區(qū)的句柄。這里面不再擴展。詳細見MDSN。

這個BeginPaint函數(shù)會執(zhí)行準備繪畫所需的所有步驟,包括返回你用于輸入的句柄。結束則是以EndPaint();

在調用完BeginPaint之后,WndProc接著調用GetClientRect:

GetClientRect(hwnd,&rect);

第一個參數(shù)是程序窗口的句柄。第二個參數(shù)是一個指針,指向一個RECT類型的結構。查MSDN,可看到這個結構有四個成員。

WndProc做了一件事,他把這個RECT結構的指針傳送給了DrawText的第四個參數(shù)。函數(shù)DrawText的目的就是在窗口上顯示一行字----"你好,歡迎你來到VC之路!",有關這個函數(shù)的具體用法這里也沒必要說了吧。

關于WM_DESTROY

這個消息要比WM_PAINT消息容易處理得多:只要用戶關閉窗口,就會發(fā)送WM_DESTROY消息(在窗口從屏幕上移去后)。

程序通過調用PostQuitMessage以標準方式響應WM_DESTROY消息:

PostQuitMessage (0) ;

這個函數(shù)在程序的消息隊列中插入一個WM_QUIT消息。(四)創(chuàng)建消息循環(huán)中我們曾有這么一段話:

消息循環(huán)以GetMessage調用開始,它從消息隊列中取出一個消息:

.......

在接收到除WM_QUIT之外的任何一個消息后,GetMessage()都返回TRUE。如果GetMessage收到一個WM_QUIT消息,則返回FALSE,如收到其他消息,則返回TRUE。因此,在接收到WM_QUIT之前,帶有GetMessage()的消息循環(huán)可以一直循環(huán)下去。只有當收到的消息是WM_QUIT時,GetMessage才返回FALSE,結束消息循環(huán),從而終止應用程序。


來自:SDK路報 ,很感謝

posted on 2006-08-21 14:36 夢在天涯 閱讀(3136) 評論(4)  編輯 收藏 引用 所屬分類: CPlusPlusWindows API

評論

# re: 使用API寫Windows程序 2007-10-04 13:59 fun

很不錯啊 值得關注 謝謝啦!!!  回復  更多評論   

# re: 使用API寫Windows程序 2007-11-08 15:24 下風

不錯,辛苦l(xiāng)z  回復  更多評論   

# re: 使用API寫Windows程序 2011-04-11 14:32 ywt

好文章  回復  更多評論   

公告

EMail:itech001#126.com

導航

統(tǒng)計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1811982
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              亚洲肉体裸体xxxx137| 欧美激情视频一区二区三区在线播放| 久久精品国产亚洲aⅴ| 国产精品欧美日韩一区二区| 亚洲制服av| 亚洲一区二区三区欧美| 国产精品一级久久久| 久久精品亚洲精品| 久久尤物电影视频在线观看| 最新日韩精品| 一本色道久久88综合日韩精品| 国产精品一区二区久久久久| 久久看片网站| 欧美mv日韩mv亚洲| 亚洲欧美亚洲| 久久美女性网| 99视频在线精品国自产拍免费观看 | 欧美大胆人体视频| 免费观看欧美在线视频的网站| 99国产精品视频免费观看| 亚洲级视频在线观看免费1级| 欧美日韩免费一区二区三区| 午夜日韩在线| 久久激五月天综合精品| 亚洲精品在线二区| 欧美一级艳片视频免费观看| 亚洲欧洲精品一区| 日韩亚洲一区在线播放| 国产综合色在线| 亚洲精品一级| 精品99视频| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 夜夜嗨av一区二区三区网页| 国产在线精品自拍| 99视频一区二区| 在线观看精品| 亚洲精品在线视频观看| 性刺激综合网| 亚洲午夜电影网| 葵司免费一区二区三区四区五区| 亚洲天堂偷拍| 免费亚洲一区| 久久婷婷国产综合精品青草 | 久久精品国产99精品国产亚洲性色| 99国产精品久久久久老师| 久久精品国产v日韩v亚洲| 先锋影音久久| 欧美三级网址| 亚洲三级影院| 日韩一级大片| 欧美成人免费在线观看| 可以免费看不卡的av网站| 欧美日韩在线亚洲一区蜜芽| 一本大道久久a久久精二百| 激情亚洲网站| 亚洲欧美国产va在线影院| 正在播放亚洲| 欧美精品xxxxbbbb| 精品51国产黑色丝袜高跟鞋| 亚洲专区在线| 久久精品动漫| 国产亚洲欧美日韩日本| 午夜国产欧美理论在线播放 | 国内精品一区二区| 性欧美大战久久久久久久免费观看 | 羞羞答答国产精品www一本| 欧美日韩国产综合视频在线| 亚洲国产一区二区三区高清| 亚洲精品欧洲精品| 欧美激情一区二区三区| 亚洲破处大片| 亚洲尤物视频网| 国产精品每日更新| 亚洲欧美激情四射在线日| 欧美怡红院视频一区二区三区| 国产精品盗摄久久久| 在线综合亚洲| 久久久国产成人精品| 国内久久婷婷综合| 美女主播一区| 亚洲欧洲视频在线| 亚洲在线成人精品| 国产精品视频免费在线观看| 先锋影音一区二区三区| 麻豆久久婷婷| 一区二区三区 在线观看视| 国产精品久久久久久久久久免费| 亚洲婷婷综合色高清在线| 久久国产精品高清| 亚洲人成毛片在线播放| 国产精品播放| 玖玖玖国产精品| 亚洲免费观看视频| 久久天堂精品| 一区二区三区视频在线观看| 国产婷婷色综合av蜜臀av| 男女视频一区二区| 亚洲一本大道在线| 欧美va天堂在线| 亚洲一区免费网站| 亚洲高清视频一区二区| 欧美日韩精品免费观看视频| 欧美在线视频a| 在线观看一区欧美| 欧美日韩三区四区| 久久视频在线看| av不卡在线| 欧美大片在线观看一区| 午夜精品视频| 日韩亚洲欧美一区二区三区| 国产主播一区| 欧美午夜不卡视频| 美女视频黄 久久| 羞羞色国产精品| 亚洲日本电影| 欧美二区在线看| 欧美自拍偷拍午夜视频| 久久激情一区| 欧美激情免费在线| 欧美一区三区二区在线观看| 99视频日韩| 亚洲高清资源| 国语自产精品视频在线看抢先版结局| 欧美伦理影院| 欧美~级网站不卡| 久久精品成人| 午夜精品区一区二区三| 在线亚洲伦理| 99视频在线观看一区三区| 亚洲国产精品成人久久综合一区| 久久精品视频在线看| 亚洲一区综合| 中文有码久久| 一本久久综合亚洲鲁鲁| 日韩一区二区精品视频| 亚洲日本中文字幕区| 亚洲国产日韩一级| 在线精品视频在线观看高清 | 午夜视黄欧洲亚洲| 亚洲一区欧美激情| 亚洲欧美日本另类| 亚洲欧美福利一区二区| 午夜久久影院| 久久成人一区二区| 久久国产黑丝| 久久婷婷人人澡人人喊人人爽| 久久精品91久久久久久再现| 欧美在线关看| 久久久综合精品| 久久亚洲捆绑美女| 欧美chengren| 欧美日韩国产一级片| 国产精品久久中文| 国产亚洲人成网站在线观看 | 老色鬼久久亚洲一区二区| 狼人天天伊人久久| 欧美极品一区| 国产精品v欧美精品∨日韩| 国产精品videosex极品| 国产一区二区三区直播精品电影 | 欧美视频免费在线| 国产欧美日韩精品a在线观看| 国产欧美日韩精品专区| 红桃视频一区| 亚洲作爱视频| 亚洲第一精品在线| 亚洲免费av片| 午夜视频一区| 免费不卡中文字幕视频| 亚洲日本黄色| 欧美一区二区三区视频免费| 免费不卡在线视频| 国产精品久久久久久久久久久久| 国内精品久久久久久| 亚洲精品一级| 欧美一级午夜免费电影| 母乳一区在线观看| 亚洲国产欧美一区二区三区丁香婷 | 一色屋精品视频在线看| 亚洲另类春色国产| 久久精品日韩欧美| 亚洲精品久久视频| 欧美一级视频免费在线观看| 欧美精品黄色| 国产主播精品在线| 亚洲一二三区精品| 老牛嫩草一区二区三区日本 | 亚洲欧美日韩中文视频| 乱中年女人伦av一区二区| 欧美性淫爽ww久久久久无| 日韩视频在线观看一区二区| 亚洲激情中文1区| 亚洲午夜伦理| 欧美国产日韩免费| 国产欧美日韩一区二区三区| aa成人免费视频| 老司机成人在线视频| 亚洲自拍电影| 欧美日韩一区三区四区| 亚洲精品一区二区三区av|