Duilib实现截图截取功能并保存为jpg图片

2023-02-05 22:10:51 3224人已围观 14已点赞 21人已收藏

简介本文向大家介绍一个C++实战项目:Duilib实现截图截取功能并保存为jpg图片,主要涉及Duilib界面开发、截取屏幕到位图、位图保存到文件、bmp格式图片转jpg等知识,具有一定的C++实战价值,感兴趣的朋友可以参考一下。

示例工程介绍

Duilib界面开发,屏幕截取,位图保存到文件,bmp转jpg

点击截图按钮,开始截图:

void CMainWnd::Notify(DuiLib::TNotifyUI &msg)
{
	if (msg.sType == _T("windowinit"))
	{
	}
	else if (msg.sType == _T("click"))
	{
		CDuiString sName = msg.pSender->GetName();
		if (sName.CompareNoCase(_T("btnClose")) == 0)
		{
			Close(IDOK);
		}
		else if (sName.CompareNoCase(_T("btnCapture")) == 0)
		{
			ShowWindow(false);
			int cx = GetSystemMetrics(SM_CXSCREEN);
			int cy = GetSystemMetrics(SM_CYSCREEN);
			CScreenshotsWnd ScreenshotsWnd;
			ScreenshotsWnd.Create(m_hWnd, _T("ScreenshotsWnd"), UI_WNDSTYLE_DIALOG, UI_WNDSTYLE_EX_DIALOG);
			::SetWindowPos(ScreenshotsWnd.GetHWND(), NULL, 0, 0, cx, cy, SWP_SHOWWINDOW);
			ScreenshotsWnd.ShowModal();
			CString strCapImgFile = ScreenshotsWnd.m_strSaveImgPath;
			if (!strCapImgFile.IsEmpty())
			{
				CUIProInterface::GenericPromptWnd(NULL, _T("截图完成!"), 1);
			}
			ShowWindow(true);
		}
	}
}

弹出截图界面:

Duilib界面开发,屏幕截取,位图保存到文件,bmp转jpg

点击完成截图:

Duilib界面开发,屏幕截取,位图保存到文件,bmp转jpg

会在主程序目录下保存jpg截图文件

技术关键点

  • 截取屏幕并保存到位图
// 截取屏幕到位图
HBITMAP CScreenshotsWnd::CopyScreenToBitmap(LPRECT lpRect)   // lpRect   代表选定区域   
{
	HDC   hScrDC, hMemDC; //屏幕和内存设备描述表   
	HBITMAP   hBitmap, hOldBitmap;//位图句柄   
	int   nX, nY, nX2, nY2; //选定区域坐标   
	int   nWidth, nHeight; //位图宽度和高度   
	int   xScrn, yScrn; //屏幕宽度和高度   
	//WriteLog("截图区域:%d,%d.,%d,%d", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
	//确保选定区域不为空矩形   
	if (IsRectEmpty(lpRect))
	{
		return   NULL;
	}

	//为屏幕创建设备描述表   
	hScrDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
	//为屏幕设备描述表创建兼容的内存设备描述表   
	hMemDC = CreateCompatibleDC(hScrDC);   //或者::CreateCompatibleDC(NULL)   

										   //获得选定区域坐标     
	nX = lpRect->left;
	nY = lpRect->top;
	nX2 = lpRect->right;
	nY2 = lpRect->bottom;

	//获得屏幕宽度和高度   
	xScrn = GetDeviceCaps(hScrDC, HORZRES);
	yScrn = GetDeviceCaps(hScrDC, VERTRES);

	//确保选定区域是可见的   
	if (nX < 0)
		nX = 0;
	if (nY < 0)
		nY = 0;
	if (nX2 > xScrn)
		nX2 = xScrn;
	if (nY2 > yScrn)
		nY2 = yScrn;

	nWidth = nX2 - nX;
	nHeight = nY2 - nY;

	//创建一个与屏幕设备描述表兼容的位图     
	hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);

	//把新位图选到内存设备描述表中     
	hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

	//把屏幕设备描述表拷贝到内存设备描述表中   
	BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);

	//得到屏幕位图的句柄   
	hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);

	//清除   
	DeleteDC(hScrDC);
	DeleteDC(hMemDC);
	return   hBitmap;   //返回位图句柄  
}
  • 保存位图到文件
// 保存位图到文件
int CScreenshotsWnd::SaveBitmapToFile(HBITMAP hBitmap, LPCWSTR lpFileName)
{           
	WORD   wBitCount;   //位图中每个像素所占字节数     
	// 定义调色板大小,位图中像素字节大小,位图文件大小,写入文件字节数     
	DWORD   dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten;
	BITMAP   Bitmap; //位图属性结构     
	BITMAPFILEHEADER   bmfHdr;   //位图文件头结构     
	BITMAPINFOHEADER   bi;   //位图信息头结构     
	HANDLE   fh;   //定义文件,分配内存句柄,调色板句柄   
	LPSTR   lpbk, lpmem;

	wBitCount = 32;
	//设置位图信息头结构     
	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = Bitmap.bmWidth;
	bi.biHeight = Bitmap.bmHeight; //为负,正向的位图;为正,倒向的位图   
	bi.biPlanes = 1;
	bi.biBitCount = wBitCount;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;
	dwBmBitsSize = ((Bitmap.bmWidth*wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

	//创建位图文件
	fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	if (fh == INVALID_HANDLE_VALUE)
		return   FALSE;
	//设置位图文件头     
	bmfHdr.bfType = 0x4D42;   //   "BM"     
	dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;
	bmfHdr.bfSize = dwDIBSize;
	bmfHdr.bfReserved1 = 0;
	bmfHdr.bfReserved2 = 0;
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

	//写入位图文件头
	WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
	//写入位图信息头   
	WriteFile(fh, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);

	//获取位图阵列
	lpmem = new   char[dwBmBitsSize];
	lpbk = (LPSTR)   new   char[dwBmBitsSize];
	GetBitmapBits(hBitmap, dwBmBitsSize, lpmem);//正向的内存图象数据  

												//转化为倒向数据(仅在bmHeight为正时需要)   
	for (int i = 0; i < Bitmap.bmHeight; i++)
	{
		memcpy(lpbk + Bitmap.bmWidth*i * 4, lpmem + Bitmap.bmWidth*(Bitmap.bmHeight - i - 1) * 4, Bitmap.bmWidth * 4);
	}
	//写位图数据
	WriteFile(fh, lpbk, dwBmBitsSize, &dwWritten, NULL);

	//清除     
	delete[]lpbk;
	delete[]lpmem;

	CloseHandle(fh);
	return   TRUE;
}
  • bmp文件转jpg

采用libjpeg库实现bmp文件转jpg

int CBmp2Jpeg::Bmp2Jpeg(const char *bmp, const char *jpeg)
{
	unsigned char *brga = nullptr; //指向位图buffer的全局指针,window下像素格式: BGRA(4个字节)
	int width = 0, height = 0, depth = 0;

	if (ReadBmp(bmp, &brga, width, height, depth) < 0)
	{
		return -1;
	}

	unsigned char *rgb = new unsigned char[width * abs(height) * depth / 8];
	Bgra2Rgb(brga, width, height, depth / 8, rgb);

	int ret = SaveJpeg(jpeg, rgb, width, abs(height), 3);

	delete[] brga;
	delete[] rgb;
	brga = nullptr;
	rgb = nullptr;
	return ret;
}


源码下载
  • 最近更新:   2022-06-14开发环境:   Visual Studio 2015
  • 源码大小:   1.37MB下载次数:  16 

更多为你推荐