C語言Windows程序設計 -> 第十一天 -> 使用鼠標


C語言Windows程序設計 -> 第十一天 -> 使用鼠標

 


鼠標的使用同樣是通過獲取Windows鼠標消息來獲取用戶當前的鼠標狀態的。

一、鼠標的介紹
    鼠標是計算機的輸入設備之一, 在圖形化的操作系統上, 鼠標的使用使一些復雜的操作變得簡單, 隨着科技的進步, 鼠標的種類也越來越多, 按接口類型可分為串行鼠標、PS/2鼠標、總線鼠標、USB鼠標(多為光電鼠標)四種。按其工作原理及其內部結構的不同可以分為機械式,光機式和光電式。
    
    這里我們不討論鼠標的硬件構造, 更多關於鼠標的硬件知識請自行查閱相關資料。
    
    1>. 鼠標所在的位置
        在Windows系統下, 用戶移動鼠標時, 在屏幕上一般會以一個斜式的箭頭來表示鼠標當前的位置, 這個箭頭實際上是一個位圖格式的小圖標, 稱為"鼠標指針", 鼠標指針具有一個單像素精度的"熱點"(hot spot), 當鼠標樣式為箭頭時, 這個"熱點"就是鼠標箭頭的頂點, 還有一些樣式是"十"字樣式, 這樣的指針"熱點"位於"十"字的中心位置, 熱點在顯示設備上指示了一個精確的位置。 當我們去捕獲鼠標指針的位置時, 實際上是指鼠標指針的這個"熱點"所在的像素單元的位置。
    
    2>. 鼠標的術語
        ①. 單擊 : 按下鼠標按鍵, 然后松開;
        ②. 雙擊 : 連續快速的按下鼠標同一個按鍵然后松開;
        ③. 拖動 : 保持按鍵按下狀態, 並移動鼠標。
        
        現在我們常見的三鍵鼠標, 三個按鍵分布稱為左鍵、中鍵和右鍵, 其中左鍵的標識符簡寫為LBUTTON, 中鍵的標識符為MBUTTON, 右鍵的標識符為RBUTTON。 雙鍵鼠標只有左鍵和右鍵, 單鍵鼠標只有左鍵。
        
    3>. 鼠標的樣式
        Windows系統為鼠標提供了幾種默認的鼠標樣式, 如: 箭頭、沙漏、十字瞄准等, 在以前學習的過程中實際上我們已經接觸了使用默認的鼠標樣式, 回憶這行代碼:

        wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;

        這樣就是使用一個默認的斜式箭頭作為鼠標的指針樣式, 斜式箭頭樣式的標識符為 IDC_ARROW, 這些標識符定義在 WINUSER.H 頭文件中, 此外還有以下標識符及其對應的樣式:



