如何在窗口中加载位图? [英] How can I load a bitmap inside my window?

查看:68
本文介绍了如何在窗口中加载位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将位图加载到我创建的窗口中.位图应该是窗口的背景(我想在其上添加标签,稍后再添加进度条).

I'm trying to load a bitmap to a window I created. The bitmap should be the background of the window (I want to add labels on it an a progress bar later on).

这是我的代码:

HINSTANCE hInst;
LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX  WndCls;
static WCHAR szAppName[] = L"BitmapIntro";
MSG         Msg;

hInst = hInstance;
WndCls.cbSize = sizeof(WndCls);
WndCls.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
WndCls.lpfnWndProc = WindProcedure;
WndCls.cbClsExtra = 0;
WndCls.cbWndExtra = 0;
WndCls.hInstance = hInst;
WndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndCls.lpszMenuName = NULL;
WndCls.lpszClassName = szAppName;
WndCls.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
RegisterClassEx(&WndCls);

CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
    szAppName,
    L"Bitmaps Fundamentals",
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    NULL,
    NULL,
    hInstance,
    NULL);

while (GetMessage(&Msg, NULL, 0, 0))
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

return static_cast<int>(Msg.wParam);
}

LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
HDC hDC, MemDCExercising;
PAINTSTRUCT Ps;
HBITMAP bmpExercising;

switch (Msg)
{
case WM_DESTROY:
    PostQuitMessage(WM_QUIT);
    break;
case WM_PAINT:

    hDC = BeginPaint(hWnd, &Ps);

    // Load the bitmap from the resource
    bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
    // Create a memory device compatible with the above DC variable
    MemDCExercising = CreateCompatibleDC(hDC);
    // Select the new bitmap
    SelectObject(MemDCExercising, bmpExercising);

    // Copy the bits from the memory DC into the current dc
    BitBlt(hDC, 10, 10, 450, 400, MemDCExercising, 0, 0, SRCCOPY);

    // Restore the old bitmap
    DeleteDC(MemDCExercising);
    DeleteObject(bmpExercising);
    EndPaint(hWnd, &Ps);
    break;
default:
    return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}

问题是,与窗口相比,PNG尺寸较小,因此,当PNG打开时,它仅占据左上角.我如何才能使其拉伸到我的窗口大小,或者至少一遍又一遍地绘制它直到填满窗口?

The problem is, the PNG size is small compared to the window, so when the PNG opens, it only occupies the left high corner. How can I make it stretch to my window size or at least draw it over and over until it fills the window?

推荐答案

如何使其伸展到我的窗口大小

How can I make it stretch to my window size

使用 StretchBlt() 代替 BitBlt().

case WM_PAINT:
{    
    // Get the window dimensions
    RECT r;
    GetClientRect(hWnd, &r);

    // Load the bitmap from the resource
    HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));

    // Get the bitmap dimensions
    BITMAP bmp;
    GetObject(bmpExercising, sizeof(BITMAP), &bmp);

    PAINTSTRUCT Ps;
    HDC hDC = BeginPaint(hWnd, &Ps);

    // Create a memory device compatible with the above DC variable
    HDC MemDCExercising = CreateCompatibleDC(hDC);

    // Select the new bitmap
    HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising);

    // Copy the bits from the memory DC into the current dc
    StretchBlt(hDC, 0, 0, r.right - r.left, r.bottom - r.top, MemDCExercising, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

    // Restore the old bitmap
    SelectObject(MemDCExercising, hOldBmp);

    // Destroy the memory device
    DeleteDC(MemDCExercising);

    // Destroy the bitmap
    DeleteObject(bmpExercising);

    EndPaint(hWnd, &Ps);
    break;
}

还是至少一遍又一遍地绘制它直到填满窗口?

or at least draw it over and over until it fills the window?

有两种不同的处理方式.

There are two different ways to handle that.

  1. 在启动时,使用

  1. at startup, load the bitmap and create an HBRUSH around it using CreatePatternBrush(), and then assign that to the WNDCLASS::hbrBackground field when you register your window class. Let the OS draw the window background using the bitmap for you.

HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
WndCls.hbrBackground = CreatePatternBrush(bmpExercising);

  • 如果要手动绘制位图,请让绘制处理程序在几个循环中调用 BitBlt().您知道位图的尺寸(可以使用在代码中进行检索) GetObject() BITMAP 结构),您就知道了窗口的尺寸(可以使用

  • if you want to paint the bitmap manually, have your paint handler call BitBlt() in a couple of loops. You know the dimensions of the bitmap (which you can retrieve in code using GetObject() and the BITMAP structure), and you know the dimensions of the window (which you can retrieve in code using GetWindowRect() or GetClientRect()). So simply draw the same bitmap more than one time at different offsets as needed. Start by drawing it once in the top-left corner, then move right bitmap-width pixels and draw it again, repeating until you move past window-width pixels. Then move left back to 0 and move down bitmap-height pixels and repeat the whole width-line again, repeating until you move past window-height pixels.

    case WM_PAINT:
    {    
        // Get the window dimensions
        RECT r;
        GetClientRect(hWnd, &r);
    
        // Load the bitmap from the resource
        HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
    
        // Get the bitmap dimensions
        BITMAP bmp;
        GetObject(bmpExercising, sizeof(BITMAP), &bmp);
    
        PAINTSTRUCT Ps;
        HDC hDC = BeginPaint(hWnd, &Ps);
    
        // Create a memory device compatible with the above DC variable
        HDC MemDCExercising = CreateCompatibleDC(hDC);
    
        // Select the new bitmap
        HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising);
    
        int width = r.right - r.left;
        int height = r.bottom - r.top;
    
        // Copy the bits from the memory DC into the current dc
        for(int y = 0; y < height; y += bmp.bmHeight)
        {
            for(int x = 0; x < width; x += bmp.bmWidth)
            {
                BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, MemDCExercising, 0, 0, SRCCOPY);
            }
        }
    
        // Restore the old bitmap
        SelectObject(MemDCExercising, hOldBmp);
    
        // Destroy the memory device
        DeleteDC(MemDCExercising);
    
        // Destroy the bitmap
        DeleteObject(bmpExercising);
    
        EndPaint(hWnd, &Ps);
        break;
    }
    

  • 现在,话虽如此,这里还有一些附加说明:

    Now, with that said, here are some additional notes:

    1. 您不应在绘画处理程序内部加载位图.在创建窗口之前将其加载一次,然后对每个绘制操作重复使用相同的 HBITMAP ,直到窗口被销毁为止,然后释放位图.

    1. you should not be loading the bitmap inside of your paint handler. Load it one time before creating the window, and then reuse the same HBITMAP for each paint operation until the window is destroyed, then free the bitmap.

    LoadBitmap()已过时,您应该使用

    LoadBitmap() is deprecated, you should be using LoadImage() instead, eg:

    HBITMAP bmpExercising = (HBITMAP) LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP3), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
    

  • 您说位图应该是窗口的背景",因此您应该绘制位图以响应

  • 这篇关于如何在窗口中加载位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