7,鼠标学习二

来源:互联网 发布:安卓数据查询源码 编辑:程序博客网 时间:2024/04/29 08:08

《鼠标学习一》描述的是鼠标在客户区情况下,

当鼠标在非客户区的时候呢?

窗口的非客户区包括:标题栏,菜单和窗口滚动条,系统一般不需要用户处理非客户区消息,只要将其发送个DefWindowProc即可,这个系统键盘消息很类似哦。


非客户区鼠标消息几乎和客户区完全类似,标识符“NC_",表示非客户(nonclient)

WM_NCMOUSEMOVE :鼠标在非客户区移动。


重点来了,非客户区鼠标消息参数wParam和lParam与客户区的不同,参数wParam表示非客户区鼠标移动或单击的位置,它的值设定成一个以HT_为首的标识符。

其中HT_表示击中测试(hit-test),这些表示符都定义在WINUSER.h头文件中。参数lParam现在表示的是屏幕坐标,而不再是相对客户区。

不过可以利用下面两个函数实现屏幕坐标和客户区坐标的物理转换。

ScreenToClient(hwnd,&pt);

ClientToScreen(hwnd,&pt);

其中pt是一个POINT结构。


示例程序:

#include <windows.h>#define DIVISIONS 5LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("Division") ;     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 ("Division 5"),                          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 intcxBlock,cyBlock;HDChdc;intx,y;PAINTSTRUCT ps;RECTrect;POINTpoint;switch(message){case WM_SIZE:cxBlock=LOWORD(lParam)/DIVISIONS;//获取将客户区划分为25块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);<span style="background-color: rgb(255, 0, 0);">ScreenToClient(hwnd,&point);</span>             //实现屏幕坐标到客户区坐标的转变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;//对于数组来说DIVISIONS-1表示最后一个break;case VK_RETURN:                 //enter|space键表示最终确定,即鼠标左键效果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;<span style="background-color: rgb(255, 0, 0);">ClientToScreen(hwnd,&point);</span>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);   //是这块矩形区域失效,发出WM_PAINT}elseMessageBeep(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);*/rect.left=x*cxBlock;          //确定矩形的范围rect.top=y*cyBlock;rect.right=(x+1)*cxBlock;rect.bottom=(y+1)*cyBlock;FillRect(hdc,&rect,CreateSolidBrush(RGB(255,0,0)));}}EndPaint(hwnd,&ps);return 0;case WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc(hwnd,message,wParam,lParam);}


效果图:







0 0