窗口中显示bmp图片的过程

创建步骤


我们首先大致了解下显示位图的基本步骤,主要有5步,如图1所示:


                                                            图1 位图显示步骤

对每个过程的解释如下:

1.创建位图

   利用CBitmap类构造一个位图对象,然后利用LoadBitmap函数完成实际位图资源和对象的关联.

2.创建兼容DC

   在OnDraw或OnEraseBkgnd函数的入参是CDC对象指针,指示了当前实际显示设备的相关信息;我们利用CreateCompatible函数创建一个内存设备上下文,和参数pDC所指定的DC相兼容。内存设备上下文实际上是一个内存块,表示一个显示的表面,可以认为是虚拟的设备显示环境

3.将位图选人兼容DC中

   当兼容的内存设备上下文被创建时,它的表面是标准的一个单色像素宽和一个单色像素高,我们需要将具有有正确的宽度和高度的位图选人兼容DC,才能正确的显示。

4.将兼容DC中的位图粘贴到当前DC

    我们可以利用BitBlt函数或者StrechBlt函数完成兼容DC中的图像到实际DC的搬移和显示。

5.位图显示

     利用窗口绘制过程的两个时机完成位图显示,一个窗口绘制过程包括两个步骤:首先是利用画刷擦除窗口背景,其次是再对窗口重新进行重绘;擦除是调用OnEraseBkgnd函数,重绘是调用OnDraw函数


函数说明


BitBlt函数是以1:1的比例完成拷贝,而StrechBlt函数则可以进行图片的压缩或者扩展,它们的函数声明和参数函数如下所示,更加具体的信息参数MSDN:

BitBlt函数声明如下:

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

返回值:函数成功,返回非零值,否则为0。
参数: 
x       指定目标矩形左上角的逻辑x坐标。  
y       指定目标矩形左上角的逻辑y坐标。  
nWidth  指定目标矩形和源位图的宽度(逻辑单位)。  
nHeight 指定目标矩形和源位图的高度(逻辑单位)。  
pSrcDC  指向CDC对象的指针,标识待拷贝位图的设备上下文。  
xSrc    指定源位图左上角的逻辑X坐标。  
ySrc    指定源位图左上角的逻辑Y坐标。  
dwRop   指定要执行的光栅操作 

StrechBlt函数声明如下:

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

返回值:如果位图已经绘制,则返回非零值,否则为0。
参数: 
x           目标矩形左上角的X逻辑坐标。  
y           目标矩形左上角的Y逻辑坐标。  
nWidth      目标矩形的宽度(逻辑单位)。  
nHeight     目标矩形的高度(逻辑单位)。  
pSrcDC      指定源设备上下文。  
xSrc        源矩形左上角的X逻辑坐标。  
ySrc        源矩形左上角的Y逻辑坐标。  
nSrcWidth   源矩形的宽度(逻辑单位)。  
nSrcHeight  源矩形的高度(逻辑单位)。  
dwRop       指定光栅操作。

功能代码


我们这里以OnEraseBKgnd消息响应函数完成整个显示功能,该函数在视类中进行响应,具体代码如下:

BOOL CCBmpViewView::OnEraseBkgnd(CDC* pDC)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    //创建位图对象
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP1);

    //获取位图信息
    BITMAP bmp;
    bitmap.GetBitmap(&bmp);

    //创建兼容DC
    CDC dcCompatible;
    dcCompatible.CreateCompatibleDC(pDC);

    //将位图选入兼容DC
    dcCompatible.SelectObject(&bitmap);

    //向实际DC输出图片
    CRect rect;
    GetClientRect(&rect);
    //1比1格式输出图片
    //pDC->BitBlt(0,0,rect.Width(), rect.Height(),&dcCompatible,0,0,SRCCOPY);
    //适应实际窗口大小进行图片压缩或者拉伸输出
    pDC->StretchBlt(0,0,rect.Width(), rect.Height(),&dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
   
    return TRUE;
}
运行效果:



效果分析


通过两种方式进行对比发现,若我们的位图大小比窗口小,以OnEraseBkgnd函数和BitBlt函数进行输出图片,改变窗口大小会有窗口的残留痕迹;若以OnDraw函数和BitBlt函数进行输出则没有这样的问题,但是会带来视觉上的闪烁;StrechBlt函数由于有压缩或者拉伸造成图片失真。


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成异形窗口的方法一般是通过设置窗口的不规则区域(non-client region)来实现的。以下是一个简单的 C++ 代码示例,可以根据一张图片生成一个具有不规则边缘的窗口: ```c++ #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 加载窗口图像 HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "window.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (!hBitmap) { MessageBox(NULL, "Failed to load image!", "Error", MB_OK | MB_ICONERROR); return 1; } // 获取窗口图像的大小 BITMAP bitmap; GetObject(hBitmap, sizeof(bitmap), &bitmap); int width = bitmap.bmWidth; int height = bitmap.bmHeight; // 创建窗口类 WNDCLASS wndClass = {}; wndClass.lpfnWndProc = WndProc; wndClass.hInstance = hInstance; wndClass.lpszClassName = "MyWindowClass"; RegisterClass(&wndClass); // 创建窗口 HWND hWnd = CreateWindow("MyWindowClass", "My Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL); // 创建一个用于绘制窗口DC HDC hdc = GetDC(hWnd); // 为窗口设置不规则区域 HRGN hRgn = CreateRectRgn(0, 0, width, height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { COLORREF color = GetPixel(hdc, x, y); if (color == RGB(0, 0, 0)) { HRGN hPixelRgn = CreateRectRgn(x, y, x + 1, y + 1); CombineRgn(hRgn, hRgn, hPixelRgn, RGN_XOR); DeleteObject(hPixelRgn); } } } SetWindowRgn(hWnd, hRgn, TRUE); // 绘制窗口图像 HDC hMemDC = CreateCompatibleDC(hdc); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hdc, 0, 0, width, height, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); // 显示窗口 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 清理资源 DeleteObject(hBitmap); ReleaseDC(hWnd, hdc); DeleteObject(hRgn); return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } ``` 在这个示例,我们首先加载了一张 BMP 格式的图片,然后获取了它的大小。接下来,我们创建了一个窗口类,并使用 CreateWindow 函数创建了一个窗口。然后,我们通过 GetDC 函数获取了用于绘制窗口DC。接着,我们根据图片的黑色像素生成了一个不规则区域,并使用 SetWindowRgn 函数将其设置为窗口的不规则区域。最后,我们使用 BitBlt 函数将图片绘制在窗口上,并使用 ShowWindow 函数显示窗口。 需要注意的是,这个示例只是一个简单的演示,可能存在一些问题。例如,如果图片太大,生成不规则区域的过程可能会很慢;如果图片的边缘不够光滑,可能会出现锯齿。在实际开发,您可能需要对代码进行优化或调整,以达到更好的效果和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值