zoukankan      html  css  js  c++  java
  • 一种在MFC程序上显示jpeg图片的方法(二)曙光乍现

    上机环境vs2015 win7 64位

    先上图,是不是扑面就感受到一股浓浓的俄罗斯风情,hehehehe~

     截图是基于MFC实现的带有插图的对话框窗口,就这么一个小破功能,折腾我一礼拜,问题集中在两方面:

    1.如何加载jpeg图片?加载bmp的案例汗牛充栋,但加载jpeg的确实不多

    2.在窗口的指定区域显示加载的jpeg图片,图中的控件布局力求表达这种意思,当然也会根据需要显示在窗口的右上角等各种场景

    • 关于问题1:

    其实,早在用vc++6.0的时代,就已经有了用IPicture接口从堆区接收图片流数据的方案,一些案例丰富的书 诸如《vc++ 开发实战》就提供了这样的案例,当然,在vs2008以后的IDE上运行,由于C++标准的演进,代码需要微调

    所以市面上大多vc++书籍,仍显得鸡肋。大多数以vc++6.0为平台的书籍弃之可惜(案例丰富),用起来对于初学者而言又是一场噩梦(在新的vs IDE运行案例代码需要微调,这需要一定C++和至少vs2008以后版本的VC基础)

    无论如何,这种加载jpeg图片的流程可以概括为:

    1. 声明CFile变量(文件描述符),打开一个硬盘上的图片
    2. 获取文件的大小(也不妨说是长度)
    3. 声明一个堆句柄(VC类型HGLOBAL)
    4. 根据文件大小(长度)为堆句柄分配空间(GlobalAlloc)
    5. 声明一个LPVOID类型指针,用指针锁定分配的堆空间----GlobalLock
    6. 用文件描述符通过LPVOID类型指针把图片信息写入堆空间(尽管调用的相关函数使用了Read这个词,但我理解是从文件xxxx读取然后写入堆空间),完成后关闭文件描述符。
    7. 释放LPVOID类型指针锁定的堆空间
    8. 调用CreateStreamOnHGlobal把堆空间内容整合成流式信息,给IStream类的变量接收
    9. 调用OleLoadPicture函数把图片流信息加载到IPicture接口
    10. 声明OLE_XSIZE_HIMETRIC 类型的变量用于接收图片文件的宽度像素信息
    11. 声明OLE_YSIZE_HIMETRIC类型变量用于接收图片文件高度的像素信息
    CDC *pdc = NULL;
    pdc = GetDlgItem(IDC_STATIC)->GetDC();
    this->file.Open(_T("E:\f575becf4c96.jpg"), CFile::modeReadWrite);//在vc6.0的实现中,没有用到可变宽度字符处理函数_T()
    this->len = this->file.GetLength();
    this->pdata = NULL;
    this->hMem=GlobalAlloc(GMEM_MOVEABLE, this->len);
    this->pdata = GlobalLock(this->hMem);
    this->file.Read(this->pdata, this->len);//vc6.0的实现为ReadHuge
    this->file.Close();
    GlobalUnlock(this->hMem);
    CreateStreamOnHGlobal(this->hMem, TRUE, &(this->picstream));
    OleLoadPicture(this->picstream, this->len, TRUE, IID_IPicture, (LPVOID*)&(this->mypic));
    this->mypic->get_Height(&this->picheight);
    this->mypic->get_Width(&this->picwidth);
    CRect zrect;
    pdc->GetWindow()->GetWindowRect(&zrect);
    int iWndWidth = zrect.right - zrect.left;
    int iWndHeight = zrect.bottom - zrect.top;
    this->mypic->Render(GetDlgItem(IDC_STATIC)->GetDC()->m_hDC,0,0, iWndWidth, iWndHeight,0, this->picheight, this->picwidth,-(this->picheight),NULL );
    • 关于问题2

    大多数资料介绍的CDC设备都用于画图,尽管jpeg图像也是画出来的,但我还是想做出区分,多数资料介绍的方法是,声明一个矩形的区域,声明一个有颜色的画刷,然后声明一个DC设备上下文,通过FillRect方法,用DC拿起画刷在矩形区域填充

    而在这个问题的处理上其流程大致可以梳理为

    1.声明设备类型指针

    2.用设备类型指针获取窗口上的控件(picture control) ID,用来生成一个渲染图像的设备(画图的画布) 。

    3.声明一个CRect类的变量,声明的设备指针变量,通过调用GetWindow(),GetWidowRect(&zrect)把picture Control控件的宽高信息传递给CRect类的实例zrect

    4.通过rect计算控件的高和宽,因为rect可能相对于窗口位置发生偏移,所以可靠的算法是rect的右边坐标减去左边坐标,得出宽,底边坐标减去上边坐标得到高

    5.渲染图片,Render()参数列表中的第4个,第5个参数就是算出的控件的宽和高。

    //......
    CDC *pdc = NULL;
    //........
    CRect zrect;
    pdc->GetWindow()->GetWindowRect(&zrect);
    //...........
    int iWndWidth = zrect.right - zrect.left;        
    int iWndHeight = zrect.bottom - zrect.top;
    this->mypic->Render(GetDlgItem(IDC_STATIC)->GetDC()->m_hDC,0,0, iWndWidth, iWndHeight,0, this->picheight, this->picwidth,-(this->picheight),NULL );

    当然,上述代码还需要及时释放堆内存 GlobalFree(hMem),以及IPicture指针(通过mypic->Release())

  • 相关阅读:
    POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
    POJ 3083 Children of the Candy Corn bfs和dfs
    POJ 2049 Finding Nemo bfs 建图很难。。
    POJ 2513 Colored Sticks 字典树、并查集、欧拉通路
    POJ 1013 Counterfeit Dollar 集合上的位运算
    POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
    无聊拿socket写的100以内的加法考试。。。
    POJ 1753 Flip Game
    初学socket,c语言写的简单局域网聊天
    汇编语言 复习 第十一章 标志寄存器
  • 原文地址:https://www.cnblogs.com/saintdingspage/p/12425813.html
Copyright © 2011-2022 走看看