一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - C/C++ - Windows程序內(nèi)部運(yùn)行機(jī)制實(shí)例詳解

Windows程序內(nèi)部運(yùn)行機(jī)制實(shí)例詳解

2021-01-27 12:06C語(yǔ)言程序設(shè)計(jì) C/C++

這篇文章主要介紹了Windows程序內(nèi)部運(yùn)行機(jī)制實(shí)例詳解,對(duì)于學(xué)習(xí)Windows程序設(shè)計(jì)來(lái)說(shuō)是非常重要的一課,需要的朋友可以參考下

本文以孫鑫老師VC++教程中的程序為基礎(chǔ),詳細(xì)講解了Windows程序內(nèi)部運(yùn)行機(jī)制,相信可以幫助大家更好的理解Windows程序運(yùn)行原理及相應(yīng)的VC++程序設(shè)計(jì)。具體內(nèi)容如下:

創(chuàng)建一個(gè)Win32應(yīng)用程序步驟:

1、編寫WinMain函數(shù);

2、創(chuàng)建窗口(步驟如下):

 a、設(shè)計(jì)(一個(gè))窗口類(WNDCLASS)

 b、注冊(cè)(該)窗口類。

 c、創(chuàng)建窗口。

 d、顯示并更新窗口。

3、編寫消息循環(huán)。

4、編寫窗口過(guò)程函數(shù)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//WinMain.cpp
#include <windows.h>
#include <stdio.h>
 
LRESULT CALLBACK WinAzeProc(
   HWND hwnd,   // handle to window
   UINT uMsg,   // message identifier
   WPARAM wParam, // first message parameter
   LPARAM lParam  // second message parameter
   );
 
int WINAPI WinMain(
          HINSTANCE hInstance,   // handle to current instance
          HINSTANCE hPrevInstance, // handle to previous instance
          LPSTR lpCmdLine,     // command line
          int nCmdShow       // show state
          )
{
  //設(shè)計(jì)一個(gè)窗口類
  WNDCLASS wndcls;
  wndcls.cbClsExtra = 0;
  wndcls.cbWndExtra = 0;
  wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);
  wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);
  wndcls.hInstance = hInstance;  //應(yīng)用程序?qū)嵗浔蒞inMain函數(shù)傳進(jìn)來(lái)
  wndcls.lpfnWndProc = WinAzeProc;
  wndcls.lpszClassName = "aze_003";
  wndcls.lpszMenuName = NULL;
  wndcls.style = CS_HREDRAW | CS_VREDRAW;
 
  RegisterClass(&wndcls);  //注冊(cè)窗口類
  
  //創(chuàng)建窗口,定義一個(gè)變量用來(lái)保存成功創(chuàng)建后返回的句柄
  HWND hwnd; 
  hwnd = CreateWindow("aze_003", "first Application", WS_OVERLAPPEDWINDOW, 0, 0, 600, 500, NULL, NULL,hInstance, NULL);
 
  ShowWindow(hwnd, SW_SHOWNORMAL);  //顯示窗口
  UpdateWindow(hwnd);    //刷新窗口
 
  //定義消息結(jié)構(gòu)體,開始消息循環(huán)
  MSG msg;
  while( GetMessage(&msg, NULL, 0, 0) )
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}
 
//編寫窗口過(guò)程函數(shù)
LRESULT CALLBACK WinAzeProc(
   HWND hwnd,   // handle to window
   UINT uMsg,   // message identifier
   WPARAM wParam, // first message parameter
   LPARAM lParam  // second message parameter
   )
{
  switch(uMsg)
  {
  case WM_CHAR:
    char szChar[20];
    sprintf(szChar, "char code is %d", wParam);
    MessageBox(hwnd, szChar, "char", 0);
    break;
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, "mouse clicked", "message", 0);
    HDC hdc;
    hdc = GetDC(hwnd);    //不能在響應(yīng)WM_PAINT消息時(shí)調(diào)用
    TextOut( hdc, 0, 50, "程序員之家!",strlen("程序員之家!") );
    ReleaseDC(hwnd, hdc);
    break;
  case WM_PAINT:
    HDC hDC;
    PAINTSTRUCT ps;
    hDC = BeginPaint(hwnd, &ps);  //BeginPaint只能在響應(yīng)WM_PAINT消息是調(diào)用
    TextOut(hDC, 0, 0, "http://www.sunxin.org", strlen("http://www.sunxin.org"));
    EndPaint(hwnd, &ps);
    break;
  case WM_CLOSE:
    if( IDYES == MessageBox(hwnd, "是否真的退出?", "message", MB_YESNO) )
    {
      DestroyWindow(hwnd);
    }
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
  }
  return 0;
}

程序運(yùn)行后顯示界面如下:

Windows程序內(nèi)部運(yùn)行機(jī)制實(shí)例詳解

窗口分為客戶區(qū)(是窗口的一部分)與非客戶區(qū)。

標(biāo)題欄、菜單欄、系統(tǒng)菜單、最小(大)化框、可調(diào)邊框統(tǒng)稱為窗口的非客戶區(qū),由Windows系統(tǒng)管理;應(yīng)用程序主要管理客戶區(qū)的外觀及操作(顯示文字、繪制圖形)。

對(duì)話框、消息框也是一種窗口;對(duì)話框上還包括許多子窗口:按鈕、單選按鈕、復(fù)選框、組狂、文本編輯框等。

2、窗口與句柄:

在Windows應(yīng)用程序中,窗口是通過(guò)窗口句柄(HWND)來(lái)標(biāo)識(shí)的;要對(duì)某個(gè)窗口進(jìn)行操作,就必須要得到這個(gè)窗口的句柄。

句柄是Windows程序中一個(gè)重要的概念(圖標(biāo)句柄(HICON)、光標(biāo)句柄(HCURSOR)、畫刷句柄(HBRUSH))。

3、消息與消息隊(duì)列:

Windows程序設(shè)計(jì)模式是一種事件驅(qū)動(dòng)方式的程序設(shè)計(jì)模式,主要是基于消息的。(當(dāng)系統(tǒng)感知到一事件時(shí)(如點(diǎn)擊鼠標(biāo)),系統(tǒng)會(huì)將這個(gè)事件包裝成一個(gè)消息,投遞到應(yīng)用程序的消息隊(duì)列中,然后應(yīng)用程序從消息隊(duì)列中取出消息并進(jìn)行響應(yīng)。在這個(gè)處理過(guò)程中,操作系統(tǒng)也會(huì)給應(yīng)用程序“發(fā)送消息”。“發(fā)送消息”:實(shí)際指:操作系統(tǒng)調(diào)用程序中一個(gè)負(fù)責(zé)處理消息的窗口過(guò)程函數(shù))

(1)消息:Windows中,消息由MSG結(jié)構(gòu)體表示,如下: 

?
1
2
3
4
5
6
7
8
9
10
//The MSG structure contains message information from a thread's message queue.
 
typedef struct tagMSG {
 HWND  hwnd;     //消息所屬的窗口,消息都是與窗口相關(guān)聯(lián)的
 UINT  message;   //the message identifier
 WPARAM wParam;    //指定消息的附加消息
 LPARAM lParam;    //指定消息的附加消息
 DWORD time;     //消息投遞到隊(duì)列中的時(shí)間
 POINT pt;      //鼠標(biāo)的當(dāng)前位置
} MSG, *PMSG;

Windows中,消息是由一個(gè)個(gè)數(shù)值表示的;Windows將消息對(duì)應(yīng)的數(shù)值定義為WM_XXX宏(WM:Window Message)的形式,XXX對(duì)應(yīng)某種消息的英文拼寫的大寫形式。如:WM_LBUTTONDOWN:鼠標(biāo)左鍵按下消息、WM_KEYDOWN:鍵盤按下消息、WM_CHAR:字符消息···

(2)消息隊(duì)列:每一個(gè)Windows應(yīng)用程序開始執(zhí)行后,系統(tǒng)都會(huì)為改程序創(chuàng)建一個(gè)消息隊(duì)列,這個(gè)消息隊(duì)列用來(lái)存放改程序創(chuàng)建的窗口的消息。

(3)進(jìn)隊(duì)消息 與 不進(jìn)隊(duì)消息:

      進(jìn)隊(duì)的消息將由系統(tǒng)放入到應(yīng)用程序的消息隊(duì)列中,然后由應(yīng)用程序取出并發(fā)送;

      不進(jìn)隊(duì)消息在系統(tǒng)調(diào)用窗口過(guò)程時(shí),直接發(fā)送給窗口;

      兩者最終都是有系統(tǒng)調(diào)用窗口過(guò)程函數(shù)對(duì)消息進(jìn)行處理。

4、WinMain函數(shù)

(一)MSDN上的WinMain函數(shù)定義如下(備有詳盡的注釋):

?
1
2
3
4
5
6
7
8
//The WinMain function is called by the system as the initial entry point for a Windows-based application.
 
int WINAPI WinMain(
 HINSTANCE hInstance,   // handle to current instance當(dāng)前窗口句柄
 HINSTANCE hPrevInstance, // handle to previous instance前一個(gè)打開的窗口句柄
 LPSTR lpCmdLine,     // command line 指定傳遞給應(yīng)用程序的*命令行*參數(shù)
 int nCmdShow       // show state 指定窗口應(yīng)該如何顯示,如:最大(小)化、隱藏等
);

(二)窗口類的結(jié)構(gòu)體的定義:

(1)本文程序中對(duì)應(yīng)代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct _WNDCLASS {
  UINT    style;    //指定*這一類型*窗口的樣式,如:CS_HREDRAW、CS_VREDRAW、CS_NOCLOSE、CS_DBLCLKS
  WNDPROC  lpfnWndProc;   //函數(shù)指針,指向窗口過(guò)程函數(shù)(窗口過(guò)程函數(shù)是一回調(diào)函數(shù))
  int    cbClsExtra;   //一般為0
  int    cbWndExtra;   //同上
  HINSTANCE hInstance;   //指定包含窗口過(guò)程的程序的實(shí)例句柄
  HICON   hIcon;     //指定窗口類的圖標(biāo)句柄
  HCURSOR  hCursor;   //指定窗口類的光標(biāo)句柄
  HBRUSH   hbrBackground;   //指定窗口類的背景畫刷句柄;當(dāng)窗口發(fā)生重繪值,系統(tǒng)使用這里指定的畫刷來(lái)查處窗口的背景
  LPCTSTR  lpszMenuName;   //指定菜單資源的名字 **菜單并不是一個(gè)窗口**
  LPCTSTR  lpszClassName;   //指定窗口類的名字
} WNDCLASS, *PWNDCLASS;

回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用,而是在特定的事件或條件發(fā)生時(shí)有另一方調(diào)用的,用于該事件或條件進(jìn)行響應(yīng)。

回調(diào)函數(shù)的實(shí)現(xiàn)機(jī)制是:

    ①定義一個(gè)回調(diào)函數(shù)

    ②提供函數(shù)實(shí)現(xiàn)的一方在初始化的時(shí)候,將回調(diào)函數(shù)的函數(shù)指針注冊(cè)給調(diào)用者

    ③當(dāng)特定的事件或條件發(fā)生的時(shí)候,調(diào)用者使用函數(shù)指針調(diào)用回調(diào)函數(shù)對(duì)事件進(jìn)行處理

針對(duì)Windows的消息處理機(jī)制,窗口過(guò)程函數(shù)被調(diào)用的過(guò)程如下:

    ①在設(shè)計(jì)窗口類的時(shí)候,將窗口過(guò)程函數(shù)的地址賦值給lpfnWndProc成員變量;

    ②調(diào)用RegisterClass(&wndclass)注冊(cè)窗口類,那么系統(tǒng)就有了我們所編寫的窗口過(guò)程函數(shù)的地址。

    ③當(dāng)應(yīng)用程序接收到某一窗口的消息時(shí),調(diào)用DispatchMessage(&msg)將對(duì)消息回傳給系統(tǒng)。系統(tǒng)則利用先前注冊(cè)窗口類時(shí)得到的函數(shù)指針,調(diào)用窗口過(guò)程函數(shù)對(duì)消息進(jìn)行處理。

提示:一個(gè)Windows程序可以包含多個(gè)窗口過(guò)程函數(shù),一個(gè)窗口過(guò)程總是與某一個(gè)特定的窗口類相關(guān)聯(lián)(通過(guò)WNDCLASS結(jié)構(gòu)體中的lpfnWndProc成員變量指定),基于該窗口類創(chuàng)建的窗口使用同一個(gè)窗口過(guò)程

lpfnWndProc成員變量的類型是WNDPROC,定義如下:

?
1
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM); //LRESULT=long, CALLBACK=_stdcall WNDPROC是函數(shù)指針類型。

注意:WNDPROC被定義為指向窗口過(guò)程函數(shù)的指針類型,窗口過(guò)程函數(shù)的格式必須與WNDPROC相同。

在VC++中,資源是通過(guò)標(biāo)識(shí)符(ID)來(lái)標(biāo)識(shí)的,同一個(gè)ID可以標(biāo)識(shí)多個(gè)不同的資源(資源的ID本質(zhì)上是一個(gè)整數(shù))。如:菜單資源:IDM_XXX(M表示Menu)、圖標(biāo)資源:IDI_XXX(I表示圖標(biāo))、按鈕資源:IDB_XXX(B表示Button)

可以調(diào)用GetStockObject(int fnObject) 來(lái)得到系統(tǒng)的標(biāo)準(zhǔn)畫刷。聲明如下:

?
1
2
3
4
5
//The GetStockObject function retrieves a handle to one of the stock pens, brushes, fonts, or palettes.
 
HGDIOBJ GetStockObject(
 int fnObject  // stock object type
);

GetStockObject函數(shù):返回多種資源對(duì)象的句柄,如:畫刷、畫筆、字體、調(diào)色板等;

函數(shù)返回時(shí),需進(jìn)行類型轉(zhuǎn)換。如:

?
1
wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

(2)注冊(cè)窗口類:設(shè)計(jì)窗口類(WNDCLASS)后,需要調(diào)用RegisterClass函數(shù)對(duì)其進(jìn)行注冊(cè),注冊(cè)成功后,才可以創(chuàng)建該類型的窗口。聲明如下:

?
1
2
3
4
ATOM RegisterClass(
 CONST WNDCLASS *lpWndClass // class data, 窗口類對(duì)象的指針
               // Pointer to a WNDCLASS structure. You must fill the structure with the appropriate class attributes before passing it to the function.
);

(3)創(chuàng)建窗口:CreateWindow函數(shù)聲明如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
HWND CreateWindow(
 LPCTSTR lpClassName, // registered class name 即:窗口類WNDCLASS的lpszClassName成員指定的名稱(必須先注冊(cè))
 LPCTSTR lpWindowName, // window name  指定窗口的名字
 DWORD dwStyle,    // window style 指定創(chuàng)建窗口的樣式 如:WS_OVERLAPPEDWINDOW
 int x,        // horizontal position of window
 int y,        // vertical position of window
 int nWidth,      // window width
 int nHeight,     // window height
 HWND hWndParent,   // handle to parent or owner window 指定被創(chuàng)建窗口的父窗口句柄
 HMENU hMenu,     // menu handle or child identifier
 HINSTANCE hInstance, // handle to application instance
 LPVOID lpParam    // window-creation data 作為WM_CREATE消息的附加參數(shù)lParam傳入的數(shù)據(jù)指針(一般為:NULL)
);

如果窗口創(chuàng)建成功,CreateWindow函數(shù)將返回系統(tǒng)為該窗口分配的句柄;否則,返回NULL

·注意:在創(chuàng)建窗口之前應(yīng)先定義一個(gè)窗口句柄變量來(lái)接收創(chuàng)建窗口之后的句柄值。

顯示及更新窗口:

(4)顯示窗口:ShowWindow聲明如下:

?
1
2
3
4
BOOL ShowWindow(
 HWND hWnd,   // handle to window 該參數(shù)為成功創(chuàng)建窗口后返回的那個(gè)窗口句柄
 int nCmdShow  // show state 如:SW_HIDE、SW_SHOW、SW_SHOWNORMAL、SW_SHOWMINIMIZED、SW_SHOWMAXIMIZED··
);

(5)更新(刷新)窗口:UpdateWindow函數(shù)聲明原型如下:

?
1
2
3
BOOL UpdateWindow(
 HWND hWnd  // handle to window 創(chuàng)建成功后的窗口句柄
);

UpdateWindow函數(shù)通過(guò)發(fā)送一個(gè)WM_PAINT消息來(lái)刷新窗口,UpdateWindow將WM_PAINT消息直接發(fā)送給了窗口過(guò)程函數(shù)進(jìn)行處理,而沒有放到消息隊(duì)列里面

(三)、消息循環(huán)

窗口 創(chuàng)建、顯示、更新后;需要編寫一個(gè)消息循環(huán),不斷的從消息隊(duì)列中取出消息,并進(jìn)行響應(yīng)。

GetMessage()函數(shù):從消息隊(duì)列中取出消息

?
1
2
3
4
5
6
BOOL GetMessage(
 LPMSG lpMsg,     // message information 指向一個(gè)消息(MSG)結(jié)構(gòu)體,GetMessage從線程的消息隊(duì)列中取出的消息信息將保存在該結(jié)構(gòu)體對(duì)象中
 HWND hWnd,      // handle to window 指定接收屬于哪一個(gè)窗口的消息;NULL:用于接收屬于調(diào)用線程的所有窗口的窗口消息
 UINT wMsgFilterMin, // first message 指定獲取打的消息的最小值
 UINT wMsgFilterMax  // last message 如果wMsgFilterMin=0和wMsgFilterMax=0,則接收所有消息
);

GetMessage函數(shù)接收到除WM_QUIT外的消息均返回非零值。

?
1
2
3
4
5
6
7
8
//消息循環(huán)代碼,一般形式
  MSG msg;
  while( GetMessage(&msg, NULL, 0, 0) )
  {
    TranslateMessage(&msg); //TranslateMessage函數(shù)將虛擬鍵消息*轉(zhuǎn)換*為字符消息,被投遞到調(diào)用線程的消息隊(duì)列中,當(dāng)下一次調(diào)用GetMessage函數(shù)時(shí)被取出
    DispatchMessage(&msg);  //DispatchMessage函數(shù)分派一個(gè)消息到窗口過(guò)程,有窗口過(guò)程函數(shù)對(duì)消息進(jìn)行處理
//DispatchMessage實(shí)際上是將消息會(huì)傳給操作系統(tǒng),有操作系統(tǒng)調(diào)用窗口過(guò)程函數(shù)對(duì)消息進(jìn)行處理(響應(yīng))
  }

Windows應(yīng)用程序的消息處理機(jī)制如下圖所示:

Windows程序內(nèi)部運(yùn)行機(jī)制實(shí)例詳解

Windows應(yīng)用程序的消息處理過(guò)程:

    (1)操作系統(tǒng)就收到應(yīng)用程序的窗口消息,將消息投遞到該應(yīng)用程序的消息隊(duì)列中

    (2)應(yīng)用程序在消息循環(huán)匯總調(diào)用GetMessage函數(shù)從消息隊(duì)列中取出一條一條的消息。取出消息后,應(yīng)用程序可以對(duì)消息進(jìn)行一些預(yù)處理,如:放棄對(duì)某些消息的響應(yīng),或者調(diào)用TranslateMessage產(chǎn)生新的消息。

    (3)應(yīng)用程序調(diào)用DisPatchMessage,將消息回傳給操作系統(tǒng)。消息是由MSG結(jié)構(gòu)體對(duì)象來(lái)表示的,其中就包含了接收消息的窗口的句柄。故:DisPatchMessage函數(shù)總能進(jìn)行正確的傳遞。

    (4)操作利用WNDCLASS結(jié)構(gòu)體的lpfnWndProc成員保存的窗口過(guò)程函數(shù)的指針調(diào)用窗口過(guò)程,對(duì)消息進(jìn)行處理(即“系統(tǒng)給應(yīng)用程序發(fā)送了消息”)。

補(bǔ)充:

  (1)從消息隊(duì)列中獲取消息還可以調(diào)用PeekMessage函數(shù),函數(shù)原型如下:

?
1
2
3
4
5
6
7
BOOL PeekMessage(
 LPMSG lpMsg,     // message information
 HWND hWnd,      // handle to window
 UINT wMsgFilterMin, // first message
 UINT wMsgFilterMax, // last message
 UINT wRemoveMsg   // removal options
);

前四個(gè)參數(shù)與GetMessage函數(shù)的參數(shù)作用相同;

最后一個(gè)參數(shù)指定消息獲取的方式;如果設(shè)為PM_NOREMOVE, 那么消息將不會(huì)從消息隊(duì)列中被移除;如果設(shè)為PM_REMOVE, 那么消息將從消息隊(duì)列中被移除(與GetMessage函數(shù)的行為一致)

  (2)發(fā)送消息可以使用SendMessage和PostMessage函數(shù)。

      SendMessage將消息直接發(fā)送給窗口,并調(diào)用該窗口的窗口過(guò)程進(jìn)行處理;在窗口過(guò)程對(duì)消息處理完畢后,該函數(shù)才返回(SendMessage發(fā)送的消息為不進(jìn)隊(duì)消息)。

      PostMessage函數(shù)將消息放入與創(chuàng)建窗口的線程相關(guān)聯(lián)的消息隊(duì)列后立即返回。

      PostThreadMessage函數(shù),用于向線程發(fā)送消息。

      對(duì)于線程消息,MSG結(jié)構(gòu)體中的hwnd成員為NULL。

(四)、編寫窗口過(guò)程函數(shù):用于處理發(fā)送給窗口的消息

?
1
2
3
4
5
6
LRESULT CALLBACK WindowProc(  //窗口過(guò)程函數(shù)的名字可以隨便取,如:WinAzeProc,但函數(shù)聲明與定義要一致;
 HWND hwnd,   // handle to window
 UINT uMsg,   // message identifier 消息代碼
 WPARAM wParam, // first message parameter 消息代碼的兩個(gè)附加值
 LPARAM lParam  // second message parameter
);

提示:系統(tǒng)通過(guò)窗口過(guò)程函數(shù)的地址(指針)來(lái)調(diào)用窗口過(guò)程函數(shù),而不是名字。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//編寫窗口過(guò)程函數(shù)
LRESULT CALLBACK WinAzeProc(
              HWND hwnd,   // handle to window
              UINT uMsg,   // message identifier
              WPARAM wParam, // first message parameter
              LPARAM lParam  // second message parameter
              )
{
  switch(uMsg)
  {
  case WM_CHAR:  //通過(guò)調(diào)用TranslateMessage函數(shù)轉(zhuǎn)換得到
    char szChar[20];
    sprintf(szChar, "char code is %d", wParam);
    MessageBox(hwnd, szChar, "char", 0);
    break;
  case WM_LBUTTONDOWN:
    MessageBox(hwnd, "mouse clicked!", "message", 0);
    HDC hdc;
    hdc = GetDC(hwnd);    //用hdc保存GetDC函數(shù)返回的與特定窗口相關(guān)聯(lián)的DC的句柄。
                //GetDC()不能在響應(yīng)WM_PAINT消息時(shí)調(diào)用
    TextOut( hdc, 0, 50, "程序員之家!",strlen("程序員之家!") );  //TextOut利用得到的DC句柄在指定的位置(0,50)出輸出一行文字
    ReleaseDC(hwnd, hdc);  //釋放hdc
    break;
  case WM_PAINT:  //當(dāng)窗口客服區(qū)的一部分或者全部變?yōu)?ldquo;無(wú)效”時(shí),系統(tǒng)會(huì)發(fā)送WM_PAINT消息,通知應(yīng)用程序重新繪制窗口
          //窗口剛創(chuàng)建時(shí),客戶區(qū)是無(wú)效狀態(tài),當(dāng)調(diào)用UpdateWindow函數(shù)時(shí),會(huì)發(fā)送WM_PAINT消息給窗口過(guò)程,對(duì)窗口進(jìn)行刷新
          //當(dāng)窗口從無(wú)到有、改變尺寸、最小化在恢復(fù)、被其他窗口遮蓋后在顯示時(shí),窗口的客戶區(qū)都將變?yōu)闊o(wú)效,此時(shí)系統(tǒng)會(huì)給應(yīng)用程序發(fā)送WM_PAINT消息,通知應(yīng)用程序重新繪制
          //提示:窗口大小發(fā)生變化時(shí),是否發(fā)生重繪,取決于WNDCLASS結(jié)構(gòu)體中style成員是否設(shè)置了CS_HREDRAW和CS_VREDRAW標(biāo)志
    HDC hDC;
    PAINTSTRUCT ps;    //ps用于接收繪制的信息
    hDC = BeginPaint(hwnd, &ps);  //BeginPaint只能在響應(yīng)WM_PAINT消息是調(diào)用
    TextOut(hDC, 0, 0, "http://www.sunxin.org", strlen("http://www.sunxin.org"));
    EndPaint(hwnd, &ps);
    break;
  case WM_CLOSE:
    if( IDYES == MessageBox(hwnd, "是否真的退出?", "message", MB_YESNO) )
    {
      DestroyWindow(hwnd);
    }
    break;
  case WM_DESTROY:
    PostQuitMessage(0);
    break;
  default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam); //DefWindowProc調(diào)用默認(rèn)的窗口過(guò)程,對(duì)應(yīng)用程序沒有處理的其他消息提供默認(rèn)處理。
//對(duì)于大多數(shù)的消息,應(yīng)用程序可以直接調(diào)用DefWindowProc函數(shù)進(jìn)行處理。
//在編寫窗口過(guò)程時(shí),應(yīng)將DefWindowProc函數(shù)的調(diào)用放到default語(yǔ)句中,并將該函數(shù)的返回值作為窗口過(guò)程函數(shù)的返回值。
  }
  return 0;
}

提示:要在窗口中輸出文字或者顯示圖形,需要用到設(shè)備描述表(Device ConText)。

設(shè)備描述表(簡(jiǎn)稱DC):

DC是一個(gè)包含設(shè)備(物理輸出設(shè)備,如顯示器、設(shè)備驅(qū)動(dòng)器)信息的結(jié)構(gòu)體,在Windows平臺(tái)下,所有的圖形操作都是利用DC來(lái)完成的。

第30、31行代碼:在調(diào)用BeginPaint時(shí),如果客戶區(qū)的背景還沒有被擦除,那么BeginPaint會(huì)發(fā)送WM_ERASEBKGND消息給窗口,系統(tǒng)就會(huì)使用WNDCLASS結(jié)構(gòu)體的hbrBackGround成員指定的畫刷來(lái)擦除背景。如果我們想要讓某個(gè)圖形時(shí)鐘在窗口中顯示,就應(yīng)該將圖形的繪制操作放到響應(yīng)WM_PAINT消息的代碼中,如TextOut()的位置。

第34-48行代碼:DestroyWindow函數(shù)在銷毀窗口后會(huì)向窗口過(guò)程發(fā)送WM_DESTROY消息。注意:此時(shí)窗口雖然銷毀了,但應(yīng)用程序并沒有退出。故:如果自己要控制程序是否退出,應(yīng)該在WM_CLOSE消息的響應(yīng)代碼中完成。

   對(duì)WM_CLOSE消息的響應(yīng)并不是必須的,如果應(yīng)用程序沒有對(duì)該消息進(jìn)行響應(yīng),系統(tǒng)將把這條消息傳給DefWindowProc函數(shù),而DefWindowProc函數(shù)則條用DestroyWindow函數(shù)來(lái)響應(yīng) 這條WM_CLOSE消息。

第40-42行代碼:DestroyWindow函數(shù)在銷毀窗口后,會(huì)給窗口過(guò)程發(fā)送WM_DESTROY消息, 然后在該消息的響應(yīng)代碼中調(diào)用PostQuitMessage函數(shù)。PostQuitMessage函數(shù)項(xiàng)應(yīng)用程序的消息隊(duì)列中投遞一條WM_QUIT消息并返回。GetMessage函數(shù)只有在收到WM_QUIT消息時(shí)才返回0,此時(shí)消息循環(huán)才結(jié)束,程序退成。

  想讓程序正常退出,我們必須響應(yīng)WM_DESTROY消息,并在消息響應(yīng)代碼中調(diào)用PostQuitMessage,向應(yīng)用程序的消息隊(duì)列中投遞WM_QUIT消息。傳遞給PostQuitMessage函數(shù)的參數(shù)值將作為WM_QUIT消息的wParam參數(shù),這個(gè)值通常用做WinMain函數(shù)的返回值。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 天天操精品视频 | 国产日韩欧美在线一区二区三区 | 免看一级一片一在线看 | www.日本黄色| 俄罗斯一级大片 | 天天干夜夜噜 | 暖暖免费观看高清在线 | 99精品国产高清自在线看超 | 亚洲AV国产福利精品在现观看 | 久久久久久久久女黄 | 亚洲国产成人在人网站天堂 | 欧美亚洲另类在线观看 | 国产在线观看色 | 毛片视频网站在线观看 | 成人欧美一区二区三区 | 桥本有菜作品在线 | 亚洲国产精品久久网午夜 | 思思91精品国产综合在线 | 国产在线拍 | 深夜在线观看网站 | 希望影院高清免费观看视频 | 国产未成女年一区二区 | 超碰成人在线播放 | 亚洲 欧美 制服 校园 动漫 | 青草娱乐极品免费视频 | 国产欧美精品一区二区三区四区 | 99热精品国产麻豆 | poronovideos极度变态 | 国产精品免费视频一区一 | 久久精品99国产精品日本 | 猥琐对着美女飞机喷到脸上 | 波多野结衣xxxx性精品 | 513热点网深夜影院影院诶 | 精品区2区3区4区产品乱码9 | 恩不要好大好硬好爽3p | 91九色国产porny | 日本韩国一区二区三区 | 国产成人久久久精品一区二区三区 | dyav午夜片| 草啪啪| 性吟网 |