• <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>


              盡管Windows應(yīng)用程序千變?nèi)f化,令人眼花繚亂,但,消息機(jī)制和窗口過程卻始終它們的基礎(chǔ),掌握了這兩項(xiàng)技術(shù),也就相當(dāng)于把握住了問題的關(guān)鍵。

              如果你以前是C程序員或是MFC的忠實(shí)用戶,只要你學(xué)習(xí)過C語言的語法,自己親手編過一些簡短的C程序,理解以下的Win32編程基礎(chǔ)也不是一件困難的事。

              一個(gè)最簡單的Win32程序

              在以前的C語言編程中,一個(gè)最簡單的程序可以只有兩行。

            void main(void)

            { printf "Hello World!"; }

              而要實(shí)現(xiàn)同樣功能的Windows程序卻最少也要寫幾十行,這并不是說明Windows應(yīng)用程序效率低下,難于掌握,只是說明程序在Windows環(huán)境下有更豐富的內(nèi)涵。Windows程序的效率其實(shí)不低,在所有的Windows應(yīng)用程序中,都有一個(gè)程序初始化的過程,這得用上幾十條語句,這段初始化的代碼對(duì)于任何Windows應(yīng)用程序而言,都是大同小異的。下面以一個(gè)實(shí)現(xiàn)最簡單功能的程序EasyWin為例,說明Windows程序的基本框架。

              打開Visual C++ 6.0。

              選擇File菜單的New,在出現(xiàn)的對(duì)話框中,選擇Projects欄目(新建工程),并點(diǎn)取其下的Win32 Application項(xiàng),表示使用Win32環(huán)境創(chuàng)建應(yīng)用程序。先在Locatin(路徑)中填入“c:\”,然后在Project Name(項(xiàng)目名稱)中填入“EasyWin”,其它按照缺省設(shè)置)。單擊OK按鈕。

              再次選擇File菜單的New,在出現(xiàn)的對(duì)話框中,選擇Files欄目(新建文件),并點(diǎn)取其下的C++ Source File項(xiàng),表示新建一個(gè)C++源文件。在右邊的File欄中輸入“EasyWin”,最后確定讓Add to project檢查框打上勾 )。單擊OK按鈕。



              在EasyWin.cpp文件中輸入以下源程序代碼。  
             
            //*******************************************************************
            // 工程:easywin
            // 文件:easywin.cpp
            // 內(nèi)容:一個(gè)基本的Win32程序//*******************************************************************

            #include <windows.h>

            #include <windowsx.h>

            //函數(shù)聲明

            BOOL InitWindow( HINSTANCE hInstance, int nCmdShow );

            LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );

            //*******************************************************************

            //函數(shù):WinMain()

            //功能:Win32應(yīng)用程序入口函數(shù)。創(chuàng)建主窗口,處理消息循環(huán)

            //*******************************************************************

            int PASCAL WinMain( HINSTANCE hInstance, //當(dāng)前實(shí)例句柄

            HINSTANCE hPrevInstance, //前一個(gè)實(shí)例句柄

            LPSTR lpCmdLine, //命令行字符

            int nCmdShow) //窗口顯示方式

            {

            MSG msg;

            //創(chuàng)建主窗口

            if ( !InitWindow( hInstance, nCmdShow ) )

            return FALSE;

            //進(jìn)入消息循環(huán):

            //從該應(yīng)用程序的消息隊(duì)列中檢取消息,送到消息處理過程,

            //當(dāng)檢取到WM_QUIT消息時(shí),退出消息循環(huán)。

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

            {

            TranslateMessage(&msg);

            DispatchMessage(&msg);

            }

            //程序結(jié)束

            return msg.wParam;

            }

            //******************************************************************

            //函數(shù):InitWindow()

            //功能:創(chuàng)建窗口。

            //******************************************************************

            static BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )

            {

            HWND hwnd; //窗口句柄

            WNDCLASS wc; //窗口類結(jié)構(gòu)

            //填充窗口類結(jié)構(gòu)

            wc.style = CS_VREDRAW | CS_HREDRAW;

            wc.lpfnWndProc = (WNDPROC)WinProc;

            wc.cbClsExtra = 0;

            wc.cbWndExtra = 0;

            wc.hInstance = hInstance;

            wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );

            wc.hCursor = LoadCursor( NULL, IDC_ARROW );

            wc.hbrBackground = GetStockObject(WHITE_BRUSH);

            wc.lpszMenuName = NULL;

            wc.lpszClassName = "EasyWin";

            //注冊(cè)窗口類

            RegisterClass( &wc );

             

            //創(chuàng)建主窗口

            hwnd = CreateWindow(

            "EasyWin", //窗口類名稱

            "一個(gè)基本的Win32程序", //窗口標(biāo)題

            WS_OVERLAPPEDWINDOW, //窗口風(fēng)格,定義為普通型

            100, //窗口位置的x坐標(biāo)

            100, //窗口位置的y坐標(biāo)

            400, //窗口的寬度

            300, //窗口的高度

            NULL, //父窗口句柄

            NULL, //菜單句柄

            hInstance, //應(yīng)用程序實(shí)例句柄

            NULL ); //窗口創(chuàng)建數(shù)據(jù)指針

            if( !hwnd ) return FALSE;

            //顯示并更新窗口

            ShowWindow( hwnd, nCmdShow );

            UpdateWindow( hwnd );

            return TRUE;

            }

            //******************************************************************

            //函數(shù):WinProc()

            //功能:處理主窗口消息

            //******************************************************************

            LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )

            {

            switch( message )

            {

            case WM_KEYDOWN://擊鍵消息

            switch( wParam )

            {

            case VK_ESCAPE:

            MessageBox(hWnd,"ESC鍵按下了!","Keyboard",MB_OK);

            break;

            }

            break;

            case WM_RBUTTONDOWN://鼠標(biāo)消息

            {

            MessageBox(hWnd,"鼠標(biāo)右鍵按下了!","Mouse",MB_OK);

            break;

            }

            case WM_PAINT://窗口重畫消息

            {

            char hello[]="你好,我是EasyWin !";

            HDC hdc;

            PAINTSTRUCT ps;

            hdc=BeginPaint( hWnd,&ps ); //取得設(shè)備環(huán)境句柄

            SetTextColor(hdc, RGB(0,0,255)); //設(shè)置文字顏色

            TextOut( hdc, 20, 10, hello, strlen(hello) );//輸出文字

            EndPaint( hWnd, &ps ); //釋放資源

            break;

            }

            case WM_DESTROY://退出消息

            PostQuitMessage( 0 );//調(diào)用退出函數(shù)

            break;

            }

            //調(diào)用缺省消息處理過程

            return DefWindowProc(hWnd, message, wParam, lParam);

            }

              程序輸入完畢,即可編譯執(zhí)行。在窗口中擊鼠標(biāo)鍵或按ESC鍵時(shí),會(huì)彈出一個(gè)對(duì)話框以表示你的操作。

              其實(shí),這個(gè)程序可以看成是所有Win32應(yīng)用程序的框架,在以后所有的程序中,你會(huì)發(fā)現(xiàn)它們都是在這個(gè)程序的基礎(chǔ)之上再添加代碼。


              WinMain()函數(shù)
             
              WinMain()函數(shù)是應(yīng)用程序開始執(zhí)行時(shí)的入口點(diǎn),通常也是應(yīng)用程序結(jié)束任務(wù)退出時(shí)的出口點(diǎn)。它與DOS程序的main()函數(shù)起同樣的作用,有一點(diǎn)不同的是,WinMain()函數(shù)必須帶有四個(gè)參數(shù),它們是系統(tǒng)傳遞給它的。WinMain()函數(shù)的原型如下:

            int PASCAL WinMain( HINSTANCE hInstance, //當(dāng)前實(shí)例句柄

            HINSTANCE hPrevInstance, //前一個(gè)實(shí)例句柄

            LPSTR lpCmdLine, //命令行字符

            int nCmdShow) //窗口顯示方式

              第一個(gè)參數(shù)hInstance,是標(biāo)識(shí)該應(yīng)用程序當(dāng)前的實(shí)例的句柄。它是HINSTANCE類型,HINSTANCE是Handle of Instance的縮寫,表示實(shí)例的句柄。hInstance是一個(gè)很關(guān)鍵的數(shù)據(jù),它唯一的代表該應(yīng)用程序,在后面初始化程序主窗口的過程中需要用到這個(gè)參數(shù)。

              這里有兩個(gè)概念,一個(gè)是實(shí)例,一個(gè)是句柄。實(shí)例代表的是應(yīng)用程序執(zhí)行的整個(gè)過程和方法,一個(gè)應(yīng)用程序如果沒有被執(zhí)行,只是存在于磁盤上,那么就說它是沒有被實(shí)例化的;只要一執(zhí)行,則說該程序的一個(gè)實(shí)例在運(yùn)行。句柄,顧名思義,指的是一個(gè)對(duì)象的把柄。在Windows中,有各種各樣的句柄,它們都是32位的指針變量,用來指向該對(duì)象所占據(jù)的內(nèi)存區(qū)。句柄的使用,可以極大的方便Windows管理其內(nèi)存中的各種對(duì)象。

              第二個(gè)參數(shù)是hPrevInstance,它是用來標(biāo)識(shí)該應(yīng)用程序的前一個(gè)實(shí)例句柄。對(duì)于基于Win32的應(yīng)用程序來說,這個(gè)參數(shù)總是NULL。這是因?yàn)樵赪in95操作系統(tǒng)中,應(yīng)用程序的每個(gè)實(shí)例都有各自獨(dú)立的地址空間,即使同一個(gè)應(yīng)用程序被執(zhí)行了兩次,在內(nèi)存中也會(huì)為它們的每一個(gè)實(shí)例分配新的內(nèi)存空間,所以一個(gè)應(yīng)用程序被執(zhí)行后,不會(huì)有前一個(gè)實(shí)例存在的可能。也就是說,hPrevInstance這個(gè)參數(shù)是完全沒有必要的,只是為了提供與16位Windows的應(yīng)用程序形式上的兼容性,才保留了這個(gè)參數(shù)。在以前的16位Windows環(huán)境下(如Windows3.2),hPrevInstance用來標(biāo)識(shí)與hInstance相關(guān)的應(yīng)用程序的前一個(gè)句柄。

              第三個(gè)參數(shù)是lpCmdLine,是指向應(yīng)用程序命令行參數(shù)字符串的指針。如在Win95的“開始”菜單中單擊“運(yùn)行”,輸入“easywin hello”,則此參數(shù)指向的字符串為“hello”。

              最后一個(gè)參數(shù)是nCmdShow,是一個(gè)用來指定窗口顯示方式的整數(shù)。這個(gè)整數(shù)值可以是SW_SHOW、SW_HIDE、SW_SHOWMAXIMIZED、SW_SHOWMINIMIZED等,關(guān)于這些值的含義,將在下一節(jié)說明。


              注冊(cè)窗口類

              一個(gè)應(yīng)用程序可以有許多窗口,但只有一個(gè)是主窗口,它是與該應(yīng)用程序的實(shí)例句柄唯一關(guān)聯(lián)的。上面的例程中,創(chuàng)建主窗口的函數(shù)是InitWindow()。

              通常要對(duì)填充一個(gè)窗口類結(jié)構(gòu)WNDCLASS,然后調(diào)用RegisterClass()對(duì)該窗口類進(jìn)行注冊(cè)。每個(gè)窗口都有一些基本的屬性,如窗口邊框、窗口標(biāo)題欄文字、窗口大小和位置、鼠標(biāo)、背景色、處理窗口消息函數(shù)的名稱等等。注冊(cè)的過程也就是將這些屬性告訴系統(tǒng),然后再調(diào)用CreateWindow()函數(shù)創(chuàng)建出窗口。這也就象你去裁縫店訂做一件衣服,先要告訴店老板你的身材尺寸、布料顏色、以及你想要的款式,然后他才能為你做出一件讓你滿意的衣服。

              在VC的幫助中,可以看到WNDCLASS結(jié)構(gòu)是這樣定義的:

            typedef struct _WNDCLASS {

            UINT style; //窗口的風(fēng)格*

            WNDPROC lpfnWndProc; //指定窗口的消息處理函數(shù)的遠(yuǎn)指針*

            int cbClsExtra; //指定分配給窗口類結(jié)構(gòu)之后的額外字節(jié)數(shù)*

            int cbWndExtra; //指定分配給窗口實(shí)例之后的額外字節(jié)數(shù)

            HANDLE hInstance; //指定窗口過程所對(duì)應(yīng)的實(shí)例句柄*

            HICON hIcon; //指定窗口的圖標(biāo)

            HCURSOR hCursor; //指定窗口的鼠標(biāo)

            HBRUSH hbrBackground; //指定窗口的背景畫刷

            LPCTSTR lpszMenuName; //窗口的菜單資源名稱

            LPCTSTR lpszClassName; //該窗口類的名稱*

            } WNDCLASS;

              在Win95和WinNT的具有新界面特性的系統(tǒng)中,為了支持新的窗口界面特性,還有一種擴(kuò)展的窗口類型WNDCLASSEX,它的定義如下:

            typedef struct _WNDCLASSEX {

            UINT cbSize; //指定WNDCLASSEX結(jié)構(gòu)的大小

            UINT style;

            WNDPROC lpfnWndProc;

            int cbClsExtra;

            int cbWndExtra;

            HANDLE hInstance;

            HICON hIcon;

            HCURSOR hCursor;

            HBRUSH hbrBackground;

            LPCTSTR lpszMenuName;

            LPCTSTR lpszClassName;

            HICON hIconSm; //窗口的小圖標(biāo)

            } WNDCLASSEX;

              WNDCLASS和WNDCLASSEX這兩個(gè)結(jié)構(gòu)基本上是一致的,只是WNDCLASSEX結(jié)構(gòu)中多了cbSize和hIconSm這兩個(gè)成員。WNDCLASS結(jié)構(gòu)的各成員中,其注釋后打了星號(hào)的表示該項(xiàng)應(yīng)特別注意。

              WNDCLASS結(jié)構(gòu)的第一個(gè)成員style表示窗口類的風(fēng)格,它往往是由一些基本的風(fēng)格通過位的“或”操作(操作符位“|”)組合而成。下表列出了一些常用的基本窗口風(fēng)格:

            風(fēng)格 含義
            CS_HREDRAW 如果窗口客戶區(qū)寬度發(fā)生改變,重繪整個(gè)窗口
            CS_VREDRAW 如果窗口客戶區(qū)高度發(fā)生改變,重繪整個(gè)窗口
            CS_DBLCLKS 能感受用戶在窗口中的雙擊消息
            CS_NOCLOSE 禁用系統(tǒng)菜單中的“關(guān)閉”命令
            CS_OWNDC 為該窗口類的各窗口分配各自獨(dú)立的設(shè)備環(huán)境
            CS_CLASSDC 為該窗口類的各窗口分配一個(gè)共享的設(shè)備環(huán)境
            CS_PARENTDC 指定子窗口繼承其父窗口的設(shè)備環(huán)境
            CS_SAVEBITS 把被窗口遮掩的屏幕圖象部分作為位圖保存起來。當(dāng)該窗口被移動(dòng)時(shí),Windows使用被保存的位圖來重建屏幕圖象

              在EasyWin應(yīng)用程序中,是按如下方式對(duì)WNDCLASS結(jié)構(gòu)進(jìn)行填充和注冊(cè)的:

            wc.style = CS_VREDRAW | CS_HREDRAW;

            wc.lpfnWndProc = (WNDPROC)WinProc;

            wc.cbClsExtra = 0;

            wc.cbWndExtra = 0;

            wc.hInstance = hInstance;

            wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );

            wc.hCursor = LoadCursor( NULL, IDC_ARROW );

            wc.hbrBackground = GetStockObject(WHITE_BRUSH);

            wc.lpszMenuName = NULL;

            wc.lpszClassName = "EasyWin";

              可以看到,wc.style被設(shè)為CS_VREDRAW | CS_HREDRAW,表示只要窗口的高度或?qū)挾劝l(fā)生變化,都會(huì)重畫整個(gè)窗口。

              第二個(gè)成員lpfnWndProc的值為(WNDPROC)WinProc。表明該窗口類的消息處理函數(shù)是WinProc()函數(shù)。這里,要指定窗口的消息處理函數(shù)的遠(yuǎn)指針,輸入消息處理函數(shù)的函數(shù)名稱即可,必要時(shí)應(yīng)該進(jìn)行強(qiáng)制類型轉(zhuǎn)換,將其轉(zhuǎn)換成WNDPROC型。

              接下來的cbClsExtra和wc.cbWndExtra在大多數(shù)情況下都會(huì)設(shè)為0。

              然后的hInstance成員,給它的值是由WinMain()傳來的應(yīng)用程序的實(shí)例句柄,表明該窗口與該實(shí)例是相關(guān)聯(lián)的。事實(shí)上,只要是注冊(cè)窗口類,該成員的值始終是該程序的實(shí)例句柄,你應(yīng)該象背書一樣記住它。

              下面的hIcon,是讓你給這個(gè)窗口指定一個(gè)圖標(biāo),調(diào)用 LoadIcon( hInstance, IDI_APPLICATION ),可以調(diào)用系統(tǒng)內(nèi)部預(yù)先定義好的標(biāo)志符為IDC_APPLICATION的圖標(biāo)作為該窗口的圖標(biāo)。

              同樣,調(diào)用LoadCursor( NULL, IDC_ARROW )為該窗口調(diào)用系統(tǒng)內(nèi)部預(yù)先定義好的箭頭型鼠標(biāo)。

              hbrBackground成員用來定義窗口的背景畫刷顏色,也就是該窗口的背景色。調(diào)用GetStockObject(WHITE_BRUSH)可以獲得系統(tǒng)內(nèi)部預(yù)先定義好的白色畫刷作為窗口的背景色。

              上面的LoadIcon()、LoadCursor()、GetStockObject()都是Windows的API函數(shù),它們的用法可以參看VC的幫助,這里就不多介紹了。

              lpszMenuName成員的值我們給它NULL,表示該窗口將沒有菜單。如果你想讓你的窗口擁有菜單,就把lpszMenuName成員賦值為標(biāo)志菜單資源的字符串。

              WNDCLASS結(jié)構(gòu)的最后一個(gè)成員lpszClassName是讓你給這個(gè)窗口類起一個(gè)唯一的名稱,因?yàn)閃indows操作系統(tǒng)中有許許多多的窗口類,必須用一個(gè)獨(dú)一無二的名稱來代表它們。通常,你可以用你的程序名來命名這個(gè)窗口類的名稱。這個(gè)名稱將在創(chuàng)建窗口的CreateWindow()函數(shù)中用到。

              填充完畢后,對(duì)于WNDCLASS結(jié)構(gòu),調(diào)用RegisterClass()函數(shù)進(jìn)行注冊(cè);對(duì)于WNDCLASSEX結(jié)構(gòu),調(diào)用RegisterClassEx()函數(shù)進(jìn)行注冊(cè),它們的原型分別如下:

            ATOM RegisterClass( CONST WNDCLASS *lpWndClass );

            ATOM RegisterClassEx( CONST WNDCLASSEX *lpwcx );

              該函數(shù)如調(diào)用成功,則返回一個(gè)非0值,表明系統(tǒng)中已經(jīng)注冊(cè)了一個(gè)名為EasyWin的窗口類。如果失敗,則返回0。


              創(chuàng)建窗口

              當(dāng)窗口類注冊(cè)完畢之后,并不會(huì)有窗口顯示出來,因?yàn)樽?cè)的過程僅僅是為創(chuàng)建窗口所做的準(zhǔn)備工作。實(shí)際創(chuàng)建一個(gè)窗口的是通過調(diào)用CreateWindow()函數(shù)完成的。窗口類中已經(jīng)預(yù)先定義了窗口的一般屬性,而CreateWindow()中的參數(shù)可以進(jìn)一步指定一個(gè)窗口的更具體的屬性,在EasyWin程序中,是如下調(diào)用CreateWindow()函數(shù)來創(chuàng)建窗口的:

            hwnd = CreateWindow(

            "EasyWin", //創(chuàng)建窗口所用的窗口類的名稱*

            "一個(gè)基本的Win32程序", //窗口標(biāo)題

            WS_OVERLAPPEDWINDOW, //窗口風(fēng)格,定義為普通型*

            100, //窗口位置的x坐標(biāo)

            100, //窗口位置的y坐標(biāo)

            400, //窗口的寬度

            300, //窗口的高度

            NULL, //父窗口句柄

            NULL, //菜單句柄

            hInstance, //應(yīng)用程序實(shí)例句柄*

            NULL ); //一般都為NULL

              CreateWindow()函數(shù)的參數(shù)的含義在上面的注釋中已有介紹,注釋后打了星號(hào)標(biāo)記的參數(shù)應(yīng)該著重注意,其它的參數(shù)都很簡單,不多做介紹,可參看VC的幫助。

              第一個(gè)參數(shù)是創(chuàng)建該窗口所使用的窗口類的名稱,注意這個(gè)名稱應(yīng)與前面所注冊(cè)的窗口類的名稱一致。

              第三個(gè)參數(shù)為創(chuàng)建的窗口的風(fēng)格,下表列出了常用的窗口風(fēng)格:

            風(fēng)格 含義
            WS_OVERLAPPEDWINDOW 創(chuàng)建一個(gè)層疊式窗口,有邊框、標(biāo)題欄、系統(tǒng)菜單、最大最小化按鈕,是以下幾種風(fēng)格的集合:WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX
            WS_POPUPWINDOW 創(chuàng)建一個(gè)彈出式窗口,是以下幾種風(fēng)格的集合: WS_BORDER,WS_POPUP,WS_SYSMENU。WS_CAPTION與WS_POPUPWINDOW風(fēng)格必須一起使用才能使窗口菜單可見
            WS_OVERLAPPED 創(chuàng)建一個(gè)層疊式窗口,它有標(biāo)題欄和邊框,與WS_TILED風(fēng)格一樣
            WS_POPUP 該窗口為彈出式窗口,不能與WS_CHILD同時(shí)使用
            WS_BORDER 窗口有單線邊框
            WS_CAPTION 窗口有標(biāo)題欄
            WS_CHILD 該窗口為子窗口,不能與WS_POPUP同時(shí)使用
            WS_DISABLED 該窗口為無效,即對(duì)用戶操作不產(chǎn)生任何反應(yīng)
            WS_HSCROLL 窗口有水平滾動(dòng)條
            WS_ICONIC 窗口初始化為最小化
            WS_MAXIMIZE 窗口初始化為最大化
            WS_MAXIMIZEBOX 窗口有最大化按鈕
            WS_MINIMIZE 與WS_MAXIMIZE一樣
            WS_MINIMIZEBOX 窗口有最小化按鈕
            WS_SIZEBOX 邊框可進(jìn)行大小控制的窗口
            WS_SYSMENU 創(chuàng)建一個(gè)有系統(tǒng)菜單的窗口,必須與WS_CAPTION風(fēng)格同時(shí)使用
            WS_THICKFRAME 創(chuàng)建一個(gè)大小可控制的窗口,與WS_SIZEBOX 風(fēng)格一樣.
            WS_TILED 創(chuàng)建一個(gè)層疊式窗口,有標(biāo)題欄
            WS_VISIBLE 窗口為可見
            WS_VSCROLL 窗口有垂直滾動(dòng)條

              程序中使用了WS_OVERLAPPEDWINDOW標(biāo)志,它是創(chuàng)建一個(gè)普通窗口常用的標(biāo)志。而在DirectX編程中,我們常用的是WS_POPUP,用這個(gè)標(biāo)志創(chuàng)建的窗口沒有標(biāo)題欄和系統(tǒng)菜單,如果設(shè)定窗口為最大化,客戶區(qū)可以占滿整個(gè)屏幕,以滿足DirectX編程的需要。

              CreateWindow()函數(shù)后面的參數(shù)中,仍用到了該應(yīng)用程序的實(shí)例句柄hInstance。

              如果窗口創(chuàng)建成功,返回值是新窗口的句柄,否則返回NULL。


              顯示和更新窗口

              窗口創(chuàng)建后,并不會(huì)在屏幕上顯示出來,要真正把窗口顯示在屏幕上,還得使用ShowWindow()函數(shù),其原型如下:

            BOOL ShowWindow( HWND hWnd, int nCmdShow );

              參數(shù)hWnd指定要顯示得窗口的句柄,nCmdShow表示窗口的顯示方式,這里指定為從WinMain()函數(shù)的nCmdShow所傳遞而來的值。

              由于ShowWindow()函數(shù)的執(zhí)行優(yōu)先級(jí)不高,所以當(dāng)系統(tǒng)正忙著執(zhí)行其它的任務(wù)時(shí),窗口不會(huì)立即顯示出來,此時(shí),調(diào)用UpdateWindow()函數(shù)以可以立即顯示窗口。其函數(shù)原型如下:

            BOOL UpdateWindow( HWND hWnd );

              消息循環(huán)

              在Win32編程中,消息循環(huán)是相當(dāng)重要的一個(gè)概念,看似很難,但是使用起來卻是非常簡單。在WinMain()函數(shù)中,調(diào)用InitWindow()函數(shù)成功的創(chuàng)建了應(yīng)用程序主窗口之后,就要啟動(dòng)消息循環(huán),其代碼如下:

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

            {

            TranslateMessage(&msg);

            DispatchMessage(&msg);

            }

              Windows應(yīng)用程序可以接收以各種形式輸入的信息,這包括鍵盤、鼠標(biāo)動(dòng)作 、記時(shí)器產(chǎn)生的消息,也可以是其它應(yīng)用程序發(fā)來的消息等等。Windows系統(tǒng)自動(dòng)監(jiān)控所有的輸入設(shè)備,并將其消息放入該應(yīng)用程序的消息隊(duì)列中。

              GetMessage()函數(shù)則是用來從應(yīng)用程序的消息隊(duì)列中按照先進(jìn)先出的原則將這些消息一個(gè)個(gè)的取出來,放進(jìn)一個(gè)MSG結(jié)構(gòu)中去。GetMessage()函數(shù)原型如下:

            BOOL GetMessage(

            LPMSG lpMsg, //指向一個(gè)MSG結(jié)構(gòu)的指針,用來保存消息

            HWND hWnd, //指定哪個(gè)窗口的消息將被獲取

            UINT wMsgFilterMin, //指定獲取的主消息值的最小值

            UINT wMsgFilterMax //指定獲取的主消息值的最大值

            );

              GetMessage()將獲取的消息復(fù)制到一個(gè)MSG結(jié)構(gòu)中。如果隊(duì)列中沒有任何消息,GetMessage()函數(shù)將一直空閑直到隊(duì)列中又有消息時(shí)再返回。如果隊(duì)列中已有消息,它將取出一個(gè)后返回。MSG結(jié)構(gòu)包含了一條Windows消息的完整信息,其定義如下:

            typedef struct tagMSG {

            HWND hwnd; //接收消息的窗口句柄

            UINT message; //主消息值

            WPARAM wParam; //副消息值,其具體含義依賴于主消息值

            LPARAM lParam; //副消息值,其具體含義依賴于主消息值

            DWORD time; //消息被投遞的時(shí)間

            POINT pt; //鼠標(biāo)的位置

            } MSG;

              該結(jié)構(gòu)中的主消息表明了消息的類型,例如是鍵盤消息還是鼠標(biāo)消息等,副消息的含義則依賴于主消息值,例如:如果主消息是鍵盤消息,那么副消息中則存儲(chǔ)了是鍵盤的哪個(gè)具體鍵的信息。

              GetMessage()函數(shù)還可以過濾消息,它的第二個(gè)參數(shù)是用來指定從哪個(gè)窗口的消息隊(duì)列中獲取消息,其它窗口的消息將被過濾掉。如果該參數(shù)為NULL,則GetMessage()從該應(yīng)用程序線程的所有窗口的消息隊(duì)列中獲取消息。

              第三個(gè)和第四個(gè)參數(shù)是用來過濾MSG結(jié)構(gòu)中主消息值的,主消息值在wMsgFilterMin和wMsgFilterMax之外的消息將被過濾掉。如果這兩個(gè)參數(shù)為0,則表示接收所有消息。

              當(dāng)且僅當(dāng)GetMessage()函數(shù)在獲取到WM_QUIT消息后,將返回0值,于是程序退出消息循環(huán)。

              TranslateMessage()函數(shù)的作用是把虛擬鍵消息轉(zhuǎn)換到字符消息,以滿足鍵盤輸入的需要。DispatchMessage()函數(shù)所完成的工作是把當(dāng)前的消息發(fā)送到對(duì)應(yīng)的窗口過程中去。

              開啟消息循環(huán)其實(shí)是很簡單的一個(gè)步驟,幾乎所有的程序都是按照EasyWin的這個(gè)方法。你完全不必去深究這些函數(shù)的作用,只是簡單的照抄就可以了。
             

              消息處理函數(shù)

              消息處理函數(shù)又叫窗口過程,在這個(gè)函數(shù)中,不同的消息將用switch語句分配到不同的處理程序中去。Windows的消息處理函數(shù)都有一個(gè)確定的樣式,即這種函數(shù)的參數(shù)個(gè)數(shù)和類型以及其返回值的類型都有明確的規(guī)定。在VC的說明書中,消息處理函數(shù)的原型是這樣定義的:

            LRESULT CALLBACK WindowProc(

            HWND hwnd, //接收消息窗口的句柄

            UINT uMsg, //主消息值

            WPARAM wParam, //副消息值

            LPARAM lParam //副消息值

            );

              如果你的程序中還有其它的消息處理函數(shù),也都必須按照上面的這個(gè)樣式來定義,但函數(shù)名稱可以隨便取。EasyWin中的WinProc()函數(shù)就是這樣一個(gè)典型的消息處理函數(shù)。

              消息處理函數(shù)的四個(gè)參數(shù)是由GetMessage()函數(shù)從消息隊(duì)列中獲得MSG結(jié)構(gòu),然后分解后得到的。第二個(gè)參數(shù)uMsg和MSG結(jié)構(gòu)中的message值是一致的,代表了主消息值。程序中用switch語句來將不同類型的消息分配到不同的處理程序中去。

              WinProc()函數(shù)明確的處理了4個(gè)消息,分別是WM_KEYDOWN(擊鍵消息)、WM_RBUTTONDOWN(鼠標(biāo)右鍵按下消息)、WM_PAINT(窗口重畫消息)、WM_DESTROY(銷毀窗口消息)。

              值得注意的是,應(yīng)用程序發(fā)送到窗口的消息遠(yuǎn)遠(yuǎn)不止以上這幾條,象WM_SIZE、WM_MINIMIZE、WM_CREATE、WM_MOVE等這樣頻頻使用的消息就有幾十條。為了減輕編程的負(fù)擔(dān),Windows的API提供了DefWindowProc()函數(shù)來處理這些最常用的消息,調(diào)用了這個(gè)函數(shù)后,這些消息將按照系統(tǒng)默認(rèn)的方式得到處理。

              因此,在switch_case語句中,只須明確的處理那些有必要進(jìn)行特別響應(yīng)的消息,把其余的消息交給DefWindowProc()函數(shù)來處理,是一種明智的選擇,也是你必須做的一件事。
             
              結(jié)束消息循環(huán)

              當(dāng)用戶按Alt+F4或單擊窗口右上角的退出按鈕,系統(tǒng)就向應(yīng)用程序發(fā)送一條WM_DESTROY的消息。在處理此消息時(shí),調(diào)用了PostQuitMessage()函數(shù),該函數(shù)會(huì)給窗口的消息隊(duì)列中發(fā)送一條WM_QUIT的消息。在消息循環(huán)中,GetMessage()函數(shù)一旦檢索到這條消息,就會(huì)返回FALSE,從而結(jié)束消息循環(huán),隨后,程序也結(jié)束。

              小結(jié)

              本章介紹的是Win32編程的基礎(chǔ)知識(shí),在進(jìn)行DirectX編程之前,掌握它們是十分必要的。

              通過本文的學(xué)習(xí),你應(yīng)該學(xué)到以下知識(shí):

               如何創(chuàng)建一個(gè)Win32應(yīng)用程序工程

               用RegisterClass()函數(shù)注冊(cè)一個(gè)窗口類,再立即調(diào)用CreateWindow()函數(shù)創(chuàng)建一個(gè)窗口的實(shí)例

               設(shè)置窗口的類型以及將一個(gè)消息處理函數(shù)與窗口聯(lián)系上

               用一固定的模式開啟消息循環(huán)

               了解消息處理函數(shù)的定義規(guī)則,如何自己定義一個(gè)窗口消息處理函數(shù)

               在消息處理函數(shù)中,最后必須調(diào)用DefWindowProc()函數(shù)以處理那些缺省的消息

               調(diào)用PostQuitMessage()函數(shù)以結(jié)束消息循環(huán)

            Posted on 2005-11-11 13:44 艾凡赫 閱讀(329) 評(píng)論(0)  編輯 收藏 引用 所屬分類: MFC技術(shù)
            亚洲午夜久久久久妓女影院 | 91精品国产乱码久久久久久 | 久久人人爽爽爽人久久久| 99久久精品国产麻豆| 国内精品久久久久久中文字幕 | 久久综合鬼色88久久精品综合自在自线噜噜| 久久天天躁狠狠躁夜夜96流白浆| 精品蜜臀久久久久99网站| 狠狠狠色丁香婷婷综合久久五月| 久久久久噜噜噜亚洲熟女综合 | 久久久精品2019免费观看| 久久久久精品国产亚洲AV无码| 久久免费视频网站| 伊人久久精品无码av一区| 国内精品久久久久国产盗摄| 色婷婷综合久久久中文字幕| 久久精品成人国产午夜| 一本综合久久国产二区| 国产精品免费久久久久电影网| 99精品国产在热久久 | 精品国产乱码久久久久久人妻 | 色成年激情久久综合| 青青草国产精品久久久久| 久久人人添人人爽添人人片牛牛| 久久综合日本熟妇| 国产99久久久国产精免费| 97精品国产97久久久久久免费| 国产成人久久精品一区二区三区 | 国产精品久久午夜夜伦鲁鲁| 久久精品国产福利国产秒| 色综合久久综合中文综合网| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 久久精品国产亚洲av麻豆小说| 久久青青草原国产精品免费 | 国产成人综合久久精品尤物| 久久久久久噜噜精品免费直播 | 久久亚洲视频| 色欲综合久久躁天天躁蜜桃| 久久亚洲sm情趣捆绑调教| 久久91精品综合国产首页| 久久99精品久久久久久齐齐|