1. 程式人生 > >windows學習記錄----hello world與窗口創建

windows學習記錄----hello world與窗口創建

wchar 得到 ret rbac text 對話框 round tab鍵 col

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"作出了如下宏定義:
#define
WINAPI __stdcall
WinMain函數的調用規則為"__stdcall"方式, 對於"__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()的函數,
當使用wchar_t類型的寬字符時, 使用"令牌粘貼", 使用TEXT宏時就避免了在字符串前面加上一個大寫字母‘L‘了。
#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與窗口創建