问题:如图所示的OpenGL场景、View、CDialogBar三个界面的内容保存成图片然后拼合成一张图
思路:
分四步
一、View视图界面保存
利用BitBlt函数将界面拷贝到内存DC中

// 将MFC的某个view保存为图片
BOOL CImageIO::saveAsImage(CString imageFormat, CString savePath)
{if (hdc != NULL  && destRect != NULL){HDC hmemDC = ::CreateCompatibleDC(hdc);hBmp = ::CreateCompatibleBitmap(hdc, destRect.Width(), destRect.Height());HANDLE hOld = ::SelectObject(hmemDC, hBmp);Graphics graphic(hmemDC);SelectObject(hmemDC, hBmp);// CDC类的BitBlt就是MFC下专门用来操作位图的,将两张位图分别导入到CBitmap做成内存DC后,一次BitBlt到设备DC上,就完成了图片的叠加,叠加效果,由BitBlt函数的光栅代码参数决定,详细看这个函数的帮助(内容不少),可以熟悉不同的叠加方式BitBlt(hmemDC, 0, 0, destRect.right, destRect.bottom, hdc, 0, 0, SRCCOPY);  //下面进行各种文字、图形、图片的绘制Bitmap bitmap(hBmp, NULL);CLSID clsID;//保存不同格式的(.jpg,bmp,png)的图片需要不同的CLSID, imageFormat为用户期望保存的图片格式if (_T("jpg") == imageFormat.MakeLower()){GetEncoderClsid(L"image/jpeg", &clsID);}else if (_T("bmp") == imageFormat.MakeLower()){GetEncoderClsid(L"image/bmp", &clsID);}else if (_T("png") == imageFormat.MakeLower()){GetEncoderClsid(L"image/png", &clsID);}// char*转WCHAR*char *p = (LPSTR)(LPCSTR)savePath;wstringstream wss;wss << p;bitmap.Save(wss.str().c_str(), &clsID, NULL);//bitmap.Save(L"D:\\ggg.jpg", &clsID, NULL);::SelectObject(hmemDC, hOld);::DeleteObject(hBmp);::DeleteDC(hmemDC);return TRUE;}else{return FALSE;}
}

其中用到的GetEncoderClsid函数为

int CImageIO::GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{UINT num = 0;  // number of image encodersUINT size = 0;  // size of the image encoder array in bytesImageCodecInfo* pImageCodecInfo = NULL;Gdiplus::GetImageEncodersSize(&num, &size);if (size == 0){return -1;}pImageCodecInfo = (ImageCodecInfo*)(malloc(size));if (pImageCodecInfo == NULL){return -1;}Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);for (UINT j = 0; j< num; ++j){//if (_tcscmp(pImageCodecInfo[j].MimeType, format1.str().c_str) == 0)//if (pImageCodecInfo[j].MimeType == format)if (wcscmp(pImageCodecInfo[j].MimeType, format))  // char*用strcmp作对比,而WCHAR*用wcscmp函数,这个是strcmp对应的UNICODE版本{*pClsid = pImageCodecInfo[j].Clsid;free(pImageCodecInfo);return j;}}free(pImageCodecInfo);return -1;
}

二、CDialogBar界面用同View的方法调用saveAsImage函数即可

三、OpenGL场景
若用上面的方法得到的是白板,这里要用glReadPixels函数来保存图片

#define BITMAP_ID 0x4D42
//  将opengl场景保存为图片
bool CImageIO::SnapScreen(int width, int height, const char *file)
{byte *image;          //接受图像数据FILE *fp;            //文件指针BITMAPFILEHEADER FileHeader;    //接受位图文件头BITMAPINFOHEADER InfoHeader;    //接受位图信息头FileHeader.bfType = BITMAP_ID;                                                  //ID设置为位图的id号FileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);      //实际图像数据的位置在文件头和信息头之后FileHeader.bfReserved1 = 0;                                                    //必须设置为0FileHeader.bfReserved2 = 0;                                                    //必须设置为0FileHeader.bfSize = height*width * 24 + FileHeader.bfOffBits;                      //BMP图像文件大小InfoHeader.biXPelsPerMeter = 0;                                              //水平分辨率,这里暂时设为0就是InfoHeader.biYPelsPerMeter = 0;                                              //垂直分辨率,这里暂时设为0就是InfoHeader.biClrUsed = 0;                                                    //图像使用的颜色,这里暂时设为0就是InfoHeader.biClrImportant = 0;                                                //重要的颜色数,这里暂时设为0就是                        //垂直分辨率,这里暂时设为0就是InfoHeader.biPlanes = 1;                //必须设置为1InfoHeader.biCompression = BI_RGB;                                              //设置为BI_RGB时,表示图像并没有彩色表InfoHeader.biBitCount = 24;                                                    //图像的位数InfoHeader.biSize = sizeof(BITMAPINFOHEADER);                                  //结构体的大小InfoHeader.biHeight = height;InfoHeader.biWidth = width;InfoHeader.biSizeImage = height*width * 4;image = (byte *)malloc(sizeof(byte)*InfoHeader.biSizeImage);if (image == NULL){free(image);printf("Exception: No enough space!\n");return false;}//像素格式设置4字节对齐glPixelStorei(GL_UNPACK_ALIGNMENT, 4);//接收出像素的数据glReadPixels(0, 0, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);fp = fopen(file, "wb");if (fp == NULL){printf("Exception: Fail to open file!\n");return false;}fwrite(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);fwrite(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);fwrite(image, InfoHeader.biSizeImage, 1, fp);free(image);fclose(fp);return true;
}

四、最终如何实现开始提到的问题呢?
1)利用SnapScreen保存opengl场景为panorama.bmp
2)利用BitBlt创建内存DC来获取View和CDialogbar的界面图片,然后加载panorama.bmp进行拼合。

// 将三张bmp图片拼接成一个
BOOL CImageIO::stitchBMP(CString imageFormat, CString savePath, int  width, int height, HDC skylineHdc, HDC infoHdc, CRect skylineRect, CRect infoRect)
{HDC hmemDC = ::CreateCompatibleDC(skylineHdc);hBmp = ::CreateCompatibleBitmap(skylineHdc, skylineRect.Width() + infoRect.Width(), infoRect.Height());HANDLE hOld = ::SelectObject(hmemDC, hBmp);Graphics graphic(hmemDC);SelectObject(hmemDC, hBmp);//下面进行各种文字、图形、图片的绘制// CDC类的BitBlt就是MFC下专门用来操作位图的,将两张位图分别导入到CBitmap做成内存DC后,一次BitBlt到设备DC上,就完成了图片的叠加,叠加效果,由BitBlt函数的光栅代码参数决定,详细看这个函数的帮助(内容不少),可以熟悉不同的叠加方式BitBlt(hmemDC, 0, 0, skylineRect.right, skylineRect.bottom, skylineHdc, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DCBitBlt(hmemDC, skylineRect.Width(), 0, infoRect.right, infoRect.bottom, infoHdc, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DC//HDC hmemDC2 = ::CreateCompatibleDC(skylineHdc);//CBitmap m_bitmap;  //对象//m_bitmap.LoadBitmap(IDB_BITMAP_TREESTATE);//加载//HBITMAP hbm = (HBITMAP)m_bitmap;//SelectObject(hmemDC2, hbm);//BitBlt(hmemDC, 0, skylineRect.Height(), 200, 200, hmemDC2, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DCHDC hmemDC2 = ::CreateCompatibleDC(skylineHdc);HBITMAP hPanoBmp = (HBITMAP)LoadImageA(NULL, "D:\\panorama.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);// 获取HBITMAP图片信息BITMAP bitbmpInfo;GetObject(hBmp, sizeof(BITMAP), (LPBYTE)&bitbmpInfo);SelectObject(hmemDC2, hPanoBmp);BitBlt(hmemDC, 0, skylineRect.Height(), bitbmpInfo.bmWidth, bitbmpInfo.bmHeight, hmemDC2, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DC//StretchBlt(hmemDC, 0, skylineRect.Height(), skylineRect.Width(), infoRect.Height() -skylineRect.Height(), hmemDC2, 0, 0, bitbmpInfo.bmWidth, bitbmpInfo.bmHeight, SRCCOPY);  // 将hdc拷贝到内存DC//CMainFrame * mainframe = (CMainFrame *)AfxGetMainWnd();//HDC pHdc = mainframe->pParonamaView->GetDC()->GetSafeHdc();//CRect prc;//mainframe->pParonamaView->GetClientRect(&prc);//BitBlt(hmemDC, 0, skylineRect.Height(), prc.right, prc.bottom, pHdc, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DC//CBitmap m_bitmap;  //对象//m_bitmap.LoadBitmap(IDB_BITMAP_TREESTATE);//加载//HBITMAP hbm = (HBITMAP)m_bitmap;//HDC memDC;////SelectObject(memDC, hbm);//BitBlt(hmemDC, 0, skylineRect.Height(), 200, 200, memDC, 0, 0, SRCCOPY);  // 将hdc拷贝到内存DC//HANDLE hf = CreateFile(//  "temp\panorama.bmp", GENERIC_WRITE, FILE_SHARE_READ, NULL,//  CREATE_ALWAYS, NULL, NULL);Bitmap bitmap(hBmp, NULL);CLSID clsID;//保存不同格式的(.jpg,bmp,png)的图片需要不同的CLSID, imageFormat为用户期望保存的图片格式if (_T("jpg") == imageFormat.MakeLower()){GetEncoderClsid(L"image/jpeg", &clsID);}else if (_T("bmp") == imageFormat.MakeLower()){GetEncoderClsid(L"image/bmp", &clsID);}else if (_T("png") == imageFormat.MakeLower()){GetEncoderClsid(L"image/png", &clsID);}// char*转WCHAR*char *p = (LPSTR)(LPCSTR)savePath;wstringstream wss;wss << p;bitmap.Save(wss.str().c_str(), &clsID, NULL);//bitmap.Save(L"D:\\ggg.jpg", &clsID, NULL);::SelectObject(hmemDC, hOld);::DeleteObject(hBmp);::DeleteDC(hmemDC);return TRUE;
}

输出结果如下图:

MFC 视图-OpenGL场景-CDialogBar三个界面保存为图片相关推荐

  1. OpenGL入门学习[三]

    OpenGL入门学习[三] http://xiaxveliang.blog.163.com/blog/static/2970803420126246501930/ OpenGL入门学习[十一] 我们在 ...

  2. MFC视图切换大全总结

    单纯视图之间的切换 单文档多视图切换是我在学习MFC中遇到的一个老大难问题,在今天总算是一一破解了.我觉得视图切换分为三个等级,第一是在未切分窗格的情况下切换视图类:第二是在分割窗格的一个窗格内实行视 ...

  3. 《MFC游戏开发》笔记三 游戏贴图与透明特效的实现

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9313239 作者:七十一雾央 新浪微博:http:// ...

  4. OpenGL纹理本质(三)

    几个月前调试3D纹理时发现一个有趣的问题:同样的3D HW lib库在android2.2系统上可以正常工作,但在2.3系统上却不能工作,显示的图像白屏,调试了几天才将问题定位并解决,解决方法很简单: ...

  5. Android 仿PhotoShop调色板应用(三) 主体界面绘制

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 仿PhotoShop调色板应用(三) 主体界面绘制    关于PhotoShop调色板应用的实现我总结了两个最核心的部分:   1 ...

  6. OpenGL Cubic Bezier三次贝塞尔曲线修补实例

    OpenGL Cubic Bezier三次贝塞尔曲线修补 先上图,再解答. 正常显示 按下C键 按下W键 按下X键 完整主要的源代码 源代码剖析 先上图,再解答. 正常显示 按下C键 按下W键

  7. 计算机图形学 opengl版本 第三版------胡事民 第四章 图形学中的向量工具

    计算机图形学 opengl版本 第三版------胡事民 第四章  图形学中的向量工具 一   基础 1:向量分析和变换   两个工具  可以设计出各种几何对象 点和向量基于坐标系定义 拇指指向z轴正 ...

  8. Android4.2.2 Gallery2源码分析(9)——三个界面的跳转

    Gallery浏览图片除开编辑界面,主要有三个界面:即起始页,相册簿集合页面(AlbumSetPage):点击某个相册进入该相册的所有图片页面(AlbumPage)和再点击某张具体图片之后的图片浏览页 ...

  9. MFC绘制二次、三次准均匀B样条曲线

    MFC绘制二次.三次准均匀B样条曲线 二次准均匀B样条曲线 三次准均匀B样条曲线 节点矢量在两端K+1次重复,即可以使得B样条的端点具有Bezier曲线端点的性质.参考之前的文章,将控制点与节点分别修 ...

最新文章

  1. jQuery MD5加密
  2. 1.FPGA开发软件安装——Vivado
  3. 如何使用Proxy模式及Java内建的动态代理机制
  4. JSF JQUERY 使用datepicker
  5. Extract Subclass(提炼子类)
  6. 【OpenCV 例程200篇】61. 导向滤波(Guided filter)
  7. php中的CURL库
  8. 诺基亚手机新品发布定档 6 月 11 日!Nokia C20 Plus 即将到来
  9. Activity生命周期方法的调用顺序project与測试日志
  10. IntelliJ IDEA、Kotlin、PyCharm 背后公司 JetBrains 遭美国调查!
  11. php判断浏览器和语言
  12. 招聘网站数百万条敏感数据泄露,简历、×××扫描件统统曝光
  13. Hive编程指南(含目录,高清,免费)
  14. Zookeeper四字监控命令使用总结
  15. Linux下通用打印系统CUPS使用教程
  16. 6个usb口服务器无响应,USB接口不能用(没反应)修复方法
  17. python评价回归模型指标:决定系数R2,相关系数R,均方误差MSE,均方根误差RMSE
  18. 名帖07 赵宧光 篆书《篆书四箴册》
  19. iphone ios 视频特效,视频合成
  20. 教务(选课)管理系统

热门文章

  1. 爱可信携手Marvell展示爱可信Linux平台
  2. 关于excel导入带图片
  3. 简单js模仿浏览器crtl+f功能
  4. 达梦数据库-国产的荣光
  5. 手术麻醉信息管理系统源码,生成规范麻醉文书,自动信息采集
  6. string大小写转换
  7. iPhone7黔驴技穷,Moto Z另辟蹊径,谁才能引领行业创新?
  8. 塞班微信登录显示服务器繁忙,塞班系统彻底告别 已无法登陆QQ/微信
  9. 第五人格服务器维修中怎么进,第五人格怎么进不去_进不去游戏原因汇总及解决办法_软吧...
  10. 深度长文:Power Automation 帮助企业实现数字化转型