Windows程序设计-鼠标

网友投稿 356 2022-11-16

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小时内删除侵权内容。

上一篇:Java IO流之StringWriter和StringReader用法分析
下一篇:typec与micro usb区别
相关文章

 发表评论

暂时没有评论,来抢沙发吧~