MFC在图片控件显示位图与动态调整适合控件的显示大小

⌚Time: 2022-08-30 12:46:31

👨‍💻Author: Jack Ge

用到StretchBlt这个函数。StretchBlt,函数名。该函数从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩。


BOOL StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);

hdcDest:指向目标设备环境的句柄。

nXOriginDest:指定目标矩形左上角的X轴坐标,按逻辑单位表示坐标。

nYOriginDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。

nWidthDest:指定目标矩形的宽度,按逻辑单位表示宽度。

nHeightDest:指定目标矩形的高度,按逻辑单位表示高度。

hdcSrc:指向源设备环境的句柄。

nXOriginSrc:指向源矩形区域左上角的X轴坐标,按逻辑单位表示坐标。

nYOriginSrc:指向源矩形区域左上角的Y轴坐标,按逻辑单位表示坐标。

nWidthSrc:指定源矩形的宽度,按逻辑单位表示宽度。

nHeightSrc:指定源矩形的高度,按逻辑单位表示高度。

dwRop:指定要进行的光栅操作。光栅操作码定义了系统如何在输出操作中组合颜色,这些操作包括刷子、源位图和目标位图等对象。参考BitBlt可了解常用的光栅操作码列表。

下面列出了一些常见的光栅操作代码:

BLACKNESS:表示使用与物理调色板的索引0相关的色彩来填充目标矩形区域,(对缺省的物理调色板而言,该颜色为黑色)。

DSTINVERT:表示使目标矩形区域颜色取反。

MERGECOPY:表示使用布尔型的AND(与)操作符将源矩形区域的颜色与特定模式组合一起。

MERGEPAINT:通过使用布尔型的OR(或)操作符将反向的源矩形区域的颜色与目标矩形区域的颜色合并。

NOTSRCCOPY:将源矩形区域颜色取反,再拷贝到目标矩形区域。

NOTSRCERASE:使用布尔类型的OR(或)操作符组合源和目标矩形区域的颜色值,然后将合成的颜色取反。

PATCOPY:将特定的模式拷贝到目标位图上。

PATPAINT:通过使用布尔OR(或)操作符将源矩形区域取反后的颜色值与特定模式的颜色合并。然后使用OR(或)操作符将该操作的结果与目标矩形区域内的颜色合并。

PATINVERT:通过使用XOR(异或)操作符将源和目标矩形区域内的颜色合并。

SRCAND:通过使用AND(与)操作符来将源和目标矩形区域内的颜色合并。

SRCCOPY:将源矩形区域直接拷贝到目标矩形区域。

SRCERASE:通过使用AND(与)操作符将目标矩形区域颜色取反后与源矩形区域的颜色值合并。

SRCINVERT:通过使用布尔型的XOR(异或)操作符将源和目标矩形区域的颜色合并。

SRCPAINT:通过使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并。

WHITENESS:使用与物理调色板中索引1有关的颜色填充目标矩形区域。(对于缺省物理调色板来说,这个颜色就是白色)。

BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );

x:逻辑单元x轴左上角坐标;

y:逻辑单元y轴左上角坐标;

nWidth: 设备矩形宽度;

nHeight:设备矩形高度;

pSrcDC: 源设备上下文;

xSrc :源矩形x轴左上角坐标;

ySrc: 源矩形y轴左上角坐标;

Specifies the x-coordinate (in logical units) of the upper-left corner of the source rectangle.

nSrcWidth:源矩形宽度;

nSrcHeight:源矩形高度

dwRop:指定要进行的光栅操作。(和第一个函数一样标示)

返回值编辑

上代码:




    //获取图片控件dc

    CDC *pDC =GetDlgItem(IDC_PIC1)->GetDC();

    CDC memDC;

    //创建兼容dc

    memDC.CreateCompatibleDC(pDC);

    //加载bitmap图片

    CBitmap bitmap;

    bitmap.LoadBitmap(IDB_BITMAP1);

    memDC.SelectObject(bitmap);

    BITMAP bmp;

    bitmap.GetBitmap(&bmp);

    //获取控件区域

    RECT rc;

    GetDlgItem(IDC_PIC1)->GetClientRect(&rc);



    //获取控件宽度和高度

    int showWidth = rc.right-rc.left;

    int showHeight = rc.bottom-rc.top;

    

    //若不设置这个模式,图片会严重失真

    pDC->SetStretchBltMode(COLORONCOLOR);

    //将图像绘制到控件区域中

    pDC->StretchBlt(rc.left,rc.top,showWidth,showHeight,&memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);



    //释放资源

    bitmap.DeleteObject();

    memDC.DeleteDC();

    ReleaseDC(pDC);

代码要放在窗体的OnPaint函数,CPaintDC dc(this)语句之后,会随着窗口的刷新而显示。

如果放在OnInitDialog等函数中,只会随着窗口初始化完成而被调用一次,之后被新的窗口画面覆盖,看起来就像没有显示一样

DC:

首先明白DC的含义,Windows不允许程序员直接访问硬件,它对屏幕的操作是通过环境设备,也就是DC来完成的。屏幕上的没一个窗口都对应一个DC,可以把DC想象成一个视频缓冲区,对这这个缓冲区的操作,会表现在这个缓冲区对应的屏幕窗口上。

在窗口的DC之外,可以建立自己的DC,就是说它不对应窗口,这个方法就是CreateCompatibleDC,这个DC就是一个内存缓冲区,通过这个DC你可以把和它兼容的窗口DC保存到这个DC中,就是说你可以通过它在不同的DC之间拷贝数据。例如:你先在这个DC中建立好数据,然后在拷贝到窗口的DC就是完成了这个窗口的刷新。