Windows SDK程式設計之一 視窗示例程式
/*****************************************************
Windows SDK程式設計之一 視窗示例程式
******************************************************/
/*Win32應用程式框架主要由"初始化視窗類","視窗註冊類","視窗的建立"以"視窗訊息函式"等組成*/
#include "stdafx.h"
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //視窗函式說明
/*
WinMain函式是所有windows應用程式的入口,類似於C語言中的Main函式,其功能是完成一系列的定義和初始化工作,併產生訊息迴圈。訊息迴圈是整個程式執行的核心。WinMain函式實現以下功能。
1. 註冊視窗類,建立視窗及執行其它必要的初始化工作;
2. 進入訊息迴圈,根據從應用程式訊息佇列接受的訊息,呼叫相應的處理過程
3. 當訊息迴圈檢索到WM_QUIT訊息時終止程式執行。
WinMain函式有三個基本的組成部份:函式說明、初始化和訊息迴圈。
WinMain函式的說明如下:
int WINAPI WinMain( //WinMain函式說明
HINSTANCE hInstance, //程式當前例項控制代碼
HINSTANCE hPrevInstance, //應用程式其它例項控制代碼
LPSTR lpCmdLine, //指向程式命令列引數的指標
int nCmdShow //應用程式開始執行時視窗顯示方式的整數值標識
)
由於Window作業系統是多工的作業系統,能進行多工的管理,因此,windows應用程式可能被並行的多次執行,因而可能出現同一個程式的多個視窗同時存在的情況,Windows系統將應用程式每一次執行稱為該應用程式的一個例項(Instance),並用一個例項控制代碼唯一的標識它。
*/
int APIENTRY WinMain(HINSTANCE hInstance, //WinMain函式說明
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
/*
建議採用Pascal的變數定義風格,即在程式(函式)開始處定義所有變數
雖然C++的變數定義比較靈活,本程式為了使程式易於理解,未採用這種方法
*/
char lpszClassName[]="視窗"; //視窗類名
char lpszTitle[]="Windows SDK程式設計之一 視窗示例程式"; //視窗標題名
//---------------視窗類定義-------------------------------------
/*
視窗類的定義
在Windows應用程式中,視窗害定義了視窗的形式與功能。視窗類定義通過給視窗類資料結構WNDCLASS賦值完成,該資料結構中包括視窗類的各種屬性,在視窗類定義過程中常用到以下函式:
*/
WNDCLASS wndclass;
wndclass.style=0; //視窗型別為預設型別
wndclass.lpfnWndProc=WndProc; //視窗處理函式為WndProc
wndclass.cbClsExtra=0; //視窗類無擴充套件
wndclass.cbWndExtra=0; //視窗例項無擴充套件
wndclass.hInstance=hInstance; //當前例項控制代碼
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); //使用預設圖示
/*
LoadIcon():在應用程式中載入一個視窗圖示
LoadIcon()函式原型為:
HICON LoadIcon(
HINSTANCE hInstance,//圖示資源所在的模組控制代碼,為NULL則使用系統預定義圖示
LPCTSTR lpIconName //圖示資源名或系統預定義圖示標識名
)
*/
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); //視窗採用箭頭游標
/*
LoadCursor():在應用程式中載入一個視窗游標
LoadCursor()函式原型為:
HCURSOR LoadCursor(
HINSTANCE hInstance,//游標資源所在的模組控制代碼,為NULL則使用系統預定義游標
LPCTSTR lpCursorName //游標資源名或系統預定義游標標識名
)
*/
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //視窗背景為白色
/*
GetStockObject():獲取已經定義的畫筆、畫刷、字型等物件的控制代碼
GetStockObject()函式原型為:
HGDIOBJ GetStockObject(int fnObject); //fnObject為物件的標識名
*/
wndclass.lpszMenuName=NULL; //視窗中無選單
wndclass.lpszClassName=lpszClassName; //視窗類名為'視窗例項'
//------------------以下是進行視窗類的註冊---------------------------
/*
註冊視窗類
Windows系統本身提供部份預定義的視窗類,程式設計師也可以自定義視窗類,視窗類必須先註冊後使用。視窗類的註冊由註冊函式RegisterClass()實現。其形式為:
RegisterClass(&wndclass)
&wndclass為視窗類結構
RegisterClass函式的返回值為布林值,註冊成功則返回真
*/
if (! RegisterClass(&wndclass)) //註冊視窗,若失敗,則發出聲音
{ MessageBeep(0);
return FALSE;
}
/*
建立視窗例項
建立一個視窗類的例項由函式CreateWindow()實現,該函式的原型為:
HWND CreateWindow(LPCTSTR lpszClassName, //建立視窗,視窗類名
LPCTSTR lpszTitle, //視窗例項的標題名
DWORD dwStyle, //視窗的風格
int x, //視窗左上角座標
int y, //視窗左上角座標
int nWidth, //視窗的寬度
int nHeight, //視窗的高度
HWND hwndParent, //此視窗父視窗
HWENU hMenu, //此視窗主選單
HINSTANCE hInstance, //應用程式當前控制代碼
LPVOID lpParam); //指向一個傳遞給視窗的引數值的指標
*/
//建立視窗操作
HWND hwnd; //視窗結構
hwnd=CreateWindow(lpszClassName, //建立視窗,視窗類名
lpszTitle, //視窗例項的標題名
WS_OVERLAPPEDWINDOW, //視窗的風格
CW_USEDEFAULT,CW_USEDEFAULT, //視窗左上角座標為預設值
CW_USEDEFAULT,CW_USEDEFAULT, //視窗的高度和寬度為預設值
NULL, //此視窗無父視窗
NULL, //此視窗無主選單
hInstance, //應用程式當前控制代碼
NULL); //不使用該值
ShowWindow(hwnd,nCmdShow); //顯示視窗
UpdateWindow(hwnd); //繪製使用者區
/*
訊息迴圈
windows應用程式的執行以訊息為核心。windows將產生的訊息放入應用程式的訊息佇列中而應用程式WinMain函式的訊息迴圈提取訊息佇列中的訊息,並將其傳遞給視窗函式為相應處理過程處理。
MSG msg; //訊息結構
while( GetMessage(&msg,NULL,0,0)) //訊息迴圈
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
*/
MSG msg; //訊息結構
/*GetMessage()作用:從訊息佇列中讀取一條訊息,並將訊息放在一個MSG結構中:
BOOL GetMessage(
LPMSG lpMsg, //指向MSG結構的指標
HWND hWnd,
UINT wMsgFilterMin, //用於訊息過濾的最小資訊號值
UINT wMsgFilterMax //用於訊息過濾的最大資訊號值 如最小值和最大值均為0, 則不過濾訊息
);
當GetMessage返回0時,即檢索到WM_QUIT訊息,程式將結束迴圈並退出
BOOL TranslateMessage( const MSG *lpMsg ); 負責把訊息的虛擬鍵值轉換為字元資訊
LRESULT DispatchMessage( const MSG *lpmsg ); 將引數lpmsg指向的訊息傳遞給指定的視窗
*/
while( GetMessage(&msg,NULL,0,0)) //訊息迴圈
{ TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam; //程式終止時,將資訊返回作業系統
}
//-----------------------------視窗函式---------------------------------------
/*
視窗訊息處理函式定義了應用程式對接收到的不同訊息的響應,它包含了應用程式對各種可用接收到的訊息的處理過程,通常 ,視窗函式由一個或多個switch...case語句組成,每一條case語句
對應一種訊息,當應用程式接收到一個訊息時,相應的case語句被 啟用並執行相應的響應程式模組。
視窗函式的一般形式如下:
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
Parameters
hwnd :[in] Handle to the window.
uMsg :[in] Specifies the message.
wParam:[in] Specifies additional message information. The contents of this parameter depend on the value of the uMsg parameter.
lParam:[in] Specifies additional message information. The contents of this parameter depend on the value of the uMsg parameter.
Return Value
The return value is the result of the message processing and depends on the message sent.
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case ...
....
break;
.........
case WM_DESTROY:
//void PostQuitMessage(int nExitCode)函式的作用是向程式傳送WM_QUIT訊息,nExitCode應用程式退出程式碼
PostQuitMessage(0); //呼叫該函式發出WM_QUIT訊息
default: //預設訊息處理函式,以保證所的發往視窗的訊息都能被處理
return DefWindowProc(hwnd,message,wParam,lParam);
}
return (0);
}
*/
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0); //呼叫該函式發出WM_QUIT訊息
default: //預設訊息處理函式
return DefWindowProc(hwnd,message,wParam,lParam);
}
return (0);
}
/*
注:
事件驅動的特點:
Windows程式設計圍繞著事件或訊息的產生驅動產生執行訊息處理函式。Windows程式的執行順序取決於事件發生的順序,程式的執行是由順序產生的訊息驅動的,程式設計師可以針對訊息型別編寫訊息處理程式以處理接收的訊息,或者發出其他訊息以驅動其他處理程式,但是不必預先確定訊息的產生順序。這是面向物件程式設計中事件驅動的顯著特點。
事件驅動程式設計方法對於編寫互動程式很有用處,用這一方法編寫的程式使程式避免了死板的操作模式,從而使使用者能夠按照自己的意願採用靈活多變的操作模式。
Windows應用程式中的訊息傳遞機制:
VC中存在幾種系統定義的訊息分類,常用的訊息由視窗訊息、初始化訊息、輸入訊息、系統訊息、剪下板訊息、文當介面訊息、DDE(動態資料交換)訊息、應用程式自定義訊息等。應用程式傳送的訊息傳送至訊息佇列,系統根據訊息到達的順序對訊息進行處理,並呼叫響應的訊息處理模組程式碼。
*/