文章来源:C++技术网 原创文章版权所有,未经授权,禁止转载。
打造自己的屏幕截图软件
一、基本功能实现
首先,建立Win32带有模板的项目,然后在此基础上完成。
//全局变量
HDC g_srcMemDc; // - 源桌面截图
HDC g_grayMemDc; // - 灰度桌面截图
int screenW; // - 电脑屏幕的宽
int screenH; // - 电脑屏幕的高
RECT rect={0}; // - 画图的矩形区域
bool isSelect=false; // - 是否已经选中区域
bool isDown = false; // - 是否已经按下左键
1.让窗口全屏(以下为需要修改的几处代码)
a) HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_POPUP,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
b) ShowWindow(hWnd, SW_MAXIMIZE);
c) wcex.lpszMenuName = 0;
2.获取整个桌面图像
case WM_CREATE:
ScreenCapture();
break;
void ScreenCapture()
{
HDC disDc = CreateDC(L"DISPLAY", 0, 0, 0); // - 创建一个DC,与桌面相关的
screenW = GetDeviceCaps(disDc, HORZRES); // - 水平分辨率
screenH = GetDeviceCaps(disDc, VERTRES); // - 垂直分辨率
//获取桌面截图
g_srcMemDc = CreateCompatibleDC(disDc); // - 创建一个兼容DC(内存DC),与桌面DC相关的
HBITMAP hbitMap = CreateCompatibleBitmap(disDc, screenW, screenH); // - 模拟一张画布,其中没有数据
SelectObject(g_srcMemDc, hbitMap); // - 将画布选入内存DC,其中还是没有数据
//将桌面画到画布上,将屏幕的dc中的画图,拷贝至内存DC中
BitBlt(g_srcMemDc, 0, 0, screenW, screenH, disDc, 0, 0, SRCCOPY); // - 整个桌面被画到memDc上
//获取屏幕的灰度图片
g_grayMemDc=CreateCompatibleDC(disDc); // - 创建一个兼容DC,存放灰度图片
HBITMAP grayMap=CreateCompatibleBitmap(disDc,screenW,screenH); // - 模拟一张画布,其中没有数据
SelectObject(g_grayMemDc,grayMap); // - 将画图选入内存DC,其中还是没有数据的
BitBlt(g_grayMemDc,0,0,screenW,screenH,disDc,0,0,SRCCOPY); // - 将屏幕的dc中的画图,拷贝至内存DC中
CovertToGrayBitmap(grayMap,g_grayMemDc); // - 将彩色图片转换为灰度图片
DeleteObject(hbitMap);
DeleteObject(grayMap);
DeleteObject(disDc);
}
3.将图像放到窗口上,在窗口上画出矩形,鼠标移动的时候,画框能够跟着变化
case WM_PAINT: // - 屏幕绘制消息,画线条,画图片
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps); // - 代表当前窗口
//将灰度图像和变亮部分画到memDc中(兼容DC)
HDC memDc=CreateCompatibleDC(hdc);
HBITMAP bmp=CreateCompatibleBitmap(hdc,screenW,screenH);
SelectObject(memDc,bmp);
BitBlt(memDc,0,0,screenW,screenH,g_grayMemDc,0,0,SRCCOPY);
SelectObject(memDc,hBrush);
SelectObject(memDc,hPen);
if (isDown || isSelect)
{
BitBlt(memDc,rect.left,rect.top,rect.rig);// - 选中的区域变亮,将变亮的部分画到memDc
Rectangle(memDc,rect.left,rect.top,rect.right,rect.bottom);// - 画矩形
}
//最后将灰度和变亮的部分一起画到桌面
BitBlt(hdc,0,0,screenW,screenH,memDc,0,0,SRCCOPY);
DeleteObject(bmp);
DeleteObject(memDc);
EndPaint(hWnd, &ps);
}
break;
case WM_MOUSEMOVE:
{
if (isDown && !isSelect)
{
POINT pt;
GetCursorPos(&pt);
rect.right = ;
rect.bottom = ;
InvalidateRgn(hWnd, 0, false);
}
}
break;
4.没有被选中的区域变灰,选中了之后,应该变亮
//彩色图片到灰度图片的转换函数,比较复杂
void CovertToGrayBitmap(HBITMAP hSourceBmp,HDC sourceDc)
{
HBITMAP retBmp=hSourceBmp;
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
bm(BITMAPINFOHEADER);
GetDIBits(sourceDc,retBmp,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
BYTE* bits=new BYTE[bm];
GetBitmapBits(retBmp,bm,bits);
int bytePerPixel=4;//默认32位
i)
{
bytePerPixel=3;
}
for(DWORD i=0;i<bm;i+=bytePerPixel)
{
BYTE r=*(bits+i);
BYTE g=*(bits+i+1);
BYTE b=*(bits+i+2);
*(bits+i)=*(bits+i+1)=*(bits+i+2)=(r+b+g)/3;
}
SetBitmapBits(hSourceBmp,bm,bits);
delete[] bits;
}
5.双击选中区域,复制截图到粘贴板
case WM_LBUTTONDBLCLK: // - 双击复制
{
POINT pt;
GetCursorPos(&pt);
if (PtInRect(&rect, pt))
{
if (isSelect) // - 选中区域了才去拷贝
{
CopyBitmapToClipBoard(); // - 拷贝选中区域到粘贴板
}
}
InvalidateRgn(hWnd, 0, false);
ShowWindow(hWnd, SW_MINIMIZE);
isDown = false;
isSelect = false;
}
break;
6.其他处理,包括左键按下,左键弹起等
case WM_LBUTTONDOWN:
{
if (!isSelect) // - 如果没有选中才能按左键
{
POINT pt;
GetCursorPos(&pt); // - 得到当前光标位置
rect.left = ;
rect.top = ;
rect.right = ;
rect.bottom = ;
InvalidateRgn(hWnd, 0, false);
isDown = true;
}
}
break;
case WM_LBUTTONUP:
{
if (isDown == TRUE &&!isSelect) // - 鼠标按下了才计算矩形大小
{
POINT pt;
GetCursorPos(&pt); // - 得到当前光标位置
rect.right = ;
rect.bottom = ;
InvalidateRgn(hWnd, 0, false);
isSelect = true; // - 弹起的时候,表示区域已经选中
}
}
break;
二、其他扩展功能,其实不难,有兴趣的可以试试
1.最好是窗口不要出现,以快捷键的方式来做(全局的钩子)
2.加上一个托盘
三、效果展示
最后,如果有什么问题,欢迎交流,C++技术网作者个人中心有联系方式!
文章来源:C++技术网 原创文章版权所有,未经授权,禁止转载。
文章地址: