• 一种在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())

  • 相关阅读:
    Java练习 SDUT-3328_JAVA判断合法标识符
    问题2:css图片、文字居中
    问题1:jquery实现全选功能,第二次失效(已解决)
    问题2:input、textarea、submit 宽度设置为100%,但显示宽度不一致
    问题1:设置了text-overflow : ellipsis未起作用
    问题1:canvas绘制图片加载不出来
    问题1:鼠标指向导航栏li,但li中a样式未改变
    Shell工具| 流程控制
    Hadoop |集群的搭建
    MySQL高级01
  • 原文地址:https://www.cnblogs.com/saintdingspage/p/12425813.html
Copyright © 2020-2023  润新知