Windows程序设计-鼠标
基础
确认鼠标是否存在
fMouse = GetSystemMetrics (SM_MOUSEPRESENT); // True(非0)存在
确定按键个数
cButtons = GetSystemMetrics (SM_CMOUSEBUTTONS) ;
双击速度SystemParametersInfo
鼠标按键动作
Clicking按下并放开一个鼠标按键。Double-clicking快速按下并放开鼠标按键两次。Dragging按住鼠标按键并移动鼠标。
对三键鼠标来说,三个键分别称为左键、中键、右键。在Windows表头文件中定义的与鼠标有关的标识符使用缩写LBUTTON、MBUTTON和RBUTTON。
显示区域鼠标消息
只要鼠标跨越窗口或者在某窗口中按下鼠标按键,那么窗口消息处理程序就会收到鼠标消息,而不管该窗口是否活动或者是否拥有输入焦点。Windows为鼠标定义了21种消息,不过,其中有11个消息和显示区域无关(下面称之为「非显示区域」消息),Windows程序经常忽略这些消息。
只要鼠标跨越窗口或者在某窗口中按下鼠标按键,那么窗口消息处理程序就会收到鼠标消息,而不管该窗口是否活动或者是否拥有输入焦点。Windows为鼠标定义了21种消息,不过,其中有11个消息和显示区域无关(下面称之为「非显示区域」消息),Windows程序经常忽略这些消息。
当鼠标移过窗口的显示区域时,窗口消息处理程序收到WM_MOUSEMOVE*消息。当在窗口的显示区域中按下或者释放一个鼠标按键时,窗口消息处理程序会接收到下面这些消息:
键
| 按下
| 释放
| 按下(双键)
|
左
| WM_LBUTTONDOWN
| WM_LBUTTONUP
| WM_LBUTTONDBLCLK
|
中
| WM_MBUTTONDOWN
| WM_MBUTTONUP
| WM_MBUTTONDBLCLK
|
右
| WM_RBUTTONDOWN
| WM_RBUTTONUP
| WM_RBUTTONDBLCLK
|
对于所有这些消息来说,其lParam值均含有鼠标的位置:低字组为x坐标,高字组为y坐标,这两个坐标是相对于窗口显示区域左上角的位置。您可以用LOWORD和HIWORD宏来提取这些值:
x = LOWORD (lParam) ;y = HIWORD (lParam) ;
wParam的值指示鼠标按键以及Shift和Ctrl键的状态。您可以使用表头文件WINUSER.H中定义的位屏蔽来测试wParam。MK前缀代表鼠标按键。
MK_LBUTTON 按下左键MK_MBUTTON 按下中键MK_RBUTTON 按下右键MK_SHIFT 按下Shift键MK_CONTROL 按下Ctrl键
例如,如果收到了WM_LBUTTONDOWN消息,而且值
wparam & MK_SHIFT
是TRUE(非0),您就知道当左键按下时也按下了Shift键。
如果希望您的窗口消息处理程序能够收到双按键的鼠标消息,那么在呼叫RegisterClass初始化窗口类别结构时,必须在窗口风格中包含CS_DBLCLKS标识符:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
如果您的窗口类别风格中包含了CS_DBLCLKS,那么双击时窗口消息处理程序将收到如下消息: WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK WM_LBUTTONUP WM_LBUTTONDBLCLK消息简单地替换了第二个WM_LBUTTONDOWN消息。
非显示区域鼠标消息
如果鼠标在窗口的显示区域之外但还在窗口内,Windows就给窗口消息处理程序发送一条「非显示区域」鼠标消息。窗口非显示区域包括标题列、菜单和窗口滚动条。
非显示区域鼠标消息几乎完全与显示区域鼠标消息相对应。消息中含有字母「NC」以表示是非显示区域消息。如果鼠标在窗口的非显示区域中移动,那么窗口消息处理程序会接收到WM_NCMOUSEMOVE消息。
键
| 按下
| 释放
| 按下(双击)
|
左
| WM_NCLBUTTONDOWN
| WM_NCLBUTTONUP
| WM_NCLBUTTONDBLCLK
|
中
| WM_NCMBUTTONDOWN
| WM_NCMBUTTONUP
| WM_NCMBUTTONDBLCLK
|
右
| WM_NCRBUTTONDOWN
| WM_NCRBUTTONUP
| WM_NCRBUTTONDBLCLK
|
对非显示区域鼠标消息,wParam和lParam参数与显示区域鼠标消息的wParam和lParam参数不同。wParam参数指明移动或者按鼠标按键的非显示区域。它设定为WINUSER.H中定义的以HT开头的标识符之一(HT表示命中测试)。
lParam参数的低位word为x坐标,高位word为y坐标,但是,它们是屏幕坐标,而不是像显示区域鼠标消息那样指的是显示区域坐标。对屏幕坐标,显示器左上角的x和y的值为0。当往右移时x的值增加,往下移时y的值增加。
可以用两个Windows函数将屏幕坐标转换为显示区域坐标或者反之:
POINT pt;ScreenToClient (hwnd, &pt) ;ClientToScreen (hwnd, &pt) ;
第21个鼠标消息:命中测试消息WM_NCHITTEST,代表非显示区域命中测试。此消息优先于所有其它的显示区域和非显示区域鼠标消息。lParam参数含有鼠标位置的x和y屏幕坐标,wParam参数没有用。
Windows 应 用 程 序 通 常 把 这 个 消 息 传 送 给 DefWindowProc , 然 后 Windows 用WM_NCHITTEST消息产生与鼠标位置相关的所有其它鼠标消息。对于非显示区域鼠标消息,在处理WM_NCHITTEST时,从DefWindowProc传回的值将成为鼠标消息中的wParam参数,这个值可以是任意非显示区域鼠标消息的wParam值再加上以下内容:
HTCLIENT 显示区域HTNOWHERE 不在窗口中HTTRANSPARENT 窗口由另一个窗口覆盖HTERROR 使DefWindowProc产生警示用的哔声
如果DefWindowProc在其处理WM_NCHITTEST消息后传回HTCLIENT,那么Windows将把屏幕坐标转换为显示区域坐标并产生显示区域鼠标消息。
命中测试例子
/*-------------------------------------------------------------------------CHECKER1.C -- Mouse Hit-Test Demo Program No. 1(c) Charles Petzold,--------------------------------------------------------------------------*/#include #define DIVISIONS 5LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("Checker1"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Checker1 Mouse Hit-Test Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static BOOL fState[DIVISIONS][DIVISIONS]; static int cxBlock, cyBlock; HDC hdc; int x, y; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_SIZE: cxBlock = LOWORD(lParam) / DIVISIONS; cyBlock = HIWORD(lParam) / DIVISIONS; return 0; case WM_LBUTTONDOWN: x = LOWORD(lParam) / cxBlock; y = HIWORD(lParam) / cyBlock; if (x < DIVISIONS && y < DIVISIONS) { fState[x][y] ^= 1; rect.left = x * cxBlock; rect.top = y * cyBlock; rect.right = (x + 1) * cxBlock; rect.bottom = (y + 1) * cyBlock; InvalidateRect(hwnd, &rect, FALSE); } else MessageBeep(0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) { Rectangle(hdc, x * cxBlock, y * cyBlock, (x + 1) * cxBlock, (y + 1) * cyBlock); if (fState[x][y]) { MoveToEx(hdc, x * cxBlock, y * cyBlock, NULL); LineTo(hdc, (x + 1) * cxBlock, (y + 1) * cyBlock); MoveToEx(hdc, x * cxBlock, (y + 1) * cyBlock, NULL); LineTo(hdc, (x + 1) * cxBlock, y * cyBlock); } } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return
加入键盘接口
/*----------------------------------------------------------------------------CHECKER2.C -- Mouse Hit-Test Demo Program No. 2(c) Charles Petzold, 1998----------------------------------------------------------------------------*/#include #define DIVISIONS 5LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("Checker2"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Checker2 Mouse Hit-Test Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static BOOL fState[DIVISIONS][DIVISIONS]; static int cxBlock, cyBlock; HDC hdc; int x, y; PAINTSTRUCT ps; POINT point; RECT rect; switch (message) { case WM_SIZE: cxBlock = LOWORD(lParam) / DIVISIONS; cyBlock = HIWORD(lParam) / DIVISIONS; return 0; case WM_SETFOCUS: ShowCursor(TRUE); return 0; case WM_KILLFOCUS: ShowCursor(FALSE); return 0; case WM_KEYDOWN: GetCursorPos(&point); ScreenToClient(hwnd, &point); x = max(0, min(DIVISIONS - 1, point.x / cxBlock)); y = max(0, min(DIVISIONS - 1, point.y / cyBlock)); switch (wParam) { case VK_UP: y--; break; case VK_DOWN: y++; break; case VK_LEFT: x--; break; case VK_RIGHT: x++; break; case VK_HOME: x = y = 0; break; case VK_END: x = y = DIVISIONS - 1; break; case VK_RETURN: case VK_SPACE: SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(x * cxBlock, y * cyBlock)); break; } x = (x + DIVISIONS) % DIVISIONS; y = (y + DIVISIONS) % DIVISIONS; point.x = x * cxBlock + cxBlock / 2; point.y = y * cyBlock + cyBlock / 2; ClientToScreen(hwnd, &point); SetCursorPos(point.x, point.y); return 0; case WM_LBUTTONDOWN: x = LOWORD(lParam) / cxBlock; y = HIWORD(lParam) / cyBlock; if (x < DIVISIONS && y < DIVISIONS) { fState[x][y] ^= 1; rect.left = x * cxBlock; rect.top = y * cyBlock; rect.right = (x + 1) * cxBlock; rect.bottom = (y + 1) * cyBlock; InvalidateRect(hwnd, &rect, FALSE); } else MessageBeep(0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) { Rectangle(hdc, x * cxBlock, y * cyBlock, (x + 1) * cxBlock, (y + 1) * cyBlock); if (fState[x][y]) { MoveToEx(hdc, x *cxBlock, y *cyBlock, NULL); LineTo(hdc, (x + 1)*cxBlock, (y + 1)*cyBlock); MoveToEx(hdc, x *cxBlock, (y + 1)*cyBlock, NULL); LineTo(hdc, (x + 1)*cxBlock, y *cyBlock); } } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return
子窗口
/*---------------------------------------------------------------------------CHECKER3.C -- Mouse Hit-Test Demo Program No. 3(c) Charles Petzold, 1998----------------------------------------------------------------------------*/#include #define DIVISIONS 5LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);TCHAR szChildClass[] = TEXT("Checker3_Child");int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("Checker3"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } wndclass.lpfnWndProc = ChildWndProc; wndclass.cbWndExtra = sizeof (long); wndclass.hIcon = NULL; wndclass.lpszClassName = szChildClass; RegisterClass(&wndclass); hwnd = CreateWindow(szAppName, TEXT("Checker3 Mouse Hit-Test Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static HWND hwndChild[DIVISIONS][DIVISIONS]; int cxBlock, cyBlock, x, y; switch (message) { case WM_CREATE: for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) hwndChild[x][y] = CreateWindow(szChildClass, NULL, WS_CHILDWINDOW | WS_VISIBLE, 0, 0, 0, 0, hwnd, (HMENU)(y << 8 | x), (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL); return 0; case WM_SIZE: cxBlock = LOWORD(lParam) / DIVISIONS; cyBlock = HIWORD(lParam) / DIVISIONS; for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) MoveWindow (hwndChild[x][y], x * cxBlock, y * cyBlock, cxBlock, cyBlock, TRUE); return 0; case WM_LBUTTONDOWN: MessageBeep(0); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam);}LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_CREATE: SetWindowLong(hwnd, 0, 0); // on/off flag return 0; case WM_LBUTTONDOWN: SetWindowLong(hwnd, 0, 1 ^ GetWindowLong(hwnd, 0)); InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); Rectangle(hdc, 0, 0, rect.right, rect.bottom); if (GetWindowLong(hwnd, 0)) { MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, rect.right, rect.bottom); MoveToEx(hdc, 0, rect.bottom, NULL); LineTo(hdc, rect.right, 0); } EndPaint(hwnd, &ps); return 0; } return
在WinMain中CreateWindow呼叫的参数,与在建立25个子窗口的WndProc中CreateWindow呼叫的参数间的比较:
参数
| 主窗口
| 子窗口
|
窗口类别
| 「Checker3」
| 「Checker3_Child」
|
窗口标题
| 「Checker3…」
| NULL
|
窗口样式
| WS_OVERLAPPEDWINDOW
| WS_CHILDWINDOW |WS_VISIBLE |
水平位置
| CW_USEDEFAULT
| 0
|
垂直位置
| CW_USEDEFAULT
| 0
|
宽度
| CW_USEDEFAULT
| 0
|
高度
| CW_USEDEFAULT
| 0
|
父窗口句柄
| NULL
| hwnd
|
菜单句柄/子ID
| NULL
| (HMENU) (y << 8 | x) |
执行实体句柄
| hInstance
| (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE) |
额外参数
| NULL
| NULL
|
子窗口和键盘
/*---------------------------------------------------------------------------CHECKER4.C -- Mouse Hit-Test Demo Program No. 4(c) Charles Petzold, 1998---------------------------------------------------------------------------*/#include #define DIVISIONS 5LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);int idFocus = 0;TCHAR szChildClass[] = TEXT("Checker4_Child");int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("Checker4"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } wndclass.lpfnWndProc = ChildWndProc; wndclass.cbWndExtra = sizeof (long); wndclass.hIcon = NULL; wndclass.lpszClassName = szChildClass; RegisterClass(&wndclass); hwnd = CreateWindow(szAppName, TEXT("Checker4 Mouse Hit-Test Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static HWND hwndChild[DIVISIONS][DIVISIONS]; int cxBlock, cyBlock, x, y; switch (message) { case WM_CREATE: for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) hwndChild[x][y] = CreateWindow(szChildClass, NULL, WS_CHILDWINDOW | WS_VISIBLE, 0, 0, 0, 0, hwnd, (HMENU)(y << 8 | x), (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE), NULL); return 0; case WM_SIZE: cxBlock = LOWORD(lParam) / DIVISIONS; cyBlock = HIWORD(lParam) / DIVISIONS; for (x = 0; x < DIVISIONS; x++) for (y = 0; y < DIVISIONS; y++) MoveWindow(hwndChild[x][y], x * cxBlock, y * cyBlock, cxBlock, cyBlock, TRUE); return 0; case WM_LBUTTONDOWN: MessageBeep(0); return 0; // On set-focus message, set focus to child window case WM_SETFOCUS: SetFocus(GetDlgItem(hwnd, idFocus)); return 0; // On key-down message, possibly change the focus window case WM_KEYDOWN: x = idFocus & 0xFF; y = idFocus >> 8; switch (wParam) { case VK_UP: y--; break; case VK_DOWN: y++; break; case VK_LEFT: x--; break; case VK_RIGHT: x++; break; case VK_HOME: x = y = 0; break; case VK_END: x = y = DIVISIONS - 1; break; default: return 0; } x = (x + DIVISIONS) % DIVISIONS; y = (y + DIVISIONS) % DIVISIONS; idFocus = y << 8 | x; SetFocus(GetDlgItem(hwnd, idFocus)); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam);}LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; RECT rect; switch (message) { case WM_CREATE: SetWindowLong(hwnd, 0, 0); // on/off flag return 0; case WM_KEYDOWN: // Send most key presses to the parent window if (wParam != VK_RETURN && wParam != VK_SPACE) { SendMessage(GetParent(hwnd), message, wParam, lParam); return 0; } // For Return and Space, fall through to toggle the square case WM_LBUTTONDOWN: SetWindowLong(hwnd, 0, 1 ^ GetWindowLong(hwnd, 0)); SetFocus(hwnd); InvalidateRect(hwnd, NULL, FALSE); return 0; // For focus messages, invalidate the window for repaint case WM_SETFOCUS: idFocus = GetWindowLong(hwnd, GWL_ID); // Fall through case WM_KILLFOCUS: InvalidateRect(hwnd, NULL, TRUE); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &rect); Rectangle(hdc, 0, 0, rect.right, rect.bottom); // Draw the "x" mark if (GetWindowLong(hwnd, 0)) { MoveToEx(hdc, 0, 0, NULL); LineTo(hdc, rect.right, rect.bottom); MoveToEx(hdc, 0, rect.bottom, NULL); LineTo(hdc, rect.right, 0); } // Draw the "focus" rectangle if (hwnd == GetFocus()) { rect.left += rect.right / 10; rect.right -= rect.left; rect.top += rect.bottom / 10; rect.bottom -= rect.top; SelectObject(hdc, GetStockObject (NULL_BRUSH)); SelectObject(hdc, CreatePen(PS_DASH, 0, 0)); Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom); DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN))); } EndPaint(hwnd, &ps); return 0; } return
拦截鼠标
/*----------------------------------------------------------------------------BLOKOUT2.C -- Mouse Button & Capture Demo Program(c) Charles Petzold, 1998----------------------------------------------------------------------------*/#include LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("BlokOut2"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("Mouse Button & Capture Demo"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;}void DrawBoxOutline(HWND hwnd, POINT ptBeg, POINT ptEnd){ HDC hdc; hdc = GetDC(hwnd); SetROP2(hdc, R2_NOT); SelectObject(hdc, GetStockObject(NULL_BRUSH)); Rectangle(hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y); ReleaseDC(hwnd, hdc);}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ static BOOL fBlocking, fValidBox; static POINT ptBeg, ptEnd, ptBoxBeg, ptBoxEnd; HDC hdc; PAINTSTRUCT ps; switch (message) { case WM_LBUTTONDOWN: ptBeg.x = ptEnd.x = LOWORD(lParam); ptBeg.y = ptEnd.y = HIWORD(lParam); DrawBoxOutline(hwnd, ptBeg, ptEnd); SetCapture(hwnd); SetCursor(LoadCursor(NULL, IDC_CROSS)); fBlocking = TRUE; return 0; case WM_MOUSEMOVE: if (fBlocking) { SetCursor(LoadCursor(NULL, IDC_CROSS)); DrawBoxOutline(hwnd, ptBeg, ptEnd); ptEnd.x = LOWORD(lParam); ptEnd.y = HIWORD(lParam); DrawBoxOutline(hwnd, ptBeg, ptEnd); } return 0; case WM_LBUTTONUP: if (fBlocking) { DrawBoxOutline(hwnd, ptBeg, ptEnd); ptBoxBeg = ptBeg; ptBoxEnd.x = LOWORD (lParam); ptBoxEnd.y = HIWORD (lParam); ReleaseCapture(); SetCursor(LoadCursor(NULL, IDC_ARROW)); fBlocking = FALSE; fValidBox = TRUE; InvalidateRect(hwnd, NULL, TRUE); } return 0; case WM_CHAR: if (fBlocking & wParam == '\x1B') // i.e., Escape { DrawBoxOutline(hwnd, ptBeg, ptEnd); ReleaseCapture(); SetCursor(LoadCursor(NULL, IDC_ARROW)); fBlocking = FALSE; } return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); if (fValidBox) { SelectObject(hdc, GetStockObject (BLACK_BRUSH)); Rectangle(hdc, ptBoxBeg.x, ptBoxBeg.y, ptBoxEnd.x, ptBoxEnd.y); } if (fBlocking) { SetROP2(hdc, R2_NOT); SelectObject(hdc, GetStockObject (NULL_BRUSH)); Rectangle(hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return
SetCapture (hwnd) ;
在这个函数调用之后,Windows将所有鼠标消息发给窗口句柄为hwnd的窗口消息处理程序。之后收到鼠标消息都是以显示区域消息的型态出现,即使鼠标正在窗口的非显示区域。lParam参数将指示鼠标在显示区域坐标中的位置。不过,当鼠标位于显示区域的左边或者上方时,这些x和y坐标可以是负的。当您想释放鼠标时,调用:
ReleaseCapture () ;
从而使处理恢复正常。
鼠标滑轮
消息:WM_MOUSEWHEEL
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~