【问题标题】:How do I load a bitmap into a Win32 application? [closed]如何将位图加载到 Win32 应用程序中? [关闭]
【发布时间】:2022-01-11 20:10:09
【问题描述】:

我正在尝试在 Win32 应用程序中加载位图,但由于某些奇怪的原因,位图无法加载。这是我目前所拥有的:

HANDLE hImg = LoadImageW(
    NULL,
    L"img.bmp",
    IMAGE_BITMAP,
    0,
    0,
    LR_LOADFROMFILE
);
if (hImg == NULL) {
    std::cout << GetLastError();
}

使用-Wall -municode 在 GCC 8.1.0 上编译。

没有任何内容输出到控制台,因此没有错误。但是,图像永远不会出现。这些问题似乎解决了类似的问题,但我查看了它们并找不到解决方案:

问题可能出在哪里?

完整代码:

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <iostream>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
    const wchar_t CLASS_NAME[] = L"Window Class";

    WNDCLASS wc = {};

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        L"My Application",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hwnd == NULL) {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    HANDLE hImg = LoadImageW(
        NULL,
        L"img.bmp",
        IMAGE_BITMAP,
        0,
        0,
        LR_LOADFROMFILE
    );
    if (hImg == NULL) {
        std::cout << GetLastError();
    }

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

            EndPaint(hwnd, &ps);
            break;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

【问题讨论】:

  • 你希望这段代码做什么?
  • 加载位图。
  • 你在某处有一些查看代码吗?也许错误在于您如何查看它
  • 它不应该显示图像。
  • 你希望代码能做什么对我来说完全是个谜。显然它成功地加载了图像,但是你决定不对那个图像做任何事情,并得出完全人为的结论。曾经有一段时间,提问者需要证明对问题领域的熟悉程度,以防止提出对任何人都无用的问题。

标签: c++ winapi


【解决方案1】:

您只是将位图加载到内存中,但实际上并没有在任何地方显示它。您需要:

【讨论】:

    【解决方案2】:

    您只需要更改窗口程序即可完成WM_PAINT 中的所有绘图。图片加载成功后,创建内存DC,将位图选中到内存DC,将内存DC绘制到目标窗口DC上。

    当不再需要来自LoadImage 的位图句柄时,应将其删除DeleteObject(或DestroyCursor/DestroyIcon,具体取决于加载的资源)

    HANDLE hImg = NULL;
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
    {
        switch (uMsg) 
        {
        case WM_CREATE:
            if (!hImg)
                hImg = LoadImage(NULL, L"img.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
            if (!hImg) { DWORD err = GetLastError(); std::cout << err; }
            return 0;
    
        case WM_PAINT: 
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
    
            if (hImg) {
                BITMAP bm;
                GetObject(hImg, sizeof(bm), &bm);//get bitmap dimension
                auto memdc = CreateCompatibleDC(hdc);
                auto oldbmp = SelectObject(memdc, (HBITMAP)hImg);
                BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY);
                SelectObject(memdc, oldbmp);//restore memdc
                DeleteDC(memdc);//delete memdc, we don't need it anymore
            }
    
            EndPaint(hwnd, &ps);
            return 0;
        }
    
        case WM_DESTROY:
            if (hImg) DeleteObject(hImg);//release resource
            hImg = NULL;
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    

    当使用GetLastError时,请确保函数在失败后立即被调用。示例:

    if (hImg == NULL) 
    {
        DWORD err = GetLastError();
        std::cout << err << '\n';
    }
    

    如果UNICODE已经定义,我们可以使用LoadImage代替LoadImageW

    【讨论】:

    • 因此hImg 被泄露。
    • @GSerg 公平点,已更新。
    • 顺便在wWinMain中也加wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    猜你喜欢
    • 1970-01-01
    • 2015-10-19
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多