windows學習記錄----hello world與窗口創建
阿新 • • 發佈:2017-09-06
wchar 得到 ret rbac text 對話框 round tab鍵 col
當使用wchar_t類型的寬字符時, 使用"令牌粘貼", 使用TEXT宏時就避免了在字符串前面加上一個大寫字母‘L‘了。
1.第一個程序:Hello,world!
1 #include<windows.h> 2 3 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) 4 { 5 MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 ); 6 7 return 0; 8 }WinMain()函數 WINAPI為WinMain函數的調用規則, 在WINDEF.H對"WINAPI"作出了如下宏定義:
#defineWinMain函數的調用規則為"__stdcall"方式, 對於"__stdcall"調用規則, 具體用法待查。WINAPI __stdcall
WinMain函數的參數: 1.HINSTANCE hInstance:實例句柄 2.HINSTANCE hPrevInstance:前一個的實例句柄,歷史原因,已無實際意義,總為NULL。 3.LPSTR lpCmdLine:PSTR:運行程序的命令行。PSTR來指向一個字符串的指針類型, szCmdLine, sz:表示以0結尾的字符串;
目的是通過命令行方式運行程序並向主函數中傳入參數, 應該就像給main函數傳入參數一樣。暫未遇到具體命令程序,待學習。4.程序(窗口)最初如何被顯示, 例如最小化?最大化?全屏?暫未遇到具體命令程序,待學習。
MessageBox函數:
int MessageBox(
HWND hWnd, // handle of owner window, 窗口的一個句柄
LPCTSTR lpText, // address of text in message box, 一個文本(字符串)的指針
LPCTSTR lpCaption, // address of title of message box, 標題字符串的指針
UINT uType // style of message box, 對話框的風格
);
MessageBox( NULL, TEXT("Hello,world!"), TEXT("MessageBox"), 0 );
第一個參數窗口的句柄的實參為NULL, 意思為不屬於任何窗口.
第二個參數為對話框的內容,
第三個參數為對話框的標題, 但是這兩個參數都使用了一個TEXT()的函數,
#define __T(x) L ## x #define _TEXT(x) __T(x) #define __TEXT(quote) L##quote #define TEXT(quote) __TEXT(quote)
第四個參數為對話框的風格, 一些以MB_開頭的一些常量的組合, 可以使用OR(|)運算進行組合, 這些常量定義在WINUSER.H中, 例如常用的有: 1>.對話框按鈕類型: #define MB_OK 0x00000000L //僅有一個"確定"按鈕 #define MB_OKCANCEL 0x00000001L //"確定" + "取消" #define MB_ABORTRETRYIGNORE 0x00000002L //"終止" + "重試" + "忽略" #define MB_YESNOCANCEL 0x00000003L //"是" + "否" + "取消" #define MB_YESNO 0x00000004L //"是" + "否" #define MB_RETRYCANCEL 0x00000005L //"重試" + "取消" 2>.對話框中的圖標類型: #define MB_ICONHAND 0x00000010L //一個紅X的錯誤/停止圖標
#define MB_ICONQUESTION 0x00000020L //一個問號的詢問圖標
#define MB_ICONEXCLAMATION 0x00000030L //一個黃色感嘆號的警告圖標
#define MB_ICONASTERISK 0x00000040L //一個帶有i的信息提示圖標 同時, 在這些圖標中有的還可以用其他名稱代替, 這些別名在WINUSER.H的定義如下: #define MB_ICONWARNING MB_ICONEXCLAMATION //警告
#define MB_ICONERROR MB_ICONHAND //錯誤
#define MB_ICONINFORMATION MB_ICONASTERISK //信息
#define MB_ICONSTOP MB_ICONHAND //停止
2.創建自己的窗口
1 #include <windows.h> 2 3 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //聲明用來處理消息的函 4 5 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow ) 6 { 7 static TCHAR szAppName[] = TEXT("MyWindow") ; 8 HWND hwnd ; 9 MSG msg ; 10 WNDCLASS wndclass ; //聲明一個窗口類對象 11 12 //以下為窗口類對象wndclass的屬性 13 wndclass.style = CS_HREDRAW | CS_VREDRAW ; //窗口樣式 14 wndclass.lpszClassName = szAppName ; //窗口類名 15 wndclass.lpszMenuName = NULL ; //窗口菜單:無 16 wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ; //窗口背景顏色 17 wndclass.lpfnWndProc = WndProc ; //窗口處理函數 18 wndclass.cbWndExtra = 0 ; //窗口實例擴展:無 19 wndclass.cbClsExtra = 0 ; //窗口類擴展:無 20 wndclass.hInstance = hInstance ; //窗口實例句柄 21 wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ; //窗口最小化圖標:使用缺省圖標 22 wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; //窗口采用箭頭光標 23 24 if( !RegisterClass( &wndclass ) ) 25 { //註冊窗口類, 如果註冊失敗彈出錯誤提示 26 MessageBox( NULL, TEXT("窗口註冊失敗!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ; 27 return 0 ; 28 } 29 30 hwnd = CreateWindow( //創建窗口 31 szAppName, //窗口類名 32 TEXT("我的窗口"), //窗口標題 33 WS_OVERLAPPEDWINDOW, //窗口的風格 34 CW_USEDEFAULT, //窗口初始顯示位置x:使用缺省值 35 CW_USEDEFAULT, //窗口初始顯示位置y:使用缺省值 36 CW_USEDEFAULT, //窗口的寬度:使用缺省值 37 CW_USEDEFAULT, //窗口的高度:使用缺省值 38 NULL, //父窗口:無 39 NULL, //子菜單:無 40 hInstance, //該窗口應用程序的實例句柄 41 NULL // 42 ) ; 43 44 ShowWindow( hwnd, iCmdShow ) ; //顯示窗口 45 UpdateWindow( hwnd ) ; //更新窗口 46 47 while( GetMessage( &msg, NULL, 0, 0 ) ) //從消息隊列中獲取消息 48 { 49 TranslateMessage( &msg ) ; //將虛擬鍵消息轉換為字符消息 50 DispatchMessage( &msg ) ; //分發到回調函數(過程函數) 51 } 52 return msg.wParam ; 53 } 54 55 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) 56 { 57 HDC hdc ; //設備環境句柄 58 PAINTSTRUCT ps ; //繪制結構 59 RECT rect; //矩形結構 60 61 switch( message ) //處理得到的消息 62 { 63 case WM_CREATE: //窗口創建完成時發來的消息 64 MessageBox( hwnd, TEXT("窗口已創建完成!"), TEXT("我的窗口"), MB_OK | MB_ICONINFORMATION ) ; 65 return 0; 66 67 case WM_PAINT: //處理窗口區域無效時發來的消息 68 hdc = BeginPaint( hwnd, &ps ) ; 69 GetClientRect( hwnd, &rect ) ; 70 DrawText( hdc, TEXT( "Hello, 這是我自己的窗口!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ; 71 EndPaint( hwnd, &ps ) ; 72 return 0 ; 73 74 case WM_LBUTTONDOWN: //處理鼠標左鍵被按下的消息 75 MessageBox( hwnd, TEXT("鼠標左鍵被按下。"), TEXT("單擊"), MB_OK | MB_ICONINFORMATION ) ; 76 return 0; 77 78 case WM_DESTROY: //處理窗口關閉時的消息 79 MessageBox( hwnd, TEXT("關閉程序!"), TEXT("結束"), MB_OK | MB_ICONINFORMATION ) ; 80 PostQuitMessage( 0 ) ; 81 return 0; 82 } 83 return DefWindowProc( hwnd, message, wParam, lParam ) ; //DefWindowProc處理我們自定義的消息處理函數沒有處理到的消息 84 }
(1)窗口類對象wndclass的屬性
wndclass.style = CS_HREDRAW | CS_VREDRAW ; //窗口樣式 wndclass.lpszClassName = szAppName ; //窗口類名 wndclass.lpszMenuName = NULL ; //窗口菜單:無 wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ; //窗口背景顏色 wndclass.lpfnWndProc = WndProc ; //窗口消息處理函數 wndclass.cbWndExtra = 0 ; //窗口實例擴展:無 wndclass.cbClsExtra = 0 ; //窗口類擴展:無 wndclass.hInstance = hInstance ; //窗口實例句柄 wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ; //窗口最小化圖標:使用缺省圖標 wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; //窗口采用箭頭光標
1>. wndclass.style = CS_HREDRAW | CS_VREDRAW ; style屬性決定著窗口的風格, 可以通過C語言的或運算組合出不同風格類型的窗口, 在WINUSER.H頭文件中定義著這些標識符以及其值, 所有的前綴為CS_的標識符如下: * Class styles #define CS_VREDRAW 0x0001 #define CS_HREDRAW 0x0002 #define CS_DBLCLKS 0x0008 #define CS_OWNDC 0x0020 #define CS_CLASSDC 0x0040 #define CS_PARENTDC 0x0080 #define CS_NOCLOSE 0x0200 #define CS_SAVEBITS 0x0800 #define CS_BYTEALIGNCLIENT 0x1000 #define CS_BYTEALIGNWINDOW 0x2000 #define CS_GLOBALCLASS 0x4000 #define CS_IME 0x00010000 2>. wndclass.lpszClassName = szAppName ; 賦予窗口一個名稱, 可以使用ASCII版本的字符串也可以使用Unicode版本的字符串, 需要註意的是, 這裏的窗口名稱並不是指窗口標題。 3>. wndclass.lpszMenuName = NULL ; 指定窗口類的菜單, 由於我們這個窗口沒有使用菜單, 所以為NULL, 4>. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ; 窗口的背景顏色, 這裏使用的是以白色作為填充, 填充白色這是常見的做法, 如果你願意, 也可以填充為其他的一些樣式, 這裏是一些樣式的標識符: #define WHITE_BRUSH 0 #define LTGRAY_BRUSH 1 #define GRAY_BRUSH 2 #define DKGRAY_BRUSH 3 #define BLACK_BRUSH 4 #define NULL_BRUSH 5 #define HOLLOW_BRUSH NULL_BRUSH #define WHITE_PEN 6 #define BLACK_PEN 7 #define NULL_PEN 8 #define OEM_FIXED_FONT 10 #define ANSI_FIXED_FONT 11 #define ANSI_VAR_FONT 12 #define SYSTEM_FONT 13 #define DEVICE_DEFAULT_FONT 14 #define DEFAULT_PALETTE 15 #define SYSTEM_FIXED_FONT 16 5>. wndclass.lpfnWndProc = WndProc ; 將窗口的消息處理函數設置為我們自定義的WndProc函數。 6>. wndclass.cbWndExtra = 0 ; 7>. wndclass.cbClsExtra = 0 ; 這兩個屬性用來維護結構中預留的一些額外空間, 程序可以根據需要要使用這些額外空間, 通過匈牙利命名的cbClsExtra、cbWndExtra中的cb可以知道, 這些成員表示一個"字節數", 由於我們這個窗口沒有使用到額外空間, 所以將這個兩個屬性賦值為0; 8>. wndclass.hInstance = hInstance ; 表示應用程序的實例句柄, hInstance的來源是WinMain的一個參數; 9>. wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ) ; 加載一個位圖作為程序標題欄最左側的小圖標, 我們這裏加載了一個系統的默認圖標, 後面的學習這將會學習到如何從磁盤加載我們自定義的圖標. 10>. wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ; 與LoadIcon類似, 加載鼠標的指針位圖;
(2)註冊窗口
if( !RegisterClass( &wndclass ) ) { //註冊窗口類, 如果註冊失敗彈出錯誤提示 MessageBox( NULL, TEXT("窗口註冊失敗!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ; return 0 ; }
(3)創建窗口
hwnd = CreateWindow( //創建窗口 szAppName, //窗口類名 TEXT("我的窗口"), //窗口標題 WS_OVERLAPPEDWINDOW, //窗口的風格 CW_USEDEFAULT, //窗口初始顯示位置x:使用缺省值 CW_USEDEFAULT, //窗口初始顯示位置y:使用缺省值 CW_USEDEFAULT, //窗口的寬度:使用缺省值 CW_USEDEFAULT, //窗口的高度:使用缺省值 NULL, //父窗口:無 NULL, //子菜單:無 hInstance, //該窗口應用程序的實例句柄 NULL // ) ;
1>.參數一: LPCTSTR lpClassName 參數LPCTSTR lpClassName,為窗口的名稱, 我們需要傳入的參數就是剛才我們在窗口類註冊的窗口類名稱, 這樣使用CreateWindow建立的窗口就能與註冊的窗口進行關聯。 2>. 參數三: DWORD dwStyle 參數三為窗口的樣式, 示例中創建的是一個普通的層疊窗口樣式, WS_OVERLAPPEDWINDOW, 打開WINUSER.H頭文件, 對於WS_OVERLAPPEDWINDOW是這樣定義的: #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) 可以看出, WS_OVERLAPPEDWINDOW樣式實際上是通過一些標識符通過或的組合, 此外我們還可以通過組合設計我們自己的樣式, 這些標識符在WINUSER.H的定義如下: #define WS_OVERLAPPED 0x00000000L //產生一個層疊的窗口。一個層疊的窗口有一個標題條和一個邊框。與WS_TILED風格相同。 #define WS_POPUP 0x80000000L //創建一個彈出式窗口。該風格不能與WS_CHLD風格同時使用。 #define WS_CHILD 0x40000000L //創建一個子窗口。這個風格不能與WS_POPUP風格合用。 #define WS_MINIMIZE 0x20000000L //創建一個初始狀態為最小化的窗口。僅與WS_OVERLAPPED風格一起使用。 #define WS_VISIBLE 0x10000000L //創建一個最初可見的窗口。 #define WS_DISABLED 0x08000000L //創建一個初始狀態為禁止的窗口。 #define WS_CLIPSIBLINGS 0x04000000L //排除子窗口之間的相對區域。 #define WS_CLIPCHILDREN 0x02000000L //創建一個初始狀態為禁止的子窗口。一個禁止狀態的窗口不能接受來自用戶的輸入信息。 #define WS_MAXIMIZE 0x01000000L //創建一個初始狀態為最大化狀態的窗口。 #define WS_CAPTION 0x00C00000L //創建一個有標題框的窗口(包括WS_BODER風格)。 #define WS_BORDER 0x00800000L //創建一個單邊框的窗口。 #define WS_DLGFRAME 0x00400000L //創建一個帶對話框邊框風格的窗口。這種風格的窗口不能帶標題條。 #define WS_VSCROLL 0x00200000L //創建一個有垂直滾動條的窗口。 #define WS_HSCROLL 0x00100000L //創建一個有水平滾動條的窗口。 #define WS_SYSMENU 0x00080000L //創建一個在標題條上帶有窗口菜單的窗口,必須同時設定WS_CAPTION風格。 #define WS_THICKFRAME 0x00040000L //創建一個具有可調邊框的窗口,與WS_SIZEBOX風格相同。 #define WS_GROUP 0x00020000L //指定一組控制的第一個控制。 #define WS_TABSTOP 0x00010000L //創建一個控制,這個控制在用戶按下Tab鍵時可以獲得鍵盤焦點。按下Tab鍵後使鍵盤焦點轉移到下一具有WS_TABSTOP風格的控制。 #define WS_MINIMIZEBOX 0x00020000L //創建一個具有最小化按鈕的窗口。 #define WS_MAXIMIZEBOX 0x00010000L //創建一個具有最大化按鈕的窗口。 #define WS_TILED WS_OVERLAPPED //產生一個層疊的窗口。一個層疊的窗口有一個標題和一個邊框。與WS_OVERLAPPED風格相同。 #define WS_ICONIC WS_MINIMIZE //創建一個初始狀態為最小化的窗口。僅與WS_OVERLAPPED風格一起使用。 #define WS_SIZEBOX WS_THICKFRAME //創建一個具有厚邊框的窗口,可以通過厚邊框來改變窗口大小。 #define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW //創建一個具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAME,WS_MINIMIZEBOX和WS_MAXIMIZEBOX風格的重疊式窗口。
(4)窗口的顯示、更新
ShowWindow( hwnd, iCmdShow ) ; //顯示窗口 UpdateWindow( hwnd ) ; //更新窗口
ShowWindow函數的原型如下: BOOL ShowWindow( HWND hWnd, int iCmdShow ); 參數一為剛才通過CreateWindow函數窗口出的窗口句柄, 參數二為窗口的顯示方式, 由WinMain函數的int iCmdShow接收該值, 常用的顯示方式有: SW_HIDE //隱藏窗口並激活其他窗口; SW_MAXIMIZE //最大化; SW_MINIMIZE //最小化指定的窗口並且激活在Z序中的下一個頂層窗口; SW_RESTORE //激活並顯示窗口。如果窗口最小化或最大化,則系統將窗口恢復到原來的尺寸和位置; SW_SHOW //在窗口原來的位置以原來的尺寸激活和顯示窗口; SW_SHOWMAXIMIZED //激活窗口並將其最大化; SW_SHOWMINIMIZED //激活窗口並將其最小化; SW_SHOWMINNOACTIVE //窗口最小化,激活窗口仍然維持激活狀態; SW_SHOWNA //以窗口原來的狀態顯示窗口。激活窗口仍然維持激活狀態; SW_SHOWNOACTIVATE //以窗口最近一次的大小和狀態顯示窗口。激活窗口仍然維持激活狀態; SW_SHOWNORMAL //激活並顯示一個窗口。如果窗口被最小化或最大化,系統將其恢復到原來的尺寸和大小;
UpdateWindow函數的原型如下: BOOL UpdateWindow( HWND hWnd ); 該函數只有一個參數, 參數為需要更新的窗口句柄; 函數調用成功返回值為非0, 調用失敗時返回值為0。
(5)消息的轉換、分發
while( GetMessage( &msg, NULL, 0, 0 ) ) //從消息隊列中獲取消息 { TranslateMessage( &msg ) ; //將虛擬鍵消息轉換為字符消息 DispatchMessage( &msg ) ; //分發到回調函數(過程函數) } return msg.wParam ; }
(6)消息處理函數
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { HDC hdc ; //設備環境句柄 PAINTSTRUCT ps ; //繪制結構 RECT rect; //矩形結構 switch( message ) //處理得到的消息 { case WM_CREATE: //窗口創建完成時發來的消息 MessageBox( hwnd, TEXT("窗口已創建完成!"), TEXT("我的窗口"), MB_OK | MB_ICONINFORMATION ) ; return 0; case WM_PAINT: //處理窗口區域無效時發來的消息 hdc = BeginPaint( hwnd, &ps ) ; GetClientRect( hwnd, &rect ) ; DrawText( hdc, TEXT( "Hello, 這是我自己的窗口!" ), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ; EndPaint( hwnd, &ps ) ; return 0 ; case WM_LBUTTONDOWN: //處理鼠標左鍵被按下的消息 MessageBox( hwnd, TEXT("鼠標左鍵被按下。"), TEXT("單擊"), MB_OK | MB_ICONINFORMATION ) ; return 0; case WM_DESTROY: //處理窗口關閉時的消息 MessageBox( hwnd, TEXT("關閉程序!"), TEXT("結束"), MB_OK | MB_ICONINFORMATION ) ; PostQuitMessage( 0 ) ; return 0; } return DefWindowProc( hwnd, message, wParam, lParam ) ; //DefWindowProc處理我們自定義的消息處理函數沒有處理到的消息 }
windows學習記錄----hello world與窗口創建