Windows編程入門程序詳解


Windows編程入門程序詳解

1.     程序

/************************************************************************
 * 名  稱:Windows_Frist_Code.cpp
 * 功  能:Windows編程入門
 * 描  述:包含WinMain函數、WNDCLASS、消息循環等多種內容
           windows窗口程序的流程如下:【WinMain入口】-->創建和設計窗口類
	    -->注冊窗口類-->創建、顯示和更新窗口-->消息循環-->【窗口過程函數】
 * 作  者:JarvisChu
 * 時  間:2012-10-24
 * 修  訂:1. 2012-10-26,Jarvis. 完善代碼和注釋。
 ************************************************************************/
#include <windows.h>
#include <stdio.h>
#include "resource.h"

//回調函數
LRESULT CALLBACK WinProc(
							HWND hwnd, 
							UINT uMsg, 
							WPARAM wParam, 
							LPARAM lParam 
);

//入口函數 WinMain
int WINAPI WinMain(HINSTANCE hInstance,    //當前應用程序的句柄
				   HINSTANCE hPrevInstance,//先前應用程序的句柄,總是NULL
				   LPSTR lpCmdLine,        //不包含程序名的命令行,可通過GetCommandLine獲取
				   int nShowCmd            //窗口顯示方式
				)
{
//-------------------創建和設計窗口類----------------------------------------------------
	WNDCLASS wndclass;    
	wndclass.cbClsExtra =0;
	wndclass.cbWndExtra =0;
	wndclass.hbrBackground =(HBRUSH)GetStockObject(GRAY_BRUSH);
	wndclass.hCursor =LoadCursor(hInstance,MAKEINTRESOURCE(ID_MYCURSOR));   //LoadCursor(NULL,IDC_HELP);//
	wndclass.hIcon =LoadIcon(hInstance,MAKEINTRESOURCE(ID_MYICON));         //LoadIcon(NULL,IDI_APPLICATION);//
	wndclass.hInstance =hInstance;
	wndclass.lpfnWndProc =WinProc;
	wndclass.lpszClassName ="Jarvis";
	wndclass.lpszMenuName =NULL;
    wndclass.style =CS_HREDRAW | CS_VREDRAW;

//-------------------注冊窗口類----------------------------------------------------
    RegisterClass(&wndclass);
	
//-------------------創建顯示更新窗口----------------------------------------------------
	HWND hwnd;
	hwnd=CreateWindow("Jarvis","Jarvis",WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_MAXIMIZE,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
	
	ShowWindow(hwnd,SW_SHOWNORMAL);
	UpdateWindow(hwnd);

//-------------------消息循環----------------------------------------------------
	MSG msg;
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}


//窗口過程函數實現
LRESULT CALLBACK WinProc(
							HWND hwnd, 
							UINT uMsg, 
							WPARAM wParam, 
							LPARAM lParam 
							)
{
	switch(uMsg)
	{

	case WM_LBUTTONDOWN:
		MessageBox(hwnd,"LeftButton Clicked!","Prompt",0);
		break;
	case WM_CLOSE:
		if(IDYES==MessageBox(hwnd,"Are you sure to quit?","Prompt",MB_YESNO))
		{
			DestroyWindow(hwnd);
		}
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd,uMsg,wParam,lParam);
		
	}
	return 0;
}

2.  WinMain函數解析

2.1.   WinMain函數原型

int WINAPI WinMain ( HINSTANCE hInstance,    //當前應用程序的句柄
                     HINSTANCE hPrevInstance,//先先前應用程序的句柄,總是NULL
                     LPSTR lpCmdLine,        //不含程序名的命令行,通過GetCommandLine獲取
		     int nShowCmd            //窗口顯示方式
		   );

2.2.   WinMain函數功能

WinMain是一個函數,該函數的功能是被系統調用,作為一個32位應用程序的入口點WinMain函數應初始化應用程序,顯示主窗口,進入一個消息接收-發送循環,這個循環是應用程序執行的其余部分的頂級控制結構。

2.3.   窗口顯示方式

WinMain函數的nShowCmd參數指示了窗口的顯示方式。顯示方式可以是下表中的任何一種。

 

表格 1 窗口顯示方式

SW_HIDE

隱藏窗口並且激活另外一個窗口

SW_RESTORE

激活並顯示窗口。如果窗口已經最小化或最大化,系統將以恢復到原來的尺寸和位置顯示窗口(與SW_SHOWNORMAL相同)

SW_SHOW

激活一個窗口並以原來的尺寸和位置顯示窗口

SW_SHOWMAXIMIZED

激活窗口並且將其最大化

SW_SHOWMINIMIZED

激活窗口並將其最小化(以圖標顯示)

SW_SHOWMINNOACTIVE

將一個窗口顯示為圖標。激活窗口維持活動狀態

SW_SHOWNA

以窗口的當前狀態顯示窗口。激活窗口保持活動狀態

SW_SHOWNOACTIVATE:

以窗口的最近一次的尺寸和位置顯示窗口。激活窗口維持激活狀態

SW_SHOWNORMAL

激活並顯示窗口。如果窗口最大化或最小化,系統將其恢復到原來的尺寸和位置(與SW_RESTORE相同)

SW_MINIMIZE

最小化指定的窗口,並且激活在系統表中的頂層窗口

 

3.     創建和設計窗口類

3.1.   WNDCLASS結構體定義

 

typedef struct {
			UINT style;              //窗口類型CS_HREDRAW|CS_VREDRAW
			WNDPROC lpfnWndProc;     //窗口回調函數
			int cbClsExtra;          //指定緊隨在 WNDCLASS 后分配的字節數,初始化為零
			int cbWndExtra;          //指定緊隨在窗口實例之后分配的字節數,初始化為零。
			HINSTANCE hInstance;     //指示該窗口類的回調函數所在實例的句柄,不為NULL
			HICON hIcon;             //窗口圖標句柄,若為NULL,系統提供默認
			HCURSOR hCursor;         //光標資源句柄
			HBRUSH hbrBackground;    //背景畫刷句柄
			LPCTSTR lpszMenuName;    //菜單資源名
			LPCTSTR lpszClassName;   //窗口對應的窗口類名
		   } WNDCLASS, *PWNDCLASS; //

3.2.   窗口類型

多種窗口類型可以使用 | 號疊加


表格 2 窗口類型

標識

描述

CS_BYTEALIGNCLIENT

在字節邊界上(在x方向上)定位窗口的用戶區域的位置

CS_BYTEALIGNWINDOW

在字節邊界上(在x方向上)定位窗口的位置

CS_CLASSDC:

窗口類的所有窗口實例都共享一個窗口類DC

CS_DBLCLKS

允許向窗口發送雙擊鼠標鍵的消息

CS_GLOBALCLASS

當調用CreateWindow 或 CreateWindowEx 函數來創建窗口時允許它的hInstance參數和注冊窗口類時傳遞給RegisterClass 的 hInstance參數不同。如果不指定該風格,則這兩個 hInstance 必須相同。

CS_HREDRAW

當水平長度改變或移動窗口時,重畫整個窗口

CS_NOCLOSE

禁止系統菜單的關閉選項

CS_OWNDC

給予每個窗口實例它本身的DC。注意,盡管這樣是很方便,但它必須慎重使用,因為每個DC大約要占800個字節的內存。

CS_PARENTDC

將子窗口的裁剪區域設置到父窗口的DC中去,這樣子窗口便可以在父窗口上繪制自身。注意,這是子窗口還是從系統緩存中獲取DC,而不是使用父窗口的DC。使用該風格可以提高系統性能。

CS_SAVEBITS

以位圖形式保存被該窗口遮擋的屏幕部分,這樣當給窗口移動以后,系統便可以用該保存的位圖恢復屏幕移動的相應部分,從而系統不用向被該窗口遮擋的窗口發送 WM_PAINT 消息。該特性對於菜單類型的窗口比較合適,因為它通常是簡短的顯示一下之后便消失。設置該特性將增加顯示該窗口的時間,因為它通常要先分配保存位圖的內存。

CS_VREDRAW

當垂直長度改變或移動窗口時,重畫整個窗口


3.3.   窗口圖標

3.3.1. LoadIcon函數

HICON  LoadIcon(  HINSTANCE Instance,   //應用程序的實例句柄
                    LPCTSTR lpIconName   //圖標資源的字符串型ID
) ;

3.3.2. 加載系統預定義圖標

LoadIcon(NULL, IDI_APPLICATION);

表格 3 系統圖標資源

IDI_APPLICATION

Default application icon.

IDI_ASTERISK

Same as IDI_INFORMATION.

IDI_ERROR

Hand-shaped icon.

IDI_EXCLAMATION

Same as IDI_WARNING.

IDI_HAND

Same as IDI_ERROR.

IDI_INFORMATION

Asterisk icon.

IDI_QUESTION

Question mark icon.

IDI_WARNING

Exclamation point icon.

IDI_WINLOGO

Windows logo icon. Windows XP: Default application icon.

IDI_SHIELD

Security Shield icon.


3.3.3. 加載自定義圖標

[1] 添加圖標資源

      File-->New-->Files-->Icon File (Name it “My_Icon.ico” on the right)-->Draw the Icon

[2] 添加資源文件

     File-->New-->Files-->Resource Script (Name it “My_Resource”)

     打開resource.h 文件,添加語句“#define ID_MYICON 1024”(1024 可以隨意)

     用記事本打開My_Resource.rc文件,添加語句“ID_MYICON ICON My_Icon.ico”

[3] 添加“resource.h”頭文件的引用

      在主程序的.cpp文件中,引用頭文件“#include “resource.h””

[4] 使用自定義圖標

LoadIcon(hInstance,MAKEINTRESOURCE(ID_MYICON));

3.4.   光標資源

光標資源的加載類似於圖標資源

3.4.1. LoadCursor函數

HCURSOR  LoadCursor (  HINSTANCE Instance,   //應用程序的實例句柄
                    LPCTSTR lpCursorName      //光標資源的字符串型ID
) ;  

3.4.2. 加載系統預定義光標

LoadCursor(NULL,IDC_CROSS);

IDC_APPSTARTING

Standard arrow and small hourglass

IDC_ARROW

Standard arrow

IDC_CROSS

Crosshair

IDC_HAND

Windows 98/Me, Windows 2000/XP: Hand

IDC_HELP

Arrow and question mark

IDC_IBEAM

I-beam

IDC_ICON

Obsolete for applications marked version 4.0 or later.

IDC_NO

Slashed circle

IDC_SIZE

Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.

IDC_SIZEALL

Four-pointed arrow pointing north, south, east, and west

IDC_SIZENESW

Double-pointed arrow pointing northeast and southwest

IDC_SIZENS

Double-pointed arrow pointing north and south

IDC_SIZENWSE

Double-pointed arrow pointing northwest and southeast

IDC_SIZEWE

Double-pointed arrow pointing west and east

IDC_UPARROW

Vertical arrow

IDC_WAIT

Hourglass

 

3.4.3. 加載自定義光標

 具體步驟與圖標相同(3.3.3

[1]  resource.h


[2] My_Resource.rc


[3] main.cpp


3.5.   背景畫刷

背景畫刷就是用來設置窗口的背景。

hbrBackground是畫刷的句柄,它必須是用於繪制背景的物理刷子的句柄,或者是一個顏色的值。

如果給出一個顏色的值,它必須是下面列出的標准系統顏色之一(系統將對所選顏色加1)。


3.5.1. 使用標准系統顏色

hbrBackground=(HBRUSH)(COLOR_ACTIVEBORDER+1);
                                                                                                                    表格 4 標准系統顏色

名稱

樣式

名稱

樣式

COLOR_ACTIVEBORDER

COLOR_ACTIVECAPTION

COLOR_CAPTIONTEXT

COLOR_WINDOWTEXT

COLOR_BTNTEXT

COLOR_MENUTEXT

COLOR_APPWORKSPACE

COLOR_HIGHLIGHTTEXT

COLOR_BACKGROUND

COLOR_GRAYTEXT

COLOR_HIGHLIGHT

COLOR_INACTIVEBORDER

COLOR_INACTIVECAPTION

COLOR_BTNFACE

COLOR_SCROLLBAR

COLOR_WINDOWFRAME

COLOR_MENU

COLOR_BTNSHADOW

COLOR_WINDOW

 

 


3.5.2. 使用系統預定義的畫刷

hbrBackground =(HBRUSH)GetStockObject(BLACK_BRUSH);

BRUSH

名稱

BLACK_BRUSH                                      

黑色畫刷

DKGRAY_BRUSH

暗灰色畫刷

DC_BRUSH

(Win7中錯誤)

GRAY_BRUSH 

灰色畫刷

HOLLOW_BRUSH 

空心刷(相當於NULL_BRUSH)

LTGRAY_BRUSH         

淺灰色畫刷

NULL_BRUSH           

空心刷(即背景透明)

WHITE_BRUSH             

白色畫刷

3.5.3. GetStockObject()函數

HGDIOBJ GetStockObject(int fnObject);

該函數檢索預定義的備用筆、刷子、字體或者調色板的句柄。

fnObject可以是: BLACK_BRUSH,WHITE_PEN,SYSTEM_FONT, DEFAULT_PALETTE

4.     注冊窗口類

ATOM RegisterClass(CONST WNDCLASS *lpWndClass);

窗口只有在其對應的窗口類注冊之后,才能使用CreateWindow或CreateWindowEx創建。

5.     創建窗口

HWND hwnd;
hwnd = CreateWindow("Jarvis","Jarvis",WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

HWND CreateWindow(           
	 LPCTSTR            lpClassName,   // 對應的窗口類的名稱
    		LPCTSTR             lpWindowName, //窗口名稱
    		DWORD              dwStyle,       / /窗口類型/
   		 int                   x,            //初始水平位置
    		int                   y,             //初始垂直位置 
  		int                   nWidth,        //窗口寬度
   		 int                   nHeight,       //窗口高度
   		 HWND               hWndParent,   //父窗口句柄
    		HMENU              hMenu,        //菜單資源句柄
    		HINSTANCE          hInstance,      //實例句柄
   		 LPVOID              lpParam       //傳給WM_CREATE的值
); 

 Window_Style(可以組合)

表格 5 Window_Style

Style

說明

WS_BORDER

創建一個單邊框的窗口。

WS_CAPTION

創建一個有標題框的窗口(包括WS_BODER風格)。

WS_CHILD

創建一個子窗口。這個風格不能與WS_POPUP風格合用。

WS_CHLDWINDOW

與WS_CHILD相同。

WS_CLIPCHILDREN

當在父窗口內繪圖時,排除子窗口區域。在創建父窗口時使用這個風格。

WS_CLIPSIBLINGS

排除子窗口之間的相對區域,也就是,當一個特定的窗口接收到WM_PAINT消息時,WS_CLIPSIBLINGS 風格將所有層疊窗口排除在繪圖之外,只重繪指定的子窗口。如果未指定WS_CLIPSIBLINGS風格,並且子窗口是層疊的,則在重繪子窗口的客戶區時,就會重繪鄰近的子窗口。

WS_DISABLED

創建一個初始狀態為禁止的子窗口。一個禁止狀態的窗口不能接受來自用戶的輸入信息。

WS_DLGFRAME

創建一個帶對話框邊框風格的窗口。這種風格的窗口不能帶標題條。

WS_GROUP

指定一組控制的第一個控制。這個控制組由第一個控制和隨后定義的控制組成,自第二個控制開始每個控制,具有WS_GROUP風格,每個組的第一個控制帶有WS_TABSTOP風格,從而使用戶可以在組間移動。用戶隨后可以使用光標在組內的控制間改變鍵盤焦點。

WS_HSCROLL

創建一個有水平滾動條的窗口。

WS_ICONIC

創建一個初始狀態為最小化狀態的窗口。與WS_MINIMIZE風格相同。

WS_MAXIMIZE

創建一個初始狀態為最大化狀態的窗口。

WS_MAXIMIZEBOX

創建一個具有最大化按鈕的窗口。該風格不能與WS_EX_CONTEXTHELP風格同時出現,同時必須指定WS_SYSMENU風格。

WS_OVERLAPPED

產生一個層疊的窗口。一個層疊的窗口有一個標題條和一個邊框。與WS_TILED風格相同。

WS_OVERLAPPEDWINDOW

創建一個具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX風格的層疊窗口,與WS_TILEDWINDOW風格相同。

WS_POPUP

創建一個彈出式窗口。該風格不能與WS_CHLD風格同時使用。

WS_POPUPWINDOW

創建一個具有WS_BORDER,WS_POPUP,WS_SYSMENU風格的窗口,WS_CAPTION和WS_POPUPWINDOW必須同時設定才能使窗口某單可見。

WS_SIZEBOX

創建一個可調邊框的窗口,與WS_THICKFRAME風格相同。

WS_SYSMENU

創建一個在標題條上帶有窗口菜單的窗口,必須同時設定WS_CAPTION風格。

WS_TABSTOP

創建一個控制,這個控制在用戶按下Tab鍵時可以獲得鍵盤焦點。按下Tab鍵后使鍵盤焦點轉移到下一具有WS_TABSTOP風格的控制。

WS_THICKFRAME

創建一個具有可調邊框的窗口,與WS_SIZEBOX風格相同。

WS_TILED

產生一個層疊的窗口。一個層疊的窗口有一個標題和一個邊框。與WS_OVERLAPPED風格相同。

WS_TILEDWINDOW

創建一個具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU, WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXMIZEBOX風格的層疊窗口。與WS_OVERLAPPEDWINDOW風格相同。

WS_VISIBLE

創建一個初始狀態為可見的窗口。

WS_VSCROLL

創建一個有垂直滾動條的窗口。

 

6.     顯示窗口

BOOL ShowWindow(HWND hWnd,     //窗口句柄
                 int nCmdShow   //顯示方式
                );

顯示方式可以是下表中的任何一種。

表格 6 窗口顯示方式

窗口顯示方式

說明

SW_HIDE

隱藏窗口並激活其他窗口。

SW_MAXIMIZE

最大化指定的窗口。

SW_MINIMIZE

最小化指定的窗口並且激活在Z序中的下一個頂層窗口。

SW_RESTORE

激活並顯示窗口。如果窗口最小化或最大化,則系統將窗口恢復到原來的尺寸和位置。在恢復最小化窗口時,應用程序應該指定這個標志。

SW_SHOW

在窗口原來的位置以原來的尺寸激活和顯示窗口。

SW_SHOWDEFAULT

依據在STARTUPINFO結構中指定的SW_FLAG標志設定顯示狀態,STARTUPINFO 結構是由啟動應用程序的程序傳遞給CreateProcess函數的。

SW_SHOWMAXIMIZED

激活窗口並將其最大化。

SW_SHOWMINIMIZED

激活窗口並將其最小化。

SW_SHOWMINNOACTIVE

窗口最小化,激活窗口仍然維持激活狀態。

SW_SHOWNA

以窗口原來的狀態顯示窗口。激活窗口仍然維持激活狀態。

SW_SHOWNOACTIVATE

以窗口最近一次的大小和狀態顯示窗口。激活窗口仍然維持激活狀態。

SW_SHOWNORMAL

激活並顯示一個窗口。如果窗口被最小化或最大化,系統將其恢復到原來的尺寸和大小。應用程序在第一次顯示窗口的時候應該指定此標志。

7.     更新窗口

 如果窗口更新的區域不為空,UpdateWindow函數通過發送一個WM_PAINT消息來更新指定窗口的客戶區。函數繞過應用程序的消息隊列,直接發送WM_PAINT消息給指定窗口的窗口過程,如果更新區域為空,則不發送消息。

8.     消息循環

MSG msg;
while (GetMessage(&msg,NULL,0,0))     //從消息隊列中取得一條消息
{
	TranslateMessage(&msg);       //將虛擬鍵消息轉化成字符消息	
	DispatchMessage(&msg);        //將消息發送給相應的窗口過程函數
}//

8.1.   MSG 結構體

MSG結構體包含一條WindowMessage的全部信息

typedef struct  tagMSG {                 //msg
                        HWND hwnd;       //接受消息循環的窗口句柄
   			UINT message;    //消息類型
   			WPARAM wParam;   //附加信息
   			LPARAM lParam;   //附加信息
   			DWORD time;      //投遞到消息隊列的時間
 			POINT pt;        //鼠標的位置
		       }MSG; //


8.2.   自定義MSG

參見博文:MFC 程序最小化到系統托盤區的一個簡單實例

 

9.     窗口過程

窗口過程函數是一個應用程序定義的函數,用來處理發送到窗口的消息。WNDPROC類型定義了一個指向該回調函數的指針。WindowProc是用於應用程序定義函數的占位符,也就是說,程序員自己更改WindowProc這個名稱,但是參數類型不變。

一個Windows 程序可以包含多個窗口過程。一個窗口過程總是與調用RegisterClass注冊的特定窗口類相關聯。程序通常不直接調用窗口過程。窗口過程通常由 Windows 本身調用。通過調用 SendMessage 函數,程序能夠直接調用它自己的窗口過程。


9.1.   函數聲明

 

LRESULT CALLBACK WindowProc(      
                         HWND	hwnd,   //指向窗口的句柄
   			 UINT 	uMsg,   //指定消息類型
 			 WPARAM wParam, //指定其余的、消息特定的信息
                         LPARAM	lParam  //指定其余的、消息特定的信息
);

9.2.   函數功能

該函數主要是用來處理發送給窗口的各類MSG消息。

窗口過程在處理消息時,必須返回0。

窗口過程不予處理的所有消息應該被傳給名為DefWindowProc() 函數。

從 DefWindowProc 返回的值必須由窗口過程返回。


本文部分內容來自MSDN和網絡。

轉載請注明地址:

JarvisChu的專欄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM