1. 程式人生 > >Window 32位 程式設計總結

Window 32位 程式設計總結

Lesson01

win32
Window 32位 程式設計
1.Windows程式設計基礎
2.Windows的字元
3.視窗處理
4.訊息處理
5.繪圖
6.對話方塊
7.控制元件

Win32程式設計:
Windows API:函式介面

一、Windows程式設計基礎
1.Windows應用程式分類
1.1 控制檯程式
DOS程式,本身沒有視窗,通過WINDOWS下的DOS視窗執行。
1.2 視窗程式
擁有自己的視窗,通過視窗可以和使用者進行互動
1.3 庫程式
1.3.1 靜態庫程式
存放程式碼,資料的程式,其他執行檔案從中獲取資料和程式碼

    1.3.2 動態庫程式
       存放程式碼,資料的程式,其他執行檔案從中獲取資料和程式碼       

2.對比
  2.1 入口函式
      控制檯程式  - main
      視窗程式    - WinMain
      動態庫程式  - DllMain
      靜態庫程式  - 無入口函式

  2.2 檔案存在方式
      控制檯程式  *.exe
      視窗程式    *.exe
      動態庫程式  *.dll
      靜態庫程式  *.lib

  2.3 執行方式
     控制檯程式  - 在DOS中執行
     視窗程式 - 擁有自己的視窗,在自己的視窗中執行
     動態庫程式 - 本身無法執行,由其他可執行的程式(*.exe)或動態庫(*.dll)呼叫
     靜態庫程式 - 執行不存在,嵌入其他可執行程式(.exe)或動態庫中

二、Windows下得開發環境
1. Visual stdio C++ 6.0

     vc1.5-vc6.0(98前後)-vs2005-vs2008-vs2010-vs2013-vs2015

  2. win30-win31-win32-windows95-98-2000- xp|2003 server - vista|win7 | 2008 server
     - win8  - win10

  3.VC++編譯工具
     1.編譯器 CL.EXE
        將原始碼編譯成目的碼

     2. 連結器 LINK.EXE
        將目的碼,庫檔案連結生成最終檔案

     3.資源管理器 RC.EXE            
        將資源編譯,最終通過連結器存入最終檔案      

   4.標頭檔案
        windows.h  - 絕大多數標頭檔案集合
        windef.h   - windows的資料型別
        winbase.h  - kernel32.dll的標頭檔案
        wingdi.h   - gdi32.dll的標頭檔案
        winuser.h  - user32.dll的標頭檔案
        winnt.h    - 提供了UNICODE字符集的支援

   5. 庫檔案
        kernel32.dll   - 提供了核心的API,例如:程序、執行緒、記憶體管理等
        gdi32.dll      - 繪圖相關的API
        user32.dll     - 提供視窗,訊息API

三 Hello World 程式
int _tWinMain(HINSTANCE hInstance,
//應用程式例項控制代碼
HINSTANCE hPrevInstance,
//當前應用程式,前一個程式的例項控制代碼
LPTSTR lpCmdLine,
//命令列引數
int nCmdShow);
//顯示方式

            hPrevInstance   - win32下一般為NULL,
             win32以前的程式用到的,現在一般不適用,歷史遺留問題。


    int MessageBox(
        HWND hWnd,
        //父視窗控制代碼
        LPCTSTR lpText,
        //提示框中資訊
        LPCTSTR lpCaption,
        //提示框標題欄的資訊
        UINT uType
        //提示框的風格
    ); //返回的是點選按鈕

Lesson02

         rc.exe

.rc ——————–>.res |
| link.exe
|——————->.exe/.lib/.dll(機器語言)
cl.exe |
.c/.cpp ——————–>組合語言(.obj)|

   編譯程式 - cl
     cl.exe /? 顯示cl命令的幫助
            /c 只編譯不連結

   連結程式 - link
      link.exe xxx.obj user32.lib uuid.lib

   執行看結果          

四、 第一個視窗程式
1.入口函式(WinMain)
2.定義視窗的處理函式 - 用於處理視窗中的各種訊息
3.註冊視窗類 - 將視窗類註冊到系統中
4.建立視窗 - 將視窗建立(並未顯示,在記憶體中建立視窗,記憶體中有了視窗的資料)
5.顯示視窗 - 將視窗顯示在顯示器上(根據記憶體中的資料將視窗繪製出來)
6.訊息迴圈 - 提取訊息/翻譯訊息/派發訊息
7.訊息處理 - 在第2步中的視窗處理函式處理訊息

Windows字元處理
  ASC        - 7位代表一個字元    128(0-127)
  ASCII      - 8位代表一個字元    256        前128與ASC相同 
                                         CODEPAGE  - 後面的128個分給其它國家語言使用
                                                漢語936  英語437

1.winodws字元的編碼方式
   DBCS編碼 (DOUBLE BYTE CHARACTER SET)
  由1個或2個位元組表示一個字元
  A    我   是   程    序    員        
 01   0203 0405 0607  0809  0A0B
 0102 0304 0506 0708  090A  0B

 UNICODE編碼(三套編碼方式,他們分別是UTF-8 UTF-16 UTF-32)
 WINDOWS平臺下,採用2個位元組表示一個字元
 A    我   是   程    序    員  
0001 0203 0405 0607  0809  0A0B

Lesson03

2.字元的使用
   1.寬位元組字元
     char       - 每一個字元佔1個位元組
     wchar_t    - 每一個字元佔2個位元組
     wchar_t    - 實際是unsigned short型別        
     定義時需要增加"L",通知編譯器按照雙位元組編譯字串,採用
     UNICODE編碼。函式需要使用支援寬位元組字串的函式 例如:
     wchar_t* wpszText = L"Hello WideChar";
     wprintf(L"%s",wprintf);
     int nlen = wcslen(wpszText);

   2.TCHAR:根據環境不同用UNICODE巨集開關切換TCHAR的定義,
           如果定義了UNICODE那麼TCHAR定義為wchar_t,如果
           沒有定義UNICODE那麼TCHAR定義為char

        #ifdef UNICODE              //#ifdef #ifndef 具有本檔案內向上溯源性
        typedef wchar_t TCHAR,*PTHCAR;
        #define __TEXT(quote) L##quote     //L"HELLO"
        #else
        typedef char TCHAR,*PTCHAR;
        #define __TEXT(quote) quote
        #endif         

     TCHAR* pszText = __TEXT("HELLO");
     如果定義了UNICODE巨集
     wchar_t* pszText = L"HELLO";
     如果沒有定義UNICODE巨集
     char* pszText = "HELLO";

    3.UNICODE字元列印
      wprintf 對UNICODE字元列印支援不完善

      在WINDOWS下使用WriteConsole
     BOOL WINAPI WriteConsole(
      _In_             HANDLE  hConsoleOutput,
      //標準輸出控制代碼
      _In_       const VOID    *lpBuffer,
      //輸出字串的BUFF
      _In_             DWORD   nNumberOfCharsToWrite,
      //準備輸出字元的個數
      _Out_            LPDWORD lpNumberOfCharsWritten,
      //實際輸出字元格式
      _Reserved_       LPVOID  lpReserved
      //備用
    );

    獲取標準控制代碼
    HANDLE GetStdHandle(
      DWORD nStdHandle
      //標準控制代碼型別
    ); //返回標準控制代碼

五、WINODWS視窗的註冊和建立
1.視窗的建立過程
1.1 入口函式 -WinMain
1.2 定義視窗處理函式 -WindowProc
1.3 註冊視窗類 -RegisterClass
1.4 建立視窗 -CreateWindow
1.5 顯示視窗 -ShowWindow/UpateWindow
1.6 訊息迴圈 -GetMessage/TranslateMessage/DispatchMessage
市場人員 需求分析師 排程/專案經理
1.7 訊息處理

2.視窗類
  視窗類就是一個結構體,它包含了視窗各種引數資訊的一個數據結構。
  每一個視窗必須有視窗類,基於視窗類,才可以建立視窗。

  每一個視窗都具有一個類名,使用前必須將類名註冊到作業系統中

