简介本文向大家介绍一个C++实战项目:Duilib实现截图截取功能并保存为jpg图片,主要涉及Duilib界面开发、截取屏幕到位图、位图保存到文件、bmp格式图片转jpg等知识,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
点击截图按钮,开始截图:
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);
}
}
}
弹出截图界面:
点击完成截图:
会在主程序目录下保存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;
}
采用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;
}
本文介绍一个C++代码实战例子:C++实现图片等比例缩放,感兴趣的朋友可以参考一下。
本文向大家介绍OpenGL绘制文字(支持中文),感兴趣的朋友可以参考一下。
本文向大家介绍一个C++实战项目:在Duilib窗口中使用OpenGL绘制图形示例,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
本文向大家介绍一个C++实战项目:C++基于OpenGL绘制一个随鼠标旋转长方体,并支持鼠标滚轮缩小放大,具有一定的C++实战价值,感兴趣的朋友可以参考一下。
本文向大家介绍OpenGL一个函数实现抗锯齿,感兴趣的朋友可以参考一下。
本文向大家介绍一个C++实战项目:OpenGL实现在透明窗口上绘制图形,具有一定的C++实战价值,感兴趣的朋友可以参考一下。