二、使用鼠標的簡單示例
    1>. 示例一: 獲取鼠標指針位置
        在這個示例中演示如何獲取鼠標的位置, 先說下相關的消息標識符以及函數。
        消息標識符: WM_MOUSEMOVE 當鼠標指針在客戶區內移動或鼠標指針經過客戶區窗口時會得到這個消息。
        獲取鼠標位置的函數: GetCursorPos 該函數的原型: BOOL GetCursorPos(LPPOINT lpPoint) ;
        代碼片段:

 1     switch(message)
 2     {
 3     case WM_PAINT:        //處理重繪消息
 4         hdc = BeginPaint( hwnd, &ps ) ;
 5         wsprintf( szBuffer,  "屏幕坐標:(%i, %i)", pt.x, pt.y );
 6         TextOut( hdc, 10, 10, szBuffer, lstrlen(szBuffer) ) ;
 7         ScreenToClient( hwnd, &pt ) ;        //將相對於屏幕的坐標轉換為相對於窗口客戶區的坐標
 8         wsprintf( szBuffer,  "客戶區坐標:(%i, %i)", pt.x, pt.y );
 9         TextOut( hdc, 10, 30, szBuffer, lstrlen(szBuffer) ) ;
10         EndPaint( hwnd, &ps ) ;
11         return 0 ;
12 
13     case WM_MOUSEMOVE:        //處理鼠標移動時發來的消息
14         GetCursorPos(&pt) ;
15         InvalidateRect( hwnd, NULL, TRUE ) ;
16         return 0 ;

    完整的示例代碼:

View Code - GetCursorPosition
 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( "UseMouse_Demo" ) ;
 8     HWND hwnd ;
 9     MSG msg ;
10     WNDCLASS wndclass ;
11 
12     wndclass.hInstance        = hInstance ;
13     wndclass.lpfnWndProc    = WndProc ;
14     wndclass.lpszClassName    = szAppName ;
15     wndclass.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
16     wndclass.hbrBackground    = (HBRUSH) GetStockObject( WHITE_BRUSH ) ;
17     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;
18     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;
19     wndclass.cbClsExtra        = 0 ;
20     wndclass.cbWndExtra        = 0 ;
21     wndclass.lpszMenuName    = 0 ;
22 
23     if( !RegisterClass(&wndclass) )
24     {
25         MessageBox( NULL, TEXT("錯誤, 無法注冊窗口類."), TEXT("錯誤"), MB_OK ) ;
26         return 0 ;
27     }
28 
29     hwnd = CreateWindow( szAppName, TEXT("獲取鼠標指針位置 - Demo"),
30         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
31         CW_USEDEFAULT, CW_USEDEFAULT,
32         NULL, NULL, hInstance, NULL ) ;
33 
34     ShowWindow( hwnd, iCmdShow ) ;
35     UpdateWindow( hwnd ) ;
36 
37     while( GetMessage(&msg, NULL, 0, 0) )
38     {
39         TranslateMessage( &msg ) ;
40         DispatchMessage( &msg ) ;
41     }
42 
43     return msg.wParam ;
44 }
45 
46 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
47 {
48     HDC hdc ;
49     PAINTSTRUCT ps ;
50     static POINT pt ;
51     TCHAR szBuffer[128] ;
52 
53     switch(message)
54     {
55     case WM_PAINT:
56         hdc = BeginPaint( hwnd, &ps ) ;
57         wsprintf( szBuffer,  "屏幕坐標:(%i, %i)", pt.x, pt.y );
58         TextOut( hdc, 10, 10, szBuffer, lstrlen(szBuffer) ) ;
59         ScreenToClient( hwnd, &pt ) ;
60         wsprintf( szBuffer,  "客戶區坐標:(%i, %i)", pt.x, pt.y );
61         TextOut( hdc, 10, 30, szBuffer, lstrlen(szBuffer) ) ;
62         EndPaint( hwnd, &ps ) ;
63         return 0 ;
64 
65     case WM_MOUSEMOVE:
66         GetCursorPos(&pt) ;
67         InvalidateRect( hwnd, NULL, TRUE ) ;
68         return 0 ;
69 
70     case WM_DESTROY:
71         PostQuitMessage(0) ;
72         return 0 ;
73     }
74 
75     return DefWindowProc( hwnd, message, wParam, lParam ) ;
76 }

        說一下整體的思路, 要即時跟蹤獲取鼠標在屏幕中的坐標, 首先要捕獲鼠標的移動消息 WM_MOUSEMOVE, 當Windows向我們發來這個消息時就代碼鼠標在進行移動, 隨后我們對這個鼠標移動消息進行處理, 調用 GetCursorPos(&pt) ; 這個函數獲取鼠標現在的位置, 獲取到鼠標位置后為了能夠立即在窗口中顯示出來, 再調用 InvalidateRect( hwnd, NULL, TRUE ) ; 使整個客戶區變成無效狀態, 從而引發 WM_PAINT 需要重繪客戶區內容的消息, 在處理重繪消息時輸出剛剛獲得的鼠標指針坐標位置。
        
        關於 ScreenToClient( hwnd, &pt ) ; :
            這個函數的功能是將屏幕坐標(相對於整個屏幕左上角的坐標)轉換成相對於窗口客戶區的坐標, 屏幕坐標與窗口客戶區坐標的含義如圖所示:


            GetCursorPos獲得的鼠標位置是屏幕坐標, 如果想知道他在窗口客戶區內的相對位置就需要調用ScreenToClient函數將其轉化為客戶區坐標。
          此外還有一個WIndows函數是將窗口客戶區坐標轉成屏幕坐標的, 函數為: ClientToScreen( hwnd, &pt ) ;
          獲取鼠標指針的位置還有其他的方法, 這里只是其中的一種。
    
    
    2>. 示例二: 處理鼠標左鍵單擊事件
        鼠標左鍵在客戶區被單擊時發來的消息: WM_LBUTTONDOWN

 1     switch(message)
 2     {
 3     case WM_PAINT:
 4         hdc = BeginPaint( hwnd, &ps ) ;
 5         EndPaint( hwnd, &ps ) ;
 6         return 0 ;
 7 
 8     case WM_LBUTTONDOWN:    //處理鼠標左鍵單擊被按下時產生的消息
 9         x = LOWORD( lParam ) ;    //獲取鼠標位置x坐標信息
10         y = HIWORD( lParam ) ;    //獲取鼠標位置y坐標信息
11         wsprintf( szBuffer,  "鼠標左鍵被單擊, 擊中位置: (%i, %i)", x, y );
12         MessageBox( hwnd, szBuffer, TEXT("鼠標動作"), MB_OK ) ;
13         return 0 ;
14 
15     case WM_DESTROY:
16         PostQuitMessage(0) ;
17         return 0 ;
18     }

    完整的示例代碼:

View Code - WM_LBUTTONDOWN
 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( "UseMouse_Demo" ) ;
 8     HWND hwnd ;
 9     MSG msg ;
10     WNDCLASS wndclass ;
11 
12     wndclass.hInstance        = hInstance ;
13     wndclass.lpfnWndProc    = WndProc ;
14     wndclass.lpszClassName    = szAppName ;
15     wndclass.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
16     wndclass.hbrBackground    = (HBRUSH) GetStockObject( WHITE_BRUSH ) ;
17     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;
18     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;
19     wndclass.cbClsExtra        = 0 ;
20     wndclass.cbWndExtra        = 0 ;
21     wndclass.lpszMenuName    = 0 ;
22 
23     if( !RegisterClass(&wndclass) )
24     {
25         MessageBox( NULL, TEXT("錯誤, 無法注冊窗口類."), TEXT("錯誤"), MB_OK ) ;
26         return 0 ;
27     }
28 
29     hwnd = CreateWindow( szAppName, TEXT("處理鼠標單擊事件 - Demo"),
30         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
31         CW_USEDEFAULT, CW_USEDEFAULT,
32         NULL, NULL, hInstance, NULL ) ;
33 
34     ShowWindow( hwnd, iCmdShow ) ;
35     UpdateWindow( hwnd ) ;
36 
37     while( GetMessage(&msg, NULL, 0, 0) )
38     {
39         TranslateMessage( &msg ) ;
40         DispatchMessage( &msg ) ;
41     }
42 
43     return msg.wParam ;
44 }
45 
46 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
47 {
48     HDC hdc ;
49     PAINTSTRUCT ps ;
50     static POINT pt ;
51     TCHAR szBuffer[128] ;
52     static int x, y ;
53 
54     switch(message)
55     {
56     case WM_PAINT:
57         hdc = BeginPaint( hwnd, &ps ) ;
58         EndPaint( hwnd, &ps ) ;
59         return 0 ;
60 
61     case WM_LBUTTONDOWN:
62         x = LOWORD( lParam ) ;
63         y = HIWORD( lParam ) ;
64         wsprintf( szBuffer,  "鼠標左鍵被單擊, 擊中位置: (%i, %i)", x, y );
65         MessageBox( hwnd, szBuffer, TEXT("鼠標動作"), MB_OK ) ;
66         return 0 ;
67 
68     case WM_DESTROY:
69         PostQuitMessage(0) ;
70         return 0 ;
71     }
72 
73     return DefWindowProc( hwnd, message, wParam, lParam ) ;
74 }

    這個示例演示的是當鼠標在客戶區按下時彈出一個對話框, 對話框的內容是鼠標被按下時鼠標指針的位置信息, 可以看到, 這里我們沒有使用 GetCursorPos 函數來獲取鼠標指針的位置, 而是通過

        x = LOWORD( lParam ) ;    //獲取鼠標位置x坐標信息
        y = HIWORD( lParam ) ;    //獲取鼠標位置y坐標信息

    來獲取的, 參數lParam包含了鼠標指針的位置信息, 其中低位字節表示x坐標, 高位字節表示y坐標, 利用LOWORDHIWORD宏可以取得這些坐標值, 這里獲取的坐標指的是相對於窗口客戶區的坐標。

 


三、客戶區鼠標消息
    與鍵盤消息不同, 在鍵盤消息中, Windows只把鍵盤消息發送到當前具有輸入焦點的窗口, 而鼠標消息無論窗口是否獲取焦點, 只要鼠標經過客戶區, 或者在客戶區內被單擊窗口過程都會收到鼠標消息, 被點擊(包括雙擊/單擊/拖動)的窗口將變成活動窗口。與客戶區消息相對應的稱為非客戶區消息, 非客戶區消息是指鼠標指針在窗口內並在在客戶區外的移動或單擊/雙擊等, 非客戶區包括窗口的標題欄、菜單欄、滾動條、窗口的邊框, 這些將在后面進行討論, 這里先說客戶區鼠標消息。
    
    1>. 鼠標單擊
        鼠標在客戶區單擊時各個鼠標按鍵所產生的消息如下:

鼠標按鍵 按下時產生的消息 釋放時產生的消息
左鍵 WM_LBUTTONDOWN WM_LBUTTONUP
中鍵 WM_MBUTTONDOWN WM_MBUTTONUP
右鍵 WM_RBUTTONDOWN WM_RBUTTONUP



        
        

 

 

    示例2中已經演示了一個處理鼠標左鍵單擊的示例, 對於中鍵和右鍵處理的方法是相同的, 只要等待Windows發來消息然后處理這些消息就行了。
        
    2>. wParam參數中的內容
        參數wParam中的值表示了鼠標按鈕、Shift鍵和Ctrl鍵的狀態。 將wParam與"鼠標鍵"標識符進行按位與(&)運算可以得到鼠標按鍵與鼠標鍵的狀態, 以前綴MK_為開頭的標識符稱為"鼠標鍵", 有如下鼠標鍵:

            #define MK_LBUTTON          0x0001            //按下左鍵
            #define MK_RBUTTON          0x0002            //按下右鍵
#define MK_MBUTTON 0x0010 //按下中鍵 #define MK_SHIFT 0x0004 //按下Shift鍵 #define MK_CONTROL 0x0008 //按下Ctrl鍵

        例如, 當接收到 WM_LBUTTONDOWN 消息時, 若

            wParam & MK_SHIFT 

        的值為TRUE(非零), 則表示按下左鍵的同時也按下了Shift鍵。
        例如:

        case WM_LBUTTONDOWN:
            if( wParam & MK_CONTROL )
            {
                MessageBox( hwnd, TEXT("Ctrl鍵與鼠標左鍵同時被按下!"), TEXT("鼠標動作"), MB_OK ) ;
                return 0 ;
            }
            return 0 ;

        只有當鼠標左鍵與鍵盤的Ctrl鍵同時被按下時我們彈出個對話框說明"Ctrl鍵與鼠標左鍵同時被按下!", 否則什么也不做。
        
        3>. 鼠標雙擊
            雙擊對兩次擊中的位置以及時間間隔都有一定要求, 只有當兩次快速的單擊在物理位置上靠的很近並且時間間隔很短的情況下才算雙擊。
            
            如果想讓窗口過程接收鼠標雙擊消息, 需要在注冊窗口類(RegisterClass)時, 初始化wndclass中的style成員的屬性中再加上CS_DBLCLKS標識符:

                wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;

            如果在窗口類的style成員中沒有包含 CS_DBLCLKS 標識符, 那么即使當用戶雙擊時不會產生雙擊消息, 而是產生一串如下的消息:

                WM_LBUTTONDOWN
                WM_LBUTTONUP
                WM_LBUTTONDOWN
                WM_LBUTTONUP

            由於用戶在連續兩次按下鼠標左鍵時需要一定時間, 即使這個時間比較短暫, 但是在這個過程中程序還是有可能收到其他消息的, 比如用戶在快速的兩次單擊中手的微微抖動就會在其中插入一個WM_MOUSEMOVE的消息, 這里暫時忽略其中插入的消息, 假設消息就是連續的這些。
            
            當窗口類的style成員只中包含CS_DBLCLKS標識符后, 用戶再次雙擊就會產生這樣的一串消息:

                WM_LBUTTONDOWN
                WM_LBUTTONUP
                WM_LBUTTONDBLCLK
                WM_LBUTTONUP

            可以看到, 在加入 CS_DBLCLKS 標識符后, 第三個消息 WM_LBUTTONDOWN 只是被簡單的替換成了 WM_LBUTTONDBLCLK 消息。
            
            鼠標各個按鍵雙擊時第三個消息所對應替換的消息如下:

            #define WM_LBUTTONDBLCLK                0x0203            //左鍵
            #define WM_MBUTTONDBLCLK                0x0209            //中鍵
            #define WM_RBUTTONDBLCLK                0x0206            //右鍵

 


四、非客戶區鼠標消息
    非客戶區消息幾乎與客戶區消息完全對應, 只是在標識符中多了一個"NC"字符(noclient), 當鼠標指針在窗口的非客戶區移動時(比如標題欄), 窗口過程就會接收到 WM_NCMOUSEMOVE 消息, 在客戶區外鼠標按下產生的消息如下:

鼠標按鍵 按下 釋放 第二次按下(雙擊)
左鍵 WM_NCLBUTTONDWON WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
中鍵 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
右鍵 WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

 

 



 

  另外與客戶區消息不同的是, 這里的 wParam 參數中的值與客戶區中的含義有所不同, 這里的 wParam 表示非客戶區鼠標移動或單擊的位置, 他的值被設定成一些以 HT 開頭的標識符中, 表示 "擊中測試"(Hit Test), 關於擊中測試與以HT開頭的標識符將在下面講到。
    
    參數 lParam 中的值依然是鼠標指針的位置信息, 但此時的信息正好與客戶區中的 lParam 的坐標信息相反, 客戶區中的 lParam 的值是相對於窗口客戶區的坐標, 而這里的(非客戶區) lParam 中所包含的坐標信息是屏幕坐標, 在上面已經提到過, 使用ScreenToClientClientToScreen可以實現屏幕坐標與客戶區坐標之間的轉化。
    
    處理非客戶區左鍵單擊示例:

    switch(message)
    {
    case WM_PAINT:
        hdc = BeginPaint( hwnd, &ps ) ;
        EndPaint( hwnd, &ps ) ;
        return 0 ;

    case WM_NCLBUTTONDOWN:        //處理非客戶區鼠標左鍵單擊事件
        MessageBox( hwnd, TEXT("非客戶區鼠標左鍵被單擊"), TEXT("鼠標動作"), MB_OK ) ;
        return 0 ;

    case WM_DESTROY:
        PostQuitMessage(0) ;
        return 0 ;
    }

 



五、關於"擊中測試"消息 WM_NCHITTEST
    WM_NCHITTEST表示"非客戶區擊中測試", 所謂的擊中測試就是測試鼠標當前所在的位置, 這個消息的優先級高於其他所有的客戶區和非客戶區消息, 參數 lParam 中包含相對於屏幕坐標的x值與y值, wParam 參數另有用途。
    
    一般來說, WM_NCHITTEST 消息是交給 DefWindowProc 默認的消息處理函數進行處理的, 對於客戶區中, Windows會利用 WM_NCHITTEST 消息來產生所有和其他鼠標位置相關的鼠標消息。對於非客戶區消息來說, DefWindowProc 處理 WM_NCHITTEST 消息后返回一個 wParam 值, 這個值可以是任意一個非客戶區鼠標消息的 wParam 參數的值, 這個 wParam 值用來判斷鼠標的所在的位置。
    
    舉例來說, 如果 DefWindowProc 函數在處理 WM_NCHITTEST 消息后返回一個 HTCLIENT , HTCLIENT 表示鼠標在客戶區, 這時Windows會將屏幕坐標轉換成客戶區坐標,並產生一個相關的客戶區的鼠標消息;
    當返回值為 HTCAPTION 表示鼠標此時在一個標題欄中, 所以Windows會將此時鼠標的坐標位置轉成屏幕坐標並發送相關的非客戶區消息。
    
    這些返回的標識符定義在WINUSER.H頭文件中, 相關的定義如下:

#define HTERROR             (-2)                    //在屏幕的后面或在窗體之間的線上(使函數DefWindowProc產生一個警示音)
#define HTTRANSPARENT       (-1)                    //在一個被其它窗口覆蓋的窗口中
#define HTNOWHERE           0                        //在屏幕背景或窗口之間的分界線
#define HTCLIENT            1                        //在客戶區中
#define HTCAPTION           2                        //在標題欄中
#define HTSYSMENU           3                        //在一個窗口菜單欄或子窗口的關閉按鈕上
#define HTGROWBOX           4                        //在尺寸框中
#define HTSIZE              HTGROWBOX                //同HTGROWBOX
#define HTMENU              5                        //在菜單區域
#define HTHSCROLL           6                        //在水平滾動條上
#define HTVSCROLL           7                        //在垂直滾動條上
#define HTMINBUTTON         8                        //在最小化按鈕上
#define HTMAXBUTTON         9                        //在最大化按鈕上
#define HTLEFT              10                        //在窗口的左邊框上
#define HTRIGHT             11                        //在窗口的右邊框上
#define HTTOP               12                        //在窗口水平邊框的上方
#define HTTOPLEFT           13                        //在窗口邊框的左上角
#define HTTOPRIGHT          14                        //在窗口邊框的右上角
#define HTBOTTOM            15                        //在窗口的水平邊框的底部
#define HTBOTTOMLEFT        16                        //在窗口邊框的左下角
#define HTBOTTOMRIGHT       17                        //在窗口邊框的右下角
#define HTBORDER            18                        //在不具有可變大小邊框的窗口的邊框上
#define HTREDUCE            HTMINBUTTON                //同HTMINBUTTON
#define HTZOOM              HTMAXBUTTON                //同HTMAXBUTTON
#define HTSIZEFIRST         HTLEFT                    //同HTLEFT
#define HTSIZELAST          HTBOTTOMRIGHT             //同HTBOTTOMRIGHT
#define HTOBJECT            19                        //忽略該標識符, 已廢棄
#define HTCLOSE             20                        //在關閉按鈕上
#define HTHELP              21                        //在幫助按鈕上

    這樣在獲取非客戶區消息時我們就可以根據 wParam 中的值判斷鼠標在窗口的位置了, 像這樣:

    case WM_NCLBUTTONDOWN:        //處理非客戶區的鼠標左鍵單擊事件
        x = LOWORD( lParam ) ;    //通過lParam獲取鼠標位置
        y = HIWORD( lParam ) ;
        switch(wParam)            //通過wParam判斷鼠標在窗口的位置
        {
        case HTCAPTION:        //在標題上
            wsprintf( szBuffer,  "鼠標左鍵在標題欄中被單擊, 擊中位置: (%i, %i)", x, y ) ;
            MessageBox( hwnd, szBuffer, TEXT("鼠標動作"), MB_OK ) ;
            break ;
        case HTMINBUTTON:    //在最小化按鈕上
            wsprintf( szBuffer,  "鼠標左鍵在最小化按鈕上被單擊, 擊中位置: (%i, %i)", x, y ) ;
            MessageBox( hwnd, szBuffer, TEXT("鼠標動作"), MB_OK ) ;
            break ;
        case HTMAXBUTTON:    //在最大化按鈕上
            wsprintf( szBuffer,  "鼠標左鍵在最大化按鈕上被單擊, 擊中位置: (%i, %i)", x, y ) ;
            MessageBox( hwnd, szBuffer, TEXT("鼠標動作"), MB_OK ) ;
            break ;
        }
        return 0 ;

    首先捕獲 鼠標左鍵在非客戶區的單擊事件, 然后再通過 wParam 判斷鼠標在窗口的位置, 這里獲取鼠標位置是通過 LOWORD 和 HIWORD 宏完成的, 還有兩個功能相同的宏也可以用來獲取lParam中的鼠標信息, 他們是 GET_X_LPARAM 宏和 GET_Y_LPARAM, 不過這兩個宏是定義在 WINDOWSX.H 頭文件中的, 如果要使用這兩個宏需要將 WINDOWSX.H 包含進來。
    舉例:

    xPos = GET_X_LPARAM(lParam) ;
    yPos = GET_Y_LPARAM(lParam) ;

 

 
--------------------


wid, 2012.11.30

 

上一篇: C語言Windows程序設計 -> 第十天 -> 響應鍵盤事件

 


免責聲明!

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



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