mfc电脑屏幕画笔

mfc电脑屏幕画笔

mfc电脑屏幕画笔

mfc电脑屏幕画笔

mfc电脑屏幕画笔

#include <windows.h>
#include <vector>
#include <algorithm>
/*
可能的优化:
创建几张位图 各自绘制 互不影响 最后在叠加绘制到屏幕上 类似ps图层结构

一些不足:
在划线过程中鼠标快速移动会出现明显的 “折线” 原因可能是鼠标坐标获取不及时导致(鼠标坐标跳跃)
通过观察 windows 自带的画图工具同样也会出现这样的状况 但只有鼠标移动速度极快的时候才会出现

当然擦除同样也会出现 “跳跃” 的情况

有生之年在想办法吧~~
*/
void CreatCanvas(HDC hdc, HDC &hdcBuffer, HBITMAP &BitMap) {//为指定设备创建 画布
	hdcBuffer = CreateCompatibleDC(hdc);
	BitMap = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN)*1.25, GetSystemMetrics(SM_CYSCREEN)*1.25);

	SelectObject(hdcBuffer, BitMap);

	BitBlt(hdcBuffer, 0, 0, GetSystemMetrics(SM_CXSCREEN)*1.25, GetSystemMetrics(SM_CYSCREEN)*1.25, hdc, 0, 0, SRCCOPY);//将背景拷贝到画布上
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstace, PSTR szCmdline, int iCmdShow) {
	/*变量声明*/
	WNDCLASS wc;
	static TCHAR *szAppName = TEXT("Screen_Paint");
	HWND hwnd = NULL;
	MSG msg;
	int nScreenWidth, nScreenHeight;
	/*获取屏幕尺寸*/
	nScreenWidth = GetSystemMetrics(SM_CXSCREEN) * 1.25;
	nScreenHeight = GetSystemMetrics(SM_CYSCREEN) * 1.25;
	/*窗口类属性填充 随后进行窗口注册*/
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(hInstance, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_CROSS);				//设置鼠标为十字
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = szAppName;
	/*失败则进行提示*/
	if (!RegisterClass(&wc)) {
		MessageBox(NULL, TEXT("该程序只能在windows NT下运行!"), szAppName, MB_ICONERROR);
		return 0;
	}
	/*进一步设置窗口样式*/
	hwnd = CreateWindowEx(WS_EX_LAYERED, szAppName,    //WS_EX_LAYERED 分层窗口(透明窗口)
		TEXT("屏幕画笔-Screen_Paint"),
		WS_POPUP, 0, 0, nScreenWidth, nScreenHeight,   //WS_POPUP 弹出风格的对话框 只有当对这个窗口的操作完成后才能进行其他操作
		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) {
	int nScreenWidth, nScreenHeight;
	long xPos, yPos;
	HDC hdc;
	static HDC hdcBuffer, auxiliaryBuffer;
	static HBITMAP BitMap, auxiliaryBitMap;
	static POINT pts[10000];
	static RECT erase = { 0,0,0,0 };
	static std::vector<HPEN> Pen;
	static HPEN hPenCur;
	static int i = 0;
	static int size = 20;
	static int leftDown = 0;
	static int rightDown = 0;

	/*至于为什么要乘1.25  是因为屏幕有放缩比例  我的屏幕放大125%*/
	nScreenWidth = GetSystemMetrics(SM_CXSCREEN) * 1.25;
	nScreenHeight = GetSystemMetrics(SM_CYSCREEN) * 1.25;

	switch (message) {
	case WM_CREATE:
		SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

		for (int i = 0; i <= 255; i += 255)
			for (int j = 0; j <= 255; j += 255)
				for (int k = 0; k <= 255; k += 255) {
					Pen.push_back(CreatePen(PS_SOLID, 3, RGB(i, j, k)));
				}

		hPenCur = Pen[4];//默认红色
		/*创建画布*/
		hdc = GetDC(NULL);
		CreatCanvas(hdc, hdcBuffer, BitMap);
		//CreatCanvas(hdc, auxiliaryBuffer, auxiliaryBitMap); 暂未用到
		ReleaseDC(NULL, hdc);
		return 0;
	case WM_KEYDOWN:
		/*换色 - 退出*/
		switch (wParam) {
		case 'D'://Dark-黑
			hPenCur = Pen[0];
			break;
		case 'B'://Blue-蓝
			hPenCur = Pen[1];
			break;
		case 'G'://Green-绿
			hPenCur = Pen[2];
			break;
		case 'C'://Cyan-青
			hPenCur = Pen[3];
			break;
		case 'R'://Red-红
			hPenCur = Pen[4];
			break;
		case 'P'://Pink-粉
			hPenCur = Pen[5];
			break;
		case 'Y'://Yellow-黄
			hPenCur = Pen[6];
			break;
		case 'W'://White-白
			hPenCur = Pen[7];
			break;
		case VK_ESCAPE://ESC-退出
			PostQuitMessage(0);
		}
		return 0;
	case WM_MOUSEMOVE:
		/*移动过程*/

		if (leftDown != 0) {//左键绘制
			xPos = LOWORD(lParam) * 1.25;
			yPos = HIWORD(lParam) * 1.25;
			pts[i].x = xPos;
			pts[i++].y = yPos;
			/*发送绘制消息 但不擦除背景*/
			InvalidateRect(hwnd, NULL, FALSE);
		}
		else if (rightDown != 0) {//右键擦除
			xPos = LOWORD(lParam) * 1.25;
			yPos = HIWORD(lParam) * 1.25;
			erase = { max(xPos - size, 0), max(yPos - size, 0), min(xPos + size, nScreenWidth), min(yPos + size, nScreenHeight) };
			InvalidateRect(hwnd, NULL, FALSE);
		}

		return 0;
	case WM_MOUSEWHEEL:
		if (GetAsyncKeyState(VK_CONTROL) & 0X8000) {//Ctrl + 滚轮 改变橡皮擦尺寸
			/*wParam 高位代表着滚轮滚动消息*/
			short val = HIWORD(wParam);
			if (val > 0)
				size = min(size + 2, 50);
			else if (val < 0)
				size = max(size - 2, 1);
		}
		return 0;
	case WM_LBUTTONDOWN://左键绘画
		/*开始操作*/
		leftDown = 1;
		i = 0;
		return 0;
	case WM_LBUTTONUP:
		/*结束操作*/
		leftDown = 0;
		return 0;
	case WM_RBUTTONDOWN://右键擦除
		rightDown = 1;
		return 0;
	case WM_RBUTTONUP:
		rightDown = 0;
		erase = { 0,0,0,0 };
		return 0;
	case WM_PAINT:
		/*绘制*/
		if (leftDown != 0) {//绘制
			hdc = GetDC(NULL);

			SelectObject(hdc, hPenCur);
			Polyline(hdc, pts, i);
			ReleaseDC(NULL, hdc);

			ValidateRect(hwnd, NULL);
		}
		else if (rightDown != 0) {//擦除
			hdc = GetDC(NULL);
			//BitBlt(hdc, erase.left, erase.top, erase.right, erase.bottom, hdcBuffer, 0, 0, SRCCOPY); //没太搞懂BitBlt 是怎么进行区域拷贝的  

			StretchBlt(hdc, erase.left, erase.top, erase.right - erase.left, erase.bottom - erase.top, hdcBuffer, erase.left, erase.top, erase.right - erase.left, erase.bottom - erase.top, SRCCOPY);

			ValidateRect(hwnd, NULL);
		}
		return 0;
	case WM_DESTROY:
		/*删除响应环境句柄和对象 并退出*/
		ReleaseDC(NULL, hdcBuffer);
		DeleteObject(BitMap);
		//ReleaseDC(NULL, auxiliaryBuffer);
		//DeleteObject(auxiliaryBitMap);
		for (int i = 0; i < Pen.size(); i++)
			DeleteObject(Pen[i]);
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

  

posted on 2023-09-06 19:14  lydstory  阅读(5)  评论(0编辑  收藏  举报

导航