当前位置: 首页 > news >正文

记录GDI+保存位图

记录使用GDI+保存位图

我做的一个项目上有一个需求:以图片的形式保存当前窗口的内容。刚开始我使用GDI中的函数,手动填充位图的内容,并写入到文件中,不知道由于什么原因,无法保存。遂使用GDI+来保存位图。其中也有许多坑,但最终也实现了该功能。现记录下来,希望对有类似需求的读者有帮助。

基本思路

通过GDI+的文档我们可以得知,Gdiplus::Bitmap类可以通过一个位图句柄构造,且该类继承了Gdiplus::Image类,Gdiplus::Image类中有一个Save方法,可以将对象中的图片内容保存到文件中。总结来说就是两步:

  • 构造正确的Gdiplus::Bitmap对象
  • 调用Save方法保存位图

构造Gdiplus::Bitmap对象

要构造正确的Gdiplus::Bitmap对象,需要先初始化一个位图句柄。该句柄指向的位图就是我们需要保存的窗口截屏。接下来就说说如何得到窗口内容对应的位图。

将窗口客户区的内容保存到位图中

如何通过一个窗口句柄获得存有其客户区的位图呢?参见以下代码:

void MyBitmap::GetBitmap()
{RECT rect;::GetClientRect(this->hwnd, &rect); //获取窗口客户区的矩形int width = rect.right - rect.left; //位图的宽度int height = rect.bottom - rect.top; //位图的高度HDC hdc = GetDC(this->hwnd); //获取窗口的设备上下文HDC hdcMem = CreateCompatibleDC(hdc); //创建兼容的内存dc,这个dc用作缓冲区,接收hdc的内容,相当于画板HBITMAP hBitmap, hOldBitmap;hBitmap = CreateCompatibleBitmap(hdc, width, height); //创建兼容位图,相当于画布hOldBitmap = static_cast<HBITMAP>(SelectObject(hdcMem, hBitmap)); //此时hBitmap将用于存储hdc的位图BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, SRCCOPY); //复制hdc的内容到hdcMem中,相当于绘制画布hBitmap = static_cast<HBITMAP>(SelectObject(hdcMem, hOldBitmap)); //得到获取的位图this->hBmp = hBitmap; //设置该成员变量以便后续使用//释放资源ReleaseDC(this->hwnd, hdc);DeleteDC(hdcMem);DeleteObject(hOldBitmap);
}

初始化Gdiplus

Gdiplus::Bitmap中的save方法中第二个参数是一个编码器的id,我们需要获取位图编码器的id。

UINT num, size;
Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
if (Gdiplus::GetImageEncodersSize(&num, &size) != Gdiplus::Status::Ok) this->errhandler(TEXT("GetImageEncodercInfo error"));
if (size == 0) this->errhandler(TEXT("没有可用的编码器"));pImageCodecInfo = reinterpret_cast<Gdiplus::ImageCodecInfo*>(malloc(size));
if (pImageCodecInfo == NULL) this->errhandler(TEXT("mallco error"));
if ((res = Gdiplus::GetImageEncoders(num, size, pImageCodecInfo)) != Gdiplus::Status::Ok)
{this->errhandler(err_msg);
}CLSID clsId;
for (UINT i = 0; i < num; i++)
{if (wcscmp(pImageCodecInfo[i].MimeType, L"image/bmp")) //遍历编码器,匹配bmp编码器{clsId = pImageCodecInfo[i].Clsid;free(pImageCodecInfo);break;}
}

初始化Gdiplus::Bitmap对象

有了有效的位图句柄和Clsid,我们就可以初始化一个Gdiplus::Bitmap对象了:

Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(this->hBmp, NULL);

调用Save方法保存位图并清理资源

if ((res = bitmap->Save(this->filename, &clsId, NULL)) != Gdiplus::Status::Ok)
{this->errhandler(err_msg);
}delete bitmap; //调用Gdiplus::GdiplusShutdown之前必须清理GDI+对象,否则会引起地址访问错误
Gdiplus::GdiplusShutdown(gdiplusToken);

如此就可以保存某一个窗口的客户区内容了。

http://www.dtcms.com/a/573411.html

相关文章:

  • 市值分析:半导体龙头的估值边界在哪里?——以NVIDIA为案例的概率化拆解
  • 内蒙古创意网站开发微网站建设服务商
  • 网站做全景图极速网站建设定制
  • wordpress新增站点盐城整站优化
  • 网络安全常见的框架漏洞
  • 停车场管理系统基础知识与原理
  • 安卓进阶——跨进程通信
  • 连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文
  • 自己做的网站怎么添加文档成都装修公司哪家口碑最好
  • 视频网站代言人建筑施工企业专职安全生产管理员
  • 保姆级教程 | 麒麟系统安装Edge浏览器
  • HAL库uint8_t,uint16_t,uint32_t类型报错error: #20: identifier “uint32_t“ is undefined
  • Java LinkedList集合全面解析:双向链表的艺术与实战
  • 【MySQL】--- 事务4种特性、隔离级别、MVCC
  • 上信考:【数据科学技术及应用】考试大纲题型示例、例题解析、模拟卷答案
  • 做游戏网站需要哪些许可黄页号码标记申诉
  • 网站建设钅金手指排名平面设计接单赚钱平台
  • 凡科轻站小程序怎么样全国十大软件开发培训机构
  • 北京多语言网站建设微网站 .net
  • 山东滨州网站建设公司做淘客都有什么网站
  • 免杀技巧 - 早鸟注入详细学习笔记
  • Tomcat安装和Servlet项目创建【保姆教程】
  • C++入门(二) (算法竞赛)
  • 【Svelte】如果是导入的组件,如何为其添加样式?
  • SpringBoot 实战(四十)集成 Statemachine
  • 网站制作教程手机杭州酒店网站设计公司推荐
  • 【设计题】如何实现限流器
  • 场外衍生品架构解析:TRS收益互换与场外个股期权的技术实现
  • 小程序定制开发实战:需求拆解、UI 设计与个性化功能落地流程
  • MATLAB基于变权理论和灰色云模型的海岛旅游地生态安全评价