如何将内存中的位图数据绘制在DC上

假如你定义了一个位图类,里面包含位图头,位图信息头,调色板,位图数据。然后你按照位图的格式将位图文件读入你的类中,现在你知道了位图的全部信息了。主要信息包含在位图信息头里面,数据则在位图数据缓冲里面。现在的问题是,在Windows下面如何将一张位图画出来,而且现在是如何从数据缓存里面绘画出位图。
  一般情况,我们都是直接绘制在dc里面,而不是绑定到子控件,让子控件自己绘画,比如picture控件之类的,我觉得提供绘制在dc里面的接口更具有广泛性。

  现在我知道两种从内存数据绘制彩色位图的2种方法。第一种麻烦一点,第二种则相当直接。
  方法一:
  第一步,用CreateCompatibleDC创建跟目标dc的兼容性内存dc。
  第二步,用CreateCompatibleBitmap创建跟目标dc的兼容性位图。
  第三步,用SelectObject将第二步创建的兼容位图选入第一步创建的兼容dc中。
  第四步,用SetDIBits设置兼容位图的数据缓冲
  第五步,用BitBlt将数据从兼容内存dc绘制到目标dc。
  第六步,删除兼容位图和兼容dc。
  代码如下,其中buffer代表位图数据缓冲。

1HDC hCompatibleDC = CreateCompatibleDC(hDc);
2HBITMAP hCompatibleBitmap = CreateCompatibleBitmap(hDc, bitmapinfoheader.biWidth,
3bitmapinfoheader.biHeight);
4HBITMAP hOldBitmap = (HBITMAP)SelectObject(hCompatibleDC, hCompatibleBitmap);
5SetDIBits(hDc, hCompatibleBitmap, 0, bitmapinfoheader.biHeight,
6buffer, (BITMAPINFO*)&bitmapinfoheader, DIB_RGB_COLORS);
7BitBlt(hDc, nStartX, nStartY, bitmapinfoheader.biWidth, bitmapinfoheader.biHeight,
8hCompatibleDC, 0, 0, SRCCOPY);
9SelectObject(hCompatibleDC, hOldBitmap);
10DeleteObject(hCompatibleDC);
11DeleteObject(hCompatibleDC);



  方法二:直接调用StretchDIBits绘制位图
  该函数功能相当强悍,似乎专为从内存数据绘制位图到dc而生。
  函数原型如下:
   int StretchDIBits(
   HDC hdc,                      // handle to DC
   int XDest,                    // x-coord of destination upper-left corner
   int YDest,                    // y-coord of destination upper-left corner
   int nDestWidth,               // width of destination rectangle
   int nDestHeight,              // height of destination rectangle
   int XSrc,                     // x-coord of source upper-left corner
   int YSrc,                     // y-coord of source upper-left corner
   int nSrcWidth,                // width of source rectangle
   int nSrcHeight,               // height of source rectangle
   CONST VOID *lpBits,           // bitmap bits
   CONST BITMAPINFO *lpBitsInfo, // bitmap data
   UINT iUsage,                  // usage options
   DWORD dwRop                   // raster operation code
   );
  使用也相当简单,调用

1StretchDIBits(hDc, nStartX, nStartY, bitmapinfoheader.biWidth,
2bitmapinfoheader.biHeight, 0, 0, bitmapinfoheader.biWidth,
3bitmapinfoheader.biHeight, buffer, (BITMAPINFO*)&bitmapinfoheader,
4DIB_RGB_COLORS, SRCCOPY);

  即可了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以给你一个简单的例子来说明如何实现透明子窗口的效果。 首先,在父窗口的 WM_CREATE 消息处理函数,创建一个与父窗口相同的内存 DC,代码如下: ``` HDC hdcScreen = GetDC(NULL); HDC hdcMem = CreateCompatibleDC(hdcScreen); ReleaseDC(NULL, hdcScreen); ``` 然后,在子窗口的 WM_PAINT 消息处理函数,将子窗口绘制内存 DC 上,代码如下: ``` RECT rcClient; GetClientRect(hwnd, &rcClient); HDC hdcMem = CreateCompatibleDC(hdcScreen); HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, rcClient.right, rcClient.bottom); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); // 在这里绘制子窗口的内容 // ... SelectObject(hdcMem, hOldBitmap); DeleteDC(hdcMem); ``` 其,hwnd 是子窗口的句柄,hdcScreen 是屏幕 DC 的句柄。 接着,在父窗口的 WM_PAINT 消息处理函数,使用 AlphaBlend 函数将内存 DC 的位复制到父窗口上,代码如下: ``` BLENDFUNCTION bf; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; RECT rcClient; GetClientRect(hwnd, &rcClient); HDC hdcMem = CreateCompatibleDC(hdcScreen); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); AlphaBlend(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, rcClient.right, rcClient.bottom, bf); SelectObject(hdcMem, hOldBitmap); DeleteDC(hdcMem); ``` 其,hdc 是父窗口的 DC 句柄,hBitmap 是存储子窗口位内存 DC 句柄。 最后,记得在父窗口的 WM_DESTROY 消息处理函数释放内存 DC 和位资源,代码如下: ``` DeleteObject(hBitmap); DeleteDC(hdcMem); ``` 这样,就可以实现透明子窗口的效果了。当然,具体的实现还需要根据你的具体需求进行调整。希望我的回答对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值