非客户区鼠标消息的处理

非客户区鼠标消息的处理

/*---------------------------------------------------------
	s037.c---a daily practice
	036.7	WIN32 API 每日一练
	第37个例子:非客户区鼠标消息的处理
	GetCursorPos
	SetCursorPos
	ScreenToClient
	ClientToScreen
	MAKELONG宏
	 2023 7.6
-----------------------------------------------------------*/

#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("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("this 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;
	RECT rect;
	POINT point;


	switch (message)
	{
	case WM_SIZE:
		cxBlock = LOWORD(lParam) / DIVISIONS;//分成若干个部分
		cyBlock = HIWORD(lParam) / DIVISIONS;//e.t.c
		InvalidateRect(hwnd, NULL, TRUE);//这里是我增加,不然不更新绘制的边框
		//InvalidateRect(hwnd, &rect, TRUE);
		return 0;
		//鼠标移入窗口的消息
	case WM_SETFOCUS:
		//如果bShow为true,则显示计数器增加1,如果bShow为false,则显示计数减1 
		ShowCursor(TRUE);//显示计数+1,如果按照了鼠标则忽略
		return 0;

	case WM_KILLFOCUS:
		ShowCursor(FALSE);//显示计数-1;
		return 0;


	case WM_KEYDOWN:
		//因wParam为虚拟键码,lParam为击键的6个字段,鼠标没坐标。
		GetCursorPos(&point);//检索鼠标光标的位置(以屏幕坐标为单位)。
		ScreenToClient(hwnd, &point);//ScreenToClient 函数将屏幕上指定点的屏幕坐标转换为工作区坐标

		x = max(0, min(DIVISIONS - 1, point.x / cxBlock));//0~4
		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原区间为]0,4]+5后,移到[5,9]区间,取模,防止x---后出现负数区间。
			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, TRUE);
		}
		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 + 0) * cxBlock, (y + 0) * cyBlock, NULL);
					LineTo(hdc, (x + 1) * cxBlock, (1 + y) * cyBlock);
					MoveToEx(hdc, (x + 0) * cxBlock, (y + 1) * cyBlock, NULL);
					LineTo(hdc, (x + 1) * cxBlock, (y + 0) * cyBlock);
				}
			}

		static int test;
	//	test = MAKELONG(x, y);
		EndPaint(hwnd, &ps);
		return 0;

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

	return DefWindowProc(hwnd, message, wParam, lParam);
}
/******************************************************
* Rectangle 函数绘制矩形。 该矩形使用当前笔轮廓,并使用当前画笔填充。
BOOL Rectangle(
	[in] HDC hdc,
	[in] int left,
	[in] int top,
	[in] int right,
	[in] int bottom
);

********************************************/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值