当前位置:C++技术网 > 资讯 > 打造自己的屏幕截图软件(QQ截图功能实现)

打造自己的屏幕截图软件(QQ截图功能实现)

更新时间:2016-03-24 12:37:40浏览次数:1+次

打造自己的屏幕截图软件

一、基本功能实现

首先,建立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.right-rect.left,rect.bottom-rect.top,g_srcMemDc,rect.left,rect.top,SRCCOPY);// - 选中的区域变亮,将变亮的部分画到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 = pt.x;
                rect.bottom = pt.y;
                InvalidateRgn(hWnd, 0, false);
            }
	}
	break;

4.没有被选中的区域变灰,选中了之后,应该变亮

//彩色图片到灰度图片的转换函数,比较复杂
void CovertToGrayBitmap(HBITMAP hSourceBmp,HDC sourceDc)  
{
    HBITMAP retBmp=hSourceBmp;
    BITMAPINFO bmpInfo;
    ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
    bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
    GetDIBits(sourceDc,retBmp,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);

    BYTE* bits=new BYTE[bmpInfo.bmiHeader.biSizeImage];
    GetBitmapBits(retBmp,bmpInfo.bmiHeader.biSizeImage,bits);

    int bytePerPixel=4;//默认32位
    if(bmpInfo.bmiHeader.biBitCount==24)
    {
        bytePerPixel=3;
    }
    for(DWORD i=0;i<bmpInfo.bmiHeader.biSizeImage;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,bmpInfo.bmiHeader.biSizeImage,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 = pt.x;
			rect.top = pt.y;
			rect.right = pt.x;
			rect.bottom = pt.y;
			InvalidateRgn(hWnd, 0, false);
			isDown = true;
		}
	}
		break;
	case WM_LBUTTONUP:
	{
		if (isDown == TRUE &&!isSelect)  // - 鼠标按下了才计算矩形大小
		{
			POINT pt;
			GetCursorPos(&pt);  // - 得到当前光标位置
			rect.right = pt.x;
			rect.bottom = pt.y;
			InvalidateRgn(hWnd, 0, false);
			isSelect = true;  // - 弹起的时候,表示区域已经选中
		}
	}
		break;
二、其他扩展功能,其实不难,有兴趣的可以试试
1.最好是窗口不要出现,以快捷键的方式来做(全局的钩子)
2.加上一个托盘
三、效果展示
    最后,如果有什么问题,欢迎交流,C++技术网作者个人中心有联系方式!