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);
}
浙公网安备 33010602011771号