7,鼠标学习二

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

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

窗口的非客户区包括:标题栏,菜单和窗口滚动条,系统一般不需要用户处理非客户区消息,只要将其发送个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 5

LRESULT 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 int	cxBlock,cyBlock;
	HDC			hdc;
	int			x,y;
	PAINTSTRUCT ps;
	RECT		rect;
	POINT		point;

	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
		}
		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);*/
					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);
}


效果图:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值