3.視窗類的分類
  3.1  系統視窗類           - 系統已定義好的視窗類,所有程式無須註冊,直接使用即可。
  3.2  應用程式全域性視窗類   - 由使用者自己定義,當前應用程式的所有模組均可以使用      
  3.3  應用程式區域性視窗類   - 由使用者自己定義,當前應用程式的本模組可以使用 

4.系統視窗類的使用
  不需要註冊(不需要使用RegisterClass)直接使用系統以及定義好的視窗類名稱即可。
  比如:"BUTTON"   - 按鈕
        "EDIT"     - 文字編輯框  

5.應用程式全域性視窗類的使用
   5.1 註冊視窗類
       RegisterClass/RegisterClassEx

      WNDCLASSEX 結構體
    typedef struct tagWNDCLASSEX {
              UINT      cbSize;         //結構體的大小, sizeof(WNDCLASSEX)
              UINT      style;          //視窗風格 
              WNDPROC   lpfnWndProc;    //視窗處理函式
              int       cbClsExtra;     //視窗類附加資料緩衝區大小,位元組為單位 
              int       cbWndExtra;     //視窗的附加資料,位元組為單位
              HINSTANCE hInstance;      //應用程式例項控制代碼
              HICON     hIcon;          //視窗大圖示控制代碼
              HCURSOR   hCursor;        //滑鼠游標
              HBRUSH    hbrBackground;  //視窗背景顏色
              LPCTSTR   lpszMenuName;   //選單
              LPCTSTR   lpszClassName;  //視窗類名稱(最好不是漢語)
              HICON     hIconSm;        //視窗的小圖示
            } WNDCLASSEX, *PWNDCLASSEX;

    應用程式全域性視窗類,在註冊時需要增加CS_GLOBALCLASS 例如:
    WNDCLASSEX wce = {0};
    wce.style = ....|CS_GLOBALCLASS;

6. 應用程式區域性視窗類
    在註冊使用,不新增CS_GLOBALCLASS風格

7. 視窗類的風格       
    CS_GLOBALCLASS   - 應用程式全域性視窗類(一般不用)
    CS_BYTEALIGNCLIENT - 視窗客戶區水平位置8
                   倍數對齊。
    CS_BYTEALIGNWINDOW - 視窗水平位置8倍數對齊
    CS_HREDRAW - 視窗水平位置移動,重繪視窗。
    CS_VREDRAW - 視窗垂直位置移動,重繪視窗。
    CS_CLASSDC - 該型別視窗,都使用同一個DC.
    CS_PARENTDC - 該型別視窗,使用父視窗的DC.
    CS_OWNDC - 該型別視窗,使用自己的DC.
    CS_SAVEBITS - 允許視窗儲存成點陣圖(BMP)
    CS_DBLCLKS - 允許視窗接收滑鼠雙擊訊息。
    CS_NOCLOSE - 視窗沒有關閉按鈕。

Lesson04
8. 視窗類的查詢過程
1. 系統會根據傳入的視窗類名,在應用程式區域性視窗類中查詢。
如果找到了執行2
如果未找到執行3

   2.比較區域性視窗類與視窗視窗時傳入的HINSTANCE變數。
     如果發現相等,建立和註冊在同一模組中,建立視窗並返回
     如果發現不相等繼續執行3

   3.在應用程式全域性視窗類中查詢。
     如果找到執行4  
     如果未找到執行5

   4.使用找到的視窗類,建立視窗,並返回。

   5.在系統視窗類中查詢,
    如果找到建立視窗並返回,
    如果未找到建立視窗失敗

六。建立視窗
CreateWindow/CreateWindowEx
HWND WINAPI CreateWindowEx(
In DWORD dwExStyle,
//視窗的拓展風格
In_opt LPCTSTR lpClassName,
//視窗類名
In_opt LPCTSTR lpWindowName,
//視窗標題名稱名
In DWORD dwStyle,
//視窗的風格
In int x,
//視窗左上角的x坐軸標
In int y,
//視窗左上角的y坐軸標
In int nWidth,
//視窗的寬度
In int nHeight,
//視窗的高度
In_opt HWND hWndParent,
//父視窗控制代碼
In_opt HMENU hMenu,
//視窗的選單控制代碼
In_opt HINSTANCE hInstance,
//應用程式例項控制代碼
In_opt LPVOID lpParam
//視窗建立時的附加資料(引數)
); //執行成功,返回視窗控制代碼

2 子視窗的建立
2.1 建立時要設定父視窗控制代碼
2.2 建立子視窗要設定WS_CHILD | WS_VISIBLE

3 視窗類和視窗的附加資料
int cbClsExtra; //視窗類附加資料的BUFF大小,建議是4的倍數
int cbWndExtra; //視窗附加資料BUFF大小,建議是4的倍數

 SetClassLong    //設定視窗類附加資料
 DWORD WINAPI SetClassLong(
  _In_ HWND hWnd,      //視窗控制代碼
  _In_ int  nIndex,    //0-? 記憶體索引 
  _In_ LONG dwNewLong  //要設定的資料 (4位元組)
 );

 GetClassLong    //獲取視窗類附加資料
 DWORD WINAPI GetClassLong(
  _In_ HWND hWnd,
  _In_ int  nIndex
);//返回設定的附加資料

 SetWindowLong  //設定視窗附加資料    
 LONG WINAPI SetWindowLong(
  _In_ HWND hWnd,
  _In_ int  nIndex,
  _In_ LONG dwNewLong
);

GetWindowLong   //獲取視窗附加資料
LONG WINAPI GetWindowLong(
  _In_ HWND hWnd,
  _In_ int  nIndex
);  
可以提供視窗類和視窗存放自己資料空間,基本不用

七 訊息機制
1.程式的執行機制
過程驅動 - 程式的執行過程按照事先安排好的順序執行

 事件驅動    - 程式的執行時無序的,使用者可以根據需要隨機
               觸發相應的事件

 win32 視窗程式採用的事件驅動方式也就是訊息機制                


2.訊息機制
   當系統通知視窗工作時,就是採用訊息的正規化派發給視窗
   2.1 訊息的定義
       每個訊息都有一個ID,同時還附帶了兩個訊息的引數
        typedef struct tagMSG {
            HWND        hwnd;     //視窗的控制代碼
            UINT        message;  //訊息的ID 
            WPARAM      wParam;   //訊息的附加資料1
            LPARAM      lParam;   //訊息的附加資料2
            DWORD       time;     //訊息產生的時間
            POINT       pt;       //訊息產生時滑鼠的位置
        } MSG;     

   2.2 視窗處理函式
      LRESULT CALLBACK WndProc(
        HWND hWnd,      //視窗控制代碼
        UINT nMsg,      //訊息ID
        WPARAM wParam,  //訊息附加引數1
        LPARAM lParam)  //訊息附加引數2

     當系統通知視窗時,會呼叫視窗處理函式,同時將
     訊息的ID和引數傳遞給視窗處理函式。
     在視窗處理函式中,不處理的訊息呼叫預設處理函式
     DefWindowProc

   2.3 訊息相關的函式
     2.3.1 GetMessage        - 獲取訊息
        BOOL WINAPI GetMessage(
          _Out_    LPMSG lpMsg,         //獲取的訊息的BUFF
          _In_opt_ HWND  hWnd,          //視窗控制代碼
          _In_     UINT  wMsgFilterMin, //獲取的訊息最小ID
          _In_     UINT  wMsgFilterMax  //獲取的訊息最大ID
        );

        wMsgFilterMin和wMsgFilterMax只能獲取由這兩個值,指定的訊息
        範圍,如果都為0,表示沒有範圍

     2.3.2 TranslateMessage  - 翻譯訊息
         將按鍵訊息(可以字元的按鍵訊息需要翻譯),翻譯成字元訊息
         BOOL TranslateMessage(
                CONST MSG* lpMsg
                    //要翻譯的訊息的地址
                );
          首先檢查是否是可見字元的按鍵訊息,如果不是,直接返回

     2.3.3 DispatchMessage - 派發訊息
          LONG DispatchMessage(
                CONST MSG* lpMsg
                //準備派發的訊息的地址
                ); 

Lesson05
3 常見的幾個訊息
3.1 WM_DESTROY -視窗銷燬時的訊息
無訊息引數,常見與視窗銷燬之前的善後處理,例如:資源,記憶體的回收等

    3.2 WM_SYSCOMMAND  -系統命令訊息   
           當點選 最小化/最大化/關閉按鈕等命令時,收到訊息。常用於才視窗關閉時,
         提示使用者處理
        WPARMA     - 具體的命令,例如:SC_CLOSE

        LPARAM
        LOWORD     - 滑鼠的X軸座標
        HIWORD     - 滑鼠的Y軸座標
        低兩個位元組:  int a = 10000;
                     short b = a & 0xffff;          
        高兩個位元組: short c = a>>16;

    3.3 WM_CREATE      -視窗建立成功但還未顯示之前
                  常見於視窗的引數初始化,資源建立包括子視窗的建立
        WPARAM   - 不使用
        LPARAM   - 是CREATESTRUCT結構體的指標,儲存了CreateWindowEx函式的12個引數


    3.4 WM_SIZE       -視窗的大小發生變化後,收到這個訊息
                   常用於視窗大小變化後,調整視窗內的佈局
           WPARAM    - 視窗大小變化的原因
           LPARAM    
             LOWORD  - 視窗大小變化後客戶區的寬度
             HIWORD  - 視窗大小變化後客戶區的高度

   3.5  WM_QUIT      - 用於結束訊息迴圈
          WPARAM     -退出碼,PostQuitMessage函式的引數指定
          LPARAM     -不使用
        當GetMessage收到這個訊息後,會返回FALSE,結束while迴圈(使訊息迴圈退出)
        該訊息不會出現在視窗處理函式中


4. 訊息的獲取和傳送
     4.1 訊息的獲取
        GetMessage    - 從系統中獲取訊息,將訊息從系統中移除,阻塞函式,當系統
                         中沒有訊息,這個函式阻塞等候下一條訊息。

        PeekMessage   - 已檢視的方式從系統獲取訊息,可以不將訊息移除,非阻塞函式

         BOOL WINAPI PeekMessage(
          _Out_    LPMSG lpMsg,
          _In_opt_ HWND  hWnd,
          _In_     UINT  wMsgFilterMin,
          _In_     UINT  wMsgFilterMax,
          _In_     UINT  wRemoveMsg
           //移除表示
        );

     4.2 訊息傳送
      BOOL WINAPI PostMessage(
          _In_opt_ HWND   hWnd,
          //視窗控制代碼
          _In_     UINT   Msg,
          //訊息ID
          _In_     WPARAM wParam,
          //訊息引數1
          _In_     LPARAM lParam
          //訊息引數2
        );   

       PostMessage   -投遞訊息,訊息發出去後立即返回,不等候訊息的處理結果


        LRESULT WINAPI SendMessage(
          _In_ HWND   hWnd,
          _In_ UINT   Msg,
          _In_ WPARAM wParam,
          _In_ LPARAM lParam
        );

        SendMessage   -傳送訊息,訊息發出去後,等候處理完,才返回.


5. 訊息的分類
    1. 系統訊息          - ID範圍(0-0x0FF) 1024
      由系統定義好的訊息,所有程式直接可以使用

    2.使用者自定義訊息     - ID範圍(0x0400-0x7FFF)(31743)
      由使用者自己定義,滿足使用者自己的需求,使用者自定義的訊息,需要使用者自己
      傳送,並負責處理
          定義巨集 WM_USER 代表0x0400,自定義訊息ID時
          #define  WM_MYMESSAGE  WM_USER+n

    3.應用程式訊息      - ID範圍(0x8000 - 0xBFFF)
      用於程式之間的通訊(目前用不到,多見底層驅動程式)
       定義巨集 WM_APP 代表0x8000


    4.系統註冊訊息     - ID範圍(0xC000-0xFFFF)
      在系統註冊並生成訊息,然後在各個應用程式中使用

八. 訊息和訊息佇列
1. 訊息佇列
用於存放訊息的佇列,訊息在佇列中先進先出,所有視窗都有訊息佇列,程式從訊息佇列
中提出訊息

  2. 訊息佇列的型別         
     2.1 系統的訊息佇列
         由系統維護的訊息佇列,存放系統產生的訊息。(滑鼠,鍵盤)

     2.2 程式的訊息佇列
         屬於程式(主執行緒)的訊息佇列,由程式本身負責維護。       


  3.訊息佇列的關係 
     3.1 當滑鼠和鍵盤產生訊息時,先放入系統訊息佇列

     3.2 系統會根據存放訊息,找到對應的視窗資訊

     3.3 按照對應的視窗資訊,將訊息轉發給相應的程序的訊息佇列中


  4.佇列訊息和非佇列訊息
     4.1 根據訊息和訊息佇列的使用關係
        4.1.1 佇列訊息
            將訊息存入訊息佇列,訊息的傳送和獲取都是通過佇列完成

        4.1.2 非佇列訊息             
             訊息不進入佇列,直接呼叫視窗處理函式

     4.2 佇列訊息 
         - 先把訊息放入佇列,通過訊息迴圈從佇列中獲取訊息並且傳送給視窗處理函式

         GetMessage/PeekMessage    -取佇列訊息
         PostMessage               -向佇列中投遞訊息


     4.3 非佇列訊息
         - 訊息直接找對應的視窗處理函式,並呼叫處理函式,完成處理

         SendMessage   -  傳送非佇列訊息,直接視窗處理函式,等待處理結果。

         SendMessage(...)
         {
            //...
            return WndProc(...);
         }      

Lesson 6
5 訊息的獲取
5.1.1 訊息迴圈
5.1.1 GetMessage/PeekMessage 從程式的訊息佇列中獲取訊息

      5.1.2 TranslateMessage   
      -檢查GetMessage/PeekMessage函式獲取到的訊息,
       如果是可見字元按鍵訊息,產生一個字元訊息(WM_CHAR),並且將
       字元訊息放入訊息佇列

      5.1.3 DispatchMessage   
       -根據取出的訊息,找到對應的視窗處理函式,
        完成訊息處理

  5.2  GetMessage/PeekMessage 執行機制
       1 先去程式(執行緒)的訊息佇列中檢查有沒有訊息,
          如果有訊息,檢查指定條件(視窗控制代碼,ID範圍)是否滿足,如果滿足
          條件取出訊息進行處理

       2 如果程式(執行緒)的訊息佇列中沒有訊息,向系統的訊息佇列中獲取本程式的
          訊息,系統將訊息轉發給程式的訊息佇列,然後GetMessage/PeekMessage再從
          程式的訊息佇列中獲取訊息
          (系統佇列中的訊息無法直接獲取,需要轉發到程式的訊息佇列中在獲取)

       3  如果系統的訊息佇列中也沒有和本程式相關的訊息,檢查有沒有需要重新繪製的
          區域,如果有傳送WM_PAINT 訊息,放入佇列,取出並處理

       4  如果沒有需要重新繪製的區域,檢查有沒有到時間的定時器,如果有傳送WM_TIMER訊息
          放入佇列,取出並處理

       5  如果以上都沒有,整理記憶體和資源等

       6  GetMessage 阻塞等候下一條訊息
          PeeKMessage 會返回FALSE,交出程式的控制權

          注:GetMessage函式,如果獲取到WM_QUIT 返回FALSE

九、WM_PAINT

 1. WM_PAINT    - 視窗中,有需要重新回去的區域,就會產生WM_PAINT訊息

 視窗需要重新繪製的區域叫視窗無效區域

 UpdateWindow/RedrawWindow 重新整理整個視窗
 BOOL InvalidateRect(
  _In_       HWND hWnd,   //視窗控制代碼
  _In_ const RECT *lpRect,//定義視窗無效區域(可以為NULL)
  _In_       BOOL bErase  //擦除標識
);             

2. 繪圖步驟(WM_PAINT)
  2.1 BeginPaint    -開始繪圖
  HDC BeginPaint(
   _In_  HWND          hwnd,   //視窗控制代碼
   _Out_ LPPAINTSTRUCT lpPaint //繪圖結構體指標(程式設計師基本不用)
 ); //返回繪圖裝置控制代碼


 2.2 繪圖(需要使用HDC)

 2.3 EndPaint     -結束繪圖

 BOOL EndPaint(
  _In_       HWND        hWnd, //視窗控制代碼
  _In_ const PAINTSTRUCT *lpPaint //繪圖結構體指標(程式設計師基本不用)
 );


 WM_PAINT的處理過程:
    如果有無效區域(無效區域標識),再合適的時機產生WM_PAINT訊息,在處理
    函式中對這個訊息進行處理,處理時先呼叫BeginPaint(...),得到繪圖裝置控制代碼
    的同時去掉無效區域標識,然後用HDC完成繪圖,最後利用EndPaint結束繪圖

十 鍵盤訊息
WM_KEYDOWN -按鍵按下時產生的訊息(按住不鬆可以產生多次WM_KEYDOWN)
WM_KEYUP -按鍵被放開產生的訊息 (一次按鍵只能產生一次)
WPARAM -虛擬鍵碼
LPARAM -按鍵的引數,比如按鍵的次數等

WM_CHAR       -字元訊息 (TranslateMessage)
    WPARAM    - 字元編碼
    LPARAM    - 按鍵的引數

    TranslateMessage(&nMsg)
    {
        //是否是按鍵訊息
        if (nMsg.message != WM_KEYDOWN )
            return;

        //通過nMsg.wParam(虛擬鍵碼)判斷是否是可見字元
        if ( 不是可見字元)
            return;

        if(是可見字元)
        {
            //判斷capslock是否處於開啟狀態
            if(開啟)
                ...
                PostMessage(nMsg.hWnd,WM_CHAR,0x41,...);
            else
                ...
                PostMessage(nMsg.hWnd,WM_CHAR,0x61,...);
        }           
    }       

 WM_KEYDOWN/UP按鍵訊息的WPARAM 表示按鍵的虛擬鍵碼

 WM_CHAR字元訊息的WPARAM 表示的是輸入字元(字元ASCII編碼)  

六 滑鼠訊息
1.滑鼠基本訊息
滑鼠左鍵按下 - WM_LBUTTONDOWN
滑鼠左鍵彈起 - WM_LBUTTONUP
滑鼠右鍵按下 - WM_RBUTTONDOWN
滑鼠右鍵彈起 - WM_RBUTTONUP
滑鼠移動 - WM_MOUSEMOVE
WPARAM -按鍵的狀態 例如:Ctrl/Shift
LPARAM
LOWORD -滑鼠游標的x軸座標(客戶區座標系)
HIWORD -滑鼠游標的y軸座標

Lesson 7

  1. 雙擊訊息 需要CS_DBLCLKS風格
    滑鼠左鍵雙擊 - WM_LBUTTONDBLCLK
    滑鼠右鍵雙擊 - WM_RBUTTONDBLCLK
    WPARAM -按鍵的狀態 例如:Ctrl/Shift
    LPARAM
    LOWORD -滑鼠游標的x軸座標
    HIWORD -滑鼠游標的y軸座標

  2. 滑鼠滾輪訊息 - WM_MOUSEWHEEL
    WPARAM
    LOWORD -按鍵的狀態 例如:Ctrl/Shift
    HIWORD -滾輪滾動偏移量(120倍數)
    正數代表向前滾,負數代表向後滾

     LPARAM       滑鼠當前位置,螢幕座標系
         LOWORD   -滑鼠游標的x軸座標
         HIWORD   -滑鼠游標的y軸座標
    

七 定時器Timer (WM_TIMER)
1.可以在程式中設定定時器,每隔一定的時間間隔會向
訊息佇列中傳送一個WM_TIMER訊息。

  定時器時間間隔的單位毫秒 但是準確率很差 

  每隔一定時間間隔,自動傳送WM_TIMER訊息到視窗處理函式,
  間隔單位毫秒,但不是一個準確的定時器,而且由於優先順序較低
  有可能根本不產生。   

2.訊息的引數
  WPARAM  - 定時器ID
  LPARAM  - 定時器處理函式的指標

3.定時器的使用
   3.1 建立並啟動定時器
     UINT WINAPI SetTimer(
       HWND      hWnd,
       //視窗控制代碼
       UINT_PTR  nIDEvent,
       //定時器ID
       UINT      uElapse,
       //定時器的時間間隔(ms)
       TIMERPROC lpTimerFunc
       //定時器的處理函式(可以為NULL)
    );//如果定時器建立成功,返回非0

  定時器的處理函式可以自己定義,也可以使用視窗處理函式

  3.2 定時器處理函式
     VOID CALLBACK TimerProc(
       HWND     hwnd,
       //視窗控制代碼
       UINT     uMsg,
       //WM_TIMER
       UINT_PTR idEvent,
       //定時器ID
       DWORD    dwTime
       //當前系統時間
    );


  3.3 定時器每隔uElapse 毫秒產生一個WM_TIMER訊息,這個訊息將由
      TimerProc或者WindowsProc來處理   

  3.4 關閉定時器
     KillTimer   -銷燬定時器
    BOOL KillTimer(
      HWND hWnd, 
      //視窗控制代碼
      UINT uIDEvent
      //定時器ID         
    ); 

練習:
GetClientRect -得到視窗客戶區的大小
BOOL WINAPI GetClientRect(
HWND hWnd,
//視窗控制代碼
LPRECT lpRect
//RECT結構體的指標
);

    typedef struct _RECT {
      LONG left;
      LONG top;
      LONG right;
      LONG bottom;
    } RECT, *PRECT;


  Ellipse    -繪製圓
     BOOL Ellipse(
         HDC hdc,
         //繪圖裝置控制代碼(BeginPaint函式的返回值)
         int nLeftRect,
         //左上角的X座標       
         int nTopRect,
         //左上角的Y座標       
         int nRightRect,
         //右下角的X座標       
         int nBottomRect
         //右下角的Y座標
     );

Lesson8
八.選單的分類
1.1 視窗頂層選單
1.2 彈出式選單
1.3 系統選單
HMENU - 選單控制代碼
每一個參與訊息的選單項都對應一個ID

2.視窗頂層選單
    2.1 CreateMenu     -建立選單      
        HMENU WINAPI CreateMenu(); 

    2.2 AppendMenu/InsertMenu   - 新增選單項        
        BOOL WINAPI AppendMenu(
           HMENU    hMenu,
           //選單控制代碼
           UINT     uFlags,
           //選單項的風格
           UINT_PTR uIDNewItem,
           //選單的ID或者(彈出式)下拉選單的控制代碼
           LPCTSTR  lpNewItem
           //選單項的文字資訊
        );

    uFlags:
    MF_POPUP       - 選單項要有彈出式選單,選單項id為(彈出式)下拉選單(子選單)的控制代碼     
    MF_SEPARATOR   - 選單項分割線
    MF_STRING      - 選單被點選之後,發出訊息WM_COMMAND
    MF_MENUBARBREAK  -對於彈出式選單,放到新欄中,欄間有分隔線          

    2.3 顯示選單
    BOOL WINAPI SetMenu(
           HWND  hWnd,
           //視窗控制代碼
           HMENU hMenu
           //選單控制代碼
    );

3. 彈出式選單
   3.1  CreatePopupMenu   - 建立彈出式選單
           HMENU WINAPI CreatePopupMenu();

   3.2  AppendMenu/InsertMenu   -新增選單項


4. 選單項的訊息
    點選選單項產生WM_COMMAND訊息
    WPARAM
        HIWORD    - 對於選單為0
        LOWORD    - 指明被點選的選單項的ID

    LPARAM     -對於選單為NULL

  可以根據LOWORD(wParam)確定選單項的ID,然後根據ID處理訊息


5. 選單的狀態
   5.1 在增加選單項時,設定選單項的狀態MF_XXX(如:MF_CHECKED MF_GRAYED)
   5.2 可以使用特定的函式改變選單項的狀態
       5.2.1 CheckMenuItem        -修改勾選狀態
         DWORD CheckMenuItem(
            HMENU hmenu, 
            //選單的控制代碼
            UINT uIDCheckItem,
            //選單項的ID(或者索引)
            UINT uCheck
            //選單項的狀態
        );

       5.2.2 EnableMenuItem      -修改可用狀態     
         DWORD EnableMenuItem(
            HMENU hmenu, 
            //選單的控制代碼
            UINT uIDCheckItem,
            //選單項的ID(或者索引)
            UINT uCheck
            //選單項的狀態
        );

       注:分割線佔一個位置
       以上兩個函式,再使用時,選單項標識
       可以使用位置(索引)或者ID
       MF_BYCOMMAND 通過id定位  
       MF_BYPOSITION 通過位置索引

    5.3 WM_INITMENUPOPUP
         在選單被啟用但還未顯示之前,產生的訊息

        WPARAM      - 選單控制代碼(彈出即將顯示的選單控制代碼) 

        LPARAM
             LOWORD  - 被點選的頂層選單項的位置(索引)
             HIWORD  - 視窗選單的標識

        視窗選單:系統選單和視窗的頂層選單
        彈出式選單不屬於視窗選單

6. 系統選單
   1.  GetSystemMenu   - 獲取系統選單控制代碼
       HMENU WINAPI GetSystemMenu(
           HWND hWnd,
           //視窗控制代碼
           BOOL bRevert
           //重置標識
        );

        TRUE:  把當前的系統選單重置為預設的系統選單
        FLASE: 不做重置,返回當前的系統選單控制代碼

   2. 系統選單的修改
        BOOL DeleteMenu( 
            HMENU hMenu,
            //選單控制代碼
            UINT uPosition,
            //選單的ID或者位置(索引)
            UINT uFlags
            //MF_BYCOMMAND/MF_BYPOSITION
         );

        AppendMenu           

   3. 系統選單的訊息
      WM_SYSCOMMAND
        WPARAM  
          LOWORD   選單項的ID


7. 右鍵彈出選單
   1.使用
      1.1 建立彈出選單 CreatePopupMenu
          AppenMenu/InsertMenu

      1.2 顯示彈出式選單 TrackPopupMenu              
        BOOL WINAPI TrackPopupMenu(
         HMENU hMenu,
         //彈出式選單控制代碼
         UINT  uFlags,
         //選單風格
         int   x,
         //選單x軸位置 (螢幕座標)
         int   y,
         //選單y軸位置 (螢幕座標)
         int   nReserved,
         //保留引數,必須為0
         HWND  hWnd,
         //視窗控制代碼
         const RECT  *prcRect
         //忽略
    );

    TrackPopupMenu 是一個阻塞函式,在選擇選單項之前程式不會繼續執行

    視窗(客戶區)座標轉換螢幕座標
    ClientToScreen
    BOOL ClientToScreen( 
      HWND hWnd, 
      //視窗控制代碼
      LPPOINT lpPoint
      //點的座標(輸入輸出引數)
      客戶區座標系下的座標
      螢幕座標系下的座標
    ); 

    螢幕座標轉換成視窗客戶區座標
    ScreentToClient
    BOOL ClientToScreen( 
      HWND hWnd, 
      //視窗控制代碼
      LPPOINT lpPoint
      //點的座標(輸入輸出引數)
      螢幕座標系下的座標
      客戶區座標系下的座標
    ); 

    1.3 選單項的命令處理
        WM_COMMAND 與視窗頂層選單一樣

    1.4 WM_CONTEXTMENU專職處理右鍵選單,在WM_RBUTTONUP之後產生
        WPARAM      -指向視窗控制代碼
        LPARAM 
           LOWORD    -游標的x軸座標(螢幕座標系)
           HIWORD    -游標的y軸座標(螢幕座標系)

Lesson 9

九、資源的使用
1. 資源相關
資源指令碼檔案 .rc檔案
rc.exe 將.rc檔案編譯生成.res檔案
資源可以給程式設定選單、工具欄、快捷鍵、點陣圖、對話方塊、
程式版本資訊、多種語言的STRING表等…

      注:使用資源必須建立.rc(資源)指令碼檔案


    2.選單資源的使用
      2.1 新增選單資源(VS中新增)

      2.2 使用選單資源
         2.2.1 註冊視窗類時載入選單          基於視窗類建立的所有視窗選單都一樣
           MAKEINTRESOURCE       - 將數字形式的資源ID轉換為字串形式的資源ID
           MAKEINTRESOURCE(IDR_MENU1)

         2.2.2 載入選單資源,設定到視窗      基於同一視窗類可以掛載不同的選單
            HMENU LoadMenu( 
              HINSTANCE hInstance,
              //應用程式例項控制代碼
              LPCTSTR lpMenuName
             //字串形式的選單資源ID
             (利用MAKEINTRESOURCE轉換)
            ); 
            將硬碟上的.rc指令碼檔案中關於lpMenuName資源的資料載入到hInstance指明的記憶體中,
            並獲取選單控制代碼

    3.圖示資源的使用
      3.1 新增圖示資源(VS中新增)

      3.2 使用圖示資源,載入圖示   
            HICON LoadIcon( 
              HINSTANCE hInstance,
               //應用程式例項控制代碼
              LPCTSTR lpIconName
             //字串形式的選單資源ID
             (利用MAKEINTRESOURCE轉換)                
            ); 
      3.3 設定圖示  
          3.3.1 註冊視窗類時,設定圖示
             建議大小圖示一致,使用者體驗好


          3.3.2 使用WM_SETICON訊息
              wParam = (WPARAM)(BOOL) fType;
                   ICON_BIG/ICON_SMALL  大圖示/小圖示

             lParam = (LPARAM)(HICON) hicon;
                   要設定的圖示的控制代碼                 

       3.4 繪製圖標到視窗
            BOOL DrawIcon(
                HDC hDC,
                //繪圖裝置控制代碼
                int X,
                //x軸座標(客戶區座標系)
                int Y, 
                //y軸座標(客戶區座標系)
                HICON hlcon 
                //圖示控制代碼
            );


    4. 游標資源的使用  
        4.1 在VS中新增
         游標的大小預設是32*32畫素,每個游標都有HotSpot,是當前滑鼠的熱點

         Windows下游標的檔案.cur(靜態)為字尾和.ani(動態)為字尾
         系統游標目錄:C:\Windows\Cursors

        4.2 載入游標資源
            HCURSOR WINAPI LoadCursor(
               HINSTANCE hInstance,
                //應用程式例項控制代碼
               LPCTSTR   lpCursorName
               //字串形式的選單資源ID
              (利用MAKEINTRESOURCE轉換) 
            );

            4.2.1 註冊視窗類時


            4.2.2 使用SetCursor設定游標
                HCURSOR SetCursor(
                  HCURSOR hCursor
                  //設定的新的游標控制代碼
                );//返回原來的游標控制代碼

        4.3  WM_SETCURSOR 訊息
           產生: 滑鼠移動導致游標的移動,並且捕獲滑鼠的移動,就產生WM_SETCURSOR
           WPARAM     -當前使用的游標控制代碼

           LPARAM
              LOWORD     - 當前區域的程式碼(hit-test code)
                        (HTCLIENT 代表客戶區  HTCAPTION 非客戶區-標題欄)

              HIWORD     - 當前滑鼠訊息ID             


            GetCursorPos    - 得到滑鼠游標位置
            BOOL WINAPI GetCursorPos(
              LPPOINT lpPoint
              //存放滑鼠位置buffer,螢幕座標系下的座標
            );

            GetClientRect      -獲取視窗邊界,視窗客氣區座標系
            ScreenToClient    -將螢幕座標系下的座標轉換為客戶區座標系下的座標


            從游標檔案中載入游標資源
            HCURSOR LoadCursorFromFile(
            LPCTSTR IpFileName
             //游標資原始檔名
            );

Lesson10

  5. 字串資源
    2.1 新增字串資源
       字串表,在表中新增字串

    2.2  字串資源的使用   
      int LoadString( 
          HINSTANCE hInstance,
            //應用程式例項控制代碼
          UINT uID,  
           //資源ID
          LPTSTR lpBuffer,
            //接收字串的BUFF
          int cchBufferMax 
           //BUFF的大小          
        ); //成功返回字元窗的長度,失敗返回0


  6 快捷鍵(加速鍵)資源
     6.1 新增快捷鍵資源
        新增加速鍵表,增加命令ID對應的加速鍵
        一般加速鍵可以和選單項的ID命令對應


     6.2 快捷鍵(加速鍵)的使用         
           6.2.1 載入快捷鍵(加速表)表
              HACCEL LoadAccelerators(
                  HINSTANCE hInstance,
                   //應用程式例項控制代碼
                  LPCTSTR lpTableName
                   //字串形式的加速鍵資源ID                    
                ); //返回加速鍵控制代碼


            6.2.2 處理加速鍵訊息
              int TranslateAccelerator(
                  HWND hWnd, 
                  //視窗控制代碼
                  HACCEL hAccTable,
                  //加速鍵表控制代碼
                  LPMSG lpMsg
                  //訊息
                ); //如果是加速鍵返回非0


            6.2.3 TranslateAccelerator 函式的執行機制

                 TranslateAccelerator(hwnd,hAccTable,&nMsg)
                 {
                    if ( nMsg.message != WM_KEYDOWN || nMsg.message != WM_SYSCOMMAND )
                        return 0;

                    根據訊息附帶的引數(nMsg.wParam)虛擬鍵碼(CTRL+Y)

                    將(CTRL+Y)去hAccTable加速鍵表中查詢

                    if(找到了)
                    {
                        PostMessage(hwnd,WM_COMMAND, L(ID_NEW) H(1),NULL);
                        return 1;
                    }else{
                        return 0;
                    }
                 }


            6.2.4 快捷鍵(加速鍵)產生WM_COMMAND   
                 WPARAM
                   HIWORD      - 加速鍵為1           選單為0                    
                   LOWORD      - 加速鍵ID            選單的ID

                 LPARAM  -未使用


            6.2.5 加速鍵的命令ID與選單項的命令ID無關
                  但是為了程式碼複用最好定義成一樣的ID

十、繪圖
1. 繪圖相關
繪圖裝置 (Device Context - DC 也叫繪圖上下文)

       BeginPaint   - 獲取繪圖裝置

          HDC hdc = BeginPaint(hWnd,...);
          TextOut(hdc,100,100,"dfsass",...);
          Ellipse(hdc,100,100,200,200,...);

       EndPaint  - 回收繪圖裝置

       HDC   -DC控制代碼  表示繪圖裝置

  2. GDI  -windows graphics device interface  WIN32提供的繪圖API            


  3. 顏色
      3.1 顏色的表示(RGB)
          計算機使用紅,綠,藍每種顏色的取值範圍
            R 代表紅色   0 ~ 255
            G 代表綠色   0 ~ 255
            B 代表藍色   0 ~ 255               

          每個點的顏色是3個位元組(24位)儲存取值範圍(0 ~ 2^24 - 1)

                R    G    B
         16位   5    5    6
         32位   8    8    8  多出的8位用於透明度(一般是3D繪圖用) 

         Direct3D
         openGL          


      3.2 顏色的使用
            COLORREF      -實際是DWORD
            COLORREF nColor = 255;

            賦值使用RGB巨集,例如:
            COLORREF nColor = RGB(0,255,0);

            獲取顏色的RGB值
            GetRValue(nColor)/GetGValue/GetBValue
              例如: BYTE nRed = GetRValue(nColor);


      3.3 點的使用
          GetPixel    - 獲取指定點的顏色 

          COLORREF GetPixel(
              HDC hdc,
              //繪圖裝置控制代碼      
              int nXPos, 
              //x軸座標
              int nYPos
              //x軸座標
           ); 


           SetPixel    - 設定指定點的顏色
           COLORREF SetPixel(
              HDC hdc, 
               //繪圖裝置控制代碼 
              int X, 
              //x軸座標
              int Y, 
              //x軸座標
              COLORREF crColor
              //設定的顏色值
            ); 


     3.4 線的使用
           MoveToEx      - 移動當前點到指定點(指定線的初始點)

            BOOL  MoveToEx(
                HDC hdc,
                //DC控制代碼
                int X,
                //指定點的x座標
                int Y,
                //指定點的y座標
                LPPOINT lpPoint
                //當期點的BUFF
                );


            LineTo  - 從當前點到終點繪製一條直線

          BOOL LineTo(
              HDC hdc,
              //DC控制代碼
              int nXEnd,
              //指定終點的x座標
              int nYEnd
              //指定終點的y座標
            );      


           預設情況下,當前為(0,0), 上一次繪圖的終點是下一次繪圖的當前點


    3.5 封閉圖形的使用( 能夠用畫刷填充的圖形 ?)
         Rectangle/RoundRect


         BOOL Rectangle(
                HDC hdc, //DC控制代碼
                int nLeftRect, //左上角的x座標
                int nTopRect,  //左上角的Y座標
                int nRightRect, //右下角的X座標
                int nBottomRect //右下角的Y座標
            );

            BOOL RoundRect(
               HDC hdc,
               int nLeftRect,
               int nTopRect,
               int nRightRect,
               int nBottomRect,
               int nWidth,
               //指定用來畫圓角的橢圓的寬
               int nHeight
               //指定用來畫圓角的橢圓的高
            );

    3.6 圓的使用
        Ellipse     - 繪製圓 或 橢圓      

        BOOL Ellipse(
         HDC hdc,
         //繪圖裝置控制代碼(BeginPaint函式的返回值)
         int nLeftRect,
         //左上角的X座標       
         int nTopRect,
         //左上角的Y座標       
         int nRightRect,
         //右下角的X座標       
         int nBottomRect
         //右下角的Y座標
        );


    3.7 圓弧的使用
        //設定圓弧的方向
         int SetArcDirection(
           HDC hdc,    
           //控制代碼
           int ArcDirection
           //圓弧的方向
           //AD_CLOCKWISE 順時針
           //AD_COUNTERCLOCKWISE 逆時針
        );          


        BOOL Arc(
            HDC hdc,
            int xLeft,
            int yTop,
            //外接矩形的左上角座標
            int xRight,
            int yBottom,
            //外接矩形的右下角座標
            int XStart,
            int YStart,
            //圓弧的起點座標
            int XEndA,
            int YEnd
            //圓弧的終點座標
            ); 

Lesson11

4 GDI繪圖物件    - 畫筆  
    4.1 畫筆相關
         作用:線的顏色,線型(實線,虛線),線粗

         HPEN    - 畫筆的控制代碼

    4.2 畫筆的使用
        4.2.1  建立畫筆  -  CreatePen
            HPEN CreatePen( 
              int fnPenStyle,
              //畫筆的樣式
              int nWidth, 
              //畫筆的寬度
              COLORREF crColor
              //畫筆的顏色
            );//建立成功,返回畫筆控制代碼

           PS_SOLID   - 實心先,可以支援1個單位寬度

           其它所有的風格,只能是1個單位的寬度  例如:PS_DASH


       4.2.2 將畫筆應用到DC中  - SelectObject  
            HGDIOBJ SelectObject( 
              HDC hdc,   //DC控制代碼
              HGDIOBJ hgdiobj
              //繪圖物件控制代碼          
            ); //返回舊的繪圖物件控制代碼


       4.2.3 繪圖


       4.2.4  取出DC中的畫筆    -  SelectObject
              將原來的畫筆,使用SelectObject函式放入到DC中,
              就會將我們建立的畫筆取出

       4.2.5  釋放畫筆    -  DeleteObject
               BOOL DeleteObject(
                 HGDIOBJ hObject
                 //繪圖物件控制代碼
               ); 


            只能刪除不被DC使用的畫筆,所以在釋放畫筆之前,必須
            將畫筆從DC中取出


5 GDI 繪圖物件     - 畫刷        
      5.1  畫刷 
          作用:給封閉圖形填充顏色,圖案

          HBRSH    - 畫刷控制代碼


      5.2 畫刷的使用 
            5.2.1 建立畫刷
               CreateSolidBrush          - 建立實心的畫刷
               HBRUSH CreateSolidBrush( 
                  COLORREF crColor
                  //畫刷的顏色
                ); //建立成功,返回畫刷的控制代碼


               CreateHatchBrush          - 建立陰影畫刷
               HBRUSH CreateHatchBrush(
                   int      fnStyle,
                   //陰影樣式
                   COLORREF clrref
                   //畫刷的顏色
                );//建立成功,返回畫刷的控制代碼


               CreatePatternBrush        - 建立點陣圖畫刷   
               HBRUSH CreatePatternBrush( 
                  HBITMAP hbmp
                  //點陣圖控制代碼
                );//建立成功,返回畫刷的控制代碼

               //載入點陣圖
              HBITMAP LoadBitmap( 
                  HINSTANCE hInstance, 
                    //應用程式例項控制代碼
                  LPCTSTR lpBitmapName
                    //字串資源ID
                );//返回點陣圖控制代碼


            5.2.2 將畫刷應用到DC中  
                    - SelectObject  


            5.2.3 繪圖


            5.2.4  取出DC中的畫刷    
                -  SelectObject


            5.2.5  釋放畫刷
                -  DeleteObject    

        5.3 其它
          可以使用GetStockObject函式獲取系統的畫刷,畫筆等           

          如果我們不使用畫刷填充,需要使用NULL_BRUSH引數,獲取不填充的畫刷

          GetStockObject返回的畫刷不需要釋放


 6  GDI繪圖物件        - 點陣圖 
      6.1 點陣圖相關
          光柵圖形    -  記錄每個點的顏色等資訊
          向量圖形    -  記錄影象的演算法,繪圖的指令

          HBITMAP      - 點陣圖控制代碼

     6.2 點陣圖的使用
          6.2.1 新增點陣圖資源

          6.2.2 載入點陣圖資源 

          6.2.3  建立一個與當前DC相匹配的DC
                 HDC CreateCompatibleDC( 
                      HDC hdc 
                      //當前的繪圖裝置,可以為NULL (使用螢幕DC)
                    ); //返回記憶體DC控制代碼

                為什麼要弄一個記憶體DC?
                為了不讓使用者看見成像的過程,提升使用者體驗 

          6.2.4 將點陣圖應用記憶體DC (記憶體DC得到點陣圖的時候,就將這個點陣圖繪製在虛擬區域中)
                SelectObject


          6.2.5 繪製點陣圖(成像)     

               BOOL BitBlt(         //1:1成像
                   HDC   hdcDest,   //目標DC
                   int   nXDest,    //目標的左上角的x座標
                   int   nYDest,    //目標的左上角的y座標
                   int   nWidth,    //目標的寬度    (成像多少圖形)
                   int   nHeight,   //目標的高度
                   HDC   hdcSrc,    //源DC
                   int   nXSrc,     //源的左上角的x座標
                   int   nYSrc,     //源的左上角的y座標
                   DWORD dwRop      //繪製方法  
                );

               BOOL StretchBlt(     //縮放成像
                  HDC hdcDest,      //目標DC 
                  int nXOriginDest, //目標的左上角的x座標  
                  int nYOriginDest, //目標的左上角的y座標
                  int nWidthDest,   //目標的寬度
                  int nHeightDest,  //目標的高度
                  HDC hdcSrc,       //源DC
                  int nXOriginSrc,  //源的左上角的x座標 
                  int nYOriginSrc,  //源的左上角的y座標
                  int nWidthSrc,    //源DC寬     (拷貝多少圖形)
                  int nHeightSrc,   //源DC高
                  DWORD dwRop       //繪製方法
                );

          6.2.6 取出點陣圖
               SelectObject

          6.2.7 釋放點陣圖
              DeleteObject

          6.2.8 釋放記憶體DC
              DeleteDC            


     6.3 其它

        使用GetObject  獲取點陣圖資訊       
          int GetObject(
            HGDIOBJ hgdiobj,
            //繪圖物件的控制代碼
            int     cbBuffer,
            //緩衝區的大小
           LPVOID  lpvObject
           //緩衝區
        );

        BITMAP 點陣圖資訊的結構
        /* Bitmap Header Definition */
            typedef struct tagBITMAP
              {
                LONG        bmType;
                LONG        bmWidth;
                LONG        bmHeight;
                LONG        bmWidthBytes;
                WORD        bmPlanes;
                WORD        bmBitsPixel;
                LPVOID      bmBits;
              } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;

Lesson 12

十一、座標系
1. 座標系的分類

   1.1 裝置座標系(以顯示器為例)

      以畫素為單位,裝置的左上角為原點,X軸右為正,Y軸下為正的座標系

      1.1.1 螢幕座標系
            - 以當前顯示器的左上角為原點

      1.1.2 視窗座標系
            - 以當前視窗的左上角為原點

      1.1.3 視窗客戶區座標系
            - 以當前視窗的客戶區左上角為原點


   1.2 邏輯座標系(計算機的是邏輯座標系)
        在GDI繪圖中,使用的是邏輯座標繪圖


2 座標的對映關係
   2.1 對映模式
        邏輯座標和裝置座標之間的對映關係 (1邏輯單位=幾個裝置單位)

        裝置座標的單位由裝置自己決定,大小固定(顯示器的畫素,印表機1/1440英寸)  


        邏輯座標的單位可以通過程式設定 

        int SetMapMode(
           HDC hdc, //DC控制代碼
           int fnMapMode //新的對映模式
        );//返回舊的對映模式


    MM_TEXT                  - 1個邏輯單位 = 1個裝置單位(預設預設)(x軸右為正,y軸下為正)   
    MM_HIENGLISH             - 1個邏輯單位 = 0.001英寸(x軸右為正,y軸上為正)     
    MM_LOENGLISH             - 1個邏輯單位 = 0.01英寸 (x軸右為正,y軸上為正)
    MM_HIMETRIC              - 1個邏輯單位 = 0.01毫米 (x軸右為正,y軸上為正) 
    MM_LOMETRIC              - 1個邏輯單位 = 0.1毫米  (x軸右為正,y軸上為正) 
    MM_TWIPS                 - 1個邏輯單位 = 1/1440   (x軸右為正,y軸上為正) (可以用來列印預覽)

    邏輯單位轉換成具有任意比例的任意單位
    MM_ISOTROPIC             - 1個邏輯單位 = 自定義

    MM_ANISOTROPIC           
                             X軸的1個邏輯單位 = 自定義1
                             Y軸的1個邏輯單位 = 自定義2

    用SetWindowExtEx 和 SetViewportExtEx 函式可指定單位、方向和比例

              BOOL SetWindowExtEx(
                    HDC    hdc,
                    //DC控制代碼
                    int    nXExtent,        1
                    //x軸的邏輯比例
                    int    nYExtent,        1
                    //y軸的邏輯比例
                    LPSIZE lpSize
                    //原來的比例
                );



            BOOL SetViewportExtEx(
                    HDC    hdc,
                    //DC控制代碼
                    int    nXExtent,
                    //x軸的裝置比例         2
                    int    nYExtent,
                    //y軸的裝置比例         3
                    LPSIZE lpSize
                    //原來的比例
                );

十二、文字和字型
1 繪製文字
1.1 TextOut - 將文字繪製到指定的位置
1.2 DrawText - 將文字繪製到矩形區域內

        int DrawText(    
           HDC     hDC,         //DC控制代碼
           LPCTSTR lpchText,    //字串BUFF
           int     nCount,      //字串長度
           LPRECT  lpRect,      //矩形區域BUFF
           UINT    uFormat      //繪製方式
        );


       BOOL ExtTextOut( 
          HDC hdc,               //DC控制代碼
          int X,                 //字串的x座標
          int Y,                 //字串Y座標
          UINT fuOptions,        //輸出選項(基本不用,給0就可以)
          const RECT* lprc,      //輸出矩形區域(基本不用,給NULL)
          LPCTSTR lpString,      //字串的BUFF
          UINT cbCount,          //字串的長度
          const int* lpDx        //字元的間距陣列
        ); 

      注:字元間距是上一個字元的開始到下一個字元開始之間的距離      


2 文字的顏色和背景  

    文字的顏色的設定
    COLORREF SetTextColor(
        HDC hdc,          
        COLORREF crColor    //要設定的文字的顏色
    );


    文字的背景顏色的設定
    COLORREF SetBkColor(
        HDC hdc,          
        COLORREF crColor    //要設定的文字的顏色
    );//執行成功,返回舊文字的背景顏色


    文字的背景模式
    int SetBkMode(
       HDC hdc,
       int iBkMode //背景模式 OPAQUE/TRANSPARENT 不透明/透明
    );

    注:透明時SetBkColor失效



3 字型 ( GDI繪圖物件 )
    3.1 字型相關    
       字型名:  標識字型的型別
       HFONT    - 字型控制代碼


    3.2 字型的使用
      3.2.1 建立字型 CreateFont
            HFONT CreateFont(
               int     nHeight,            //字型的高度
               int     nWidth,             //字型的寬度
               int     nEscapement,        //字型的切斜度(以度為單位)
               int     nOrientation,       //字型的旋轉度(二維程式設計看不出效果)
               int     fnWeight,           //字型的粗度
               DWORD   fdwItalic,          //是否是斜體(TRUE 是,FALSE否)
               DWORD   fdwUnderline,       //是否有下劃線
               DWORD   fdwStrikeOut,       //是否有刪除
               DWORD   fdwCharSet,         //字符集(漢語作業系統定死GB2312_CHARSET)
               DWORD   fdwOutputPrecision, //輸出精度(基本無效 置0)
               DWORD   fdwClipPrecision,   //裁剪精度(基本無效 置0)
               DWORD   fdwQuality,         //輸出質量(基本無效 置0)
               DWORD   fdwPitchAndFamily,  //匹配字型(基本無效 置0)
               LPCTSTR lpszFace            //字型名稱
            );//返回建立的字型的控制代碼


    3.2.2 將字元應用到DC中
          SelectObject

    3.2.3 繪製文字

    3.2.4 從DC中取出字型
           SelectObject 

    3.2.5 釋放字型
          DeleteObject

十三 對話方塊
1 對話方塊的分類
1.1 模式(態)對話方塊 - 當對話方塊顯示時,會禁止本程序的其它視窗和使用者
進行互動操作

      1.2  非模式(態)對話方塊      -  當對話方塊顯示時,其它視窗同樣可以和使用者進行互動操作 


      模式對話方塊和非模式對話方塊的建立和銷燬完成不同



  2 對話方塊的基本使用
    2.1   對話方塊的視窗處理函式


    2.2   建立對話方塊

    2.3   對話方塊的關閉


  3 模式對話方塊的使用
       3.1 對話方塊的處理函式 DialogProc (並非真正的對話方塊處理函式)     

          BOOL CALLBACK DigLogProc(
            HWND hwndDlg,    //對話方塊的視窗控制代碼
            UINT uMsg,       //訊息ID
            WPARAM wParam,   //訊息附帶引數1
            LPARAM lParam    //訊息附帶引數2
          );

         對話方塊的處理函式的呼叫和普通的視窗不同

         普通的視窗處理函式是自定義呼叫預設
          WindowProc(.......)
          {

                return DefWindowProc(.....);
          }           


          對話方塊處理函式是預設呼叫自定義
          SysDlgProc(...)
          {
              ....;                   //區分是哪個對話方塊的訊息,
                                      //並呼叫相應的自定義的處理函式

              if ( DialogProc )
                return;

             ......;                   //預設的各種訊息的預設處理
          }


          返回FALSE    - 表示DialogProc沒有處理這個訊息
                         交給預設處理函式去處理

          返回TRUE     - 表示DialogProc處理了這個訊息
                         直接返回,預設的處理函式不處理


        3.2 建立模式對話方塊
           int DialogBox( 
              HINSTANCE hInstance,   //應用程式例項控制代碼
              LPCTSTR lpTemplate,    //對話方塊字串資源ID
              HWND hWndParent,       //父視窗控制代碼
              DLGPROC lpDialogFunc   //自定義的對話方塊處理函式
            ); 

            需要新增對話方塊資源;
            DialogBox是一個阻塞函式,只有當對話方塊關閉後才會返回,
            繼續執行後續程式碼;
            返回值由EndDialog指定

        3.3 模式對話方塊的關閉    
            BOOL EndDialog(  //銷燬對話方塊同時讓DialogBox返回
              HWND hDlg,     //對話方塊控制代碼
              int nResult    //指定DialogBox函式的返回值
            ); 

            注:關閉模式對話方塊只能用EndDialog函式,不能使用DestroyWindow函式。
                DestroyWindow雖然能銷燬視窗,但是不能讓DialogBox返回

        3.4 對話方塊的訊息
             對話方塊沒有WM_CREATE訊息,取而代之的是 WM_INITDIALOG

             WM_INITDIALOG  - 對話方塊建立成功,但還未顯示之前產生,
                              可以完成自己的初始化工作       

    4. 非模式對話方塊
         4.1 對話方塊的處理函式(與模式對話方塊處理函式一樣)


         4.2 建立非模式對話方塊           

            HWND CreateDialog( 
              HINSTANCE hInstance,  //應程式例項控制代碼
              LPCTSTR lpTemplate,   //對話方塊字串資源ID
              HWND hWndParent,      //父視窗
              DLGPROC lpDialogFunc  //視窗處理函式
            );  

           非阻塞函式,建立成功返回對話方塊視窗控制代碼,
           需要使用ShowWindow函式顯示對話方塊


        4.3 非模式對話方塊的關閉
             關閉時使用DestroyWindow銷燬視窗,不要使用EndDialog關閉非模式對話方塊


    5 對話方塊VS普通視窗
       5.1 建立
            模式對話方塊       - DialogBox,阻塞函式        
            無模式對話方塊     - CreateDialog
            普通視窗         - CreateWindow/CreateWindowEx

       5.2 視窗處理函式
           對話方塊            - DialogProc(並非真正的對話方塊處理函式) 
           普通視窗          - WindowProc,需要呼叫預設視窗處理函式 

       5.3 視窗訊息
            普通視窗         - WM_CREATE
            對話方塊           - WM_INITDIALOG

       5.4 視窗關閉
             模式對話方塊               - EndDialog
             無模式對話方塊/普通視窗    -DestroyWindow 

Lesson13

十四、子控制元件
1. 子控制元件相關
系統已經定義(註冊)的視窗型別,相應的處理函式都已經有系統完成。
例如:按鈕,檔案編輯框等等

 2. 子控制元件的建立
     不需要註冊,直接使用CreateWindow/CreateWindowEx函式建立該類的視窗。
     子控制元件建立時,每個控制元件都有唯一的ID。


 3. 控制元件的訊息
      程式和控制元件的互動,通過訊息完成

      3.1 控制元件的視窗訊息
           程式設計師可以使用SendMessage函式,向控制元件傳送訊息,
           獲取控制元件的資訊和設定控制元件的狀態             

      3.2  控制元件的通知訊息
            控制元件有相應的事件發生後,會向父視窗傳送通知訊息(WM_COMMAND),
            父視窗根據控制元件ID,做相應的處理

十五、靜態框
1. 靜態框的分類
文字靜態框 - 顯示文字
圖示靜態框 - 顯示圖示 設定SS_ICON/SS_BITMAP

   2.靜態框作用
     作用:顯示文字或影象,類名"STATIC"  

   3.靜態框的使用
      3.1 建立
         3.1.1 函式CreateWindow/CreateWindowEx函式

         3.1.2 風格
             圖示靜態框使用SS_ICON/SS_BITMAP風格
             如果要建立圖示靜態框,那麼視窗名稱引數要設定為圖示或者點陣圖的ID