【问题标题】:How to draw image on a window?如何在窗口上绘制图像?
【发布时间】:2009-11-17 12:17:28
【问题描述】:

我在 Windows Vista 上使用 C++ 中的 VS2005 创建了一个带有 createwindow() api 的窗口

我的要求是在该窗口上绘制图像(任何格式)。我没有在此应用程序中使用任何 MFC。

【问题讨论】:

    标签: windows winapi createwindow


    【解决方案1】:

    不完全确定您的问题是什么:在表单上绘制位图,或者您想知道如何处理各种图像格式,或两者兼而有之。无论如何,下面是一个如何加载位图并将其绘制在表单上的示例:

    HBITMAP hBitmap = NULL;
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int wmId, wmEvent;
    
        switch (message)
        {
    <...>
    
        case WM_CREATE:
            hBitmap = (HBITMAP)LoadImage(hInst, L"c:\\test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
            break;
        case WM_PAINT:
            PAINTSTRUCT     ps;
            HDC             hdc;
            BITMAP          bitmap;
            HDC             hdcMem;
            HGDIOBJ         oldBitmap;
    
            hdc = BeginPaint(hWnd, &ps);
    
            hdcMem = CreateCompatibleDC(hdc);
            oldBitmap = SelectObject(hdcMem, hBitmap);
    
            GetObject(hBitmap, sizeof(bitmap), &bitmap);
            BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
    
            SelectObject(hdcMem, oldBitmap);
            DeleteDC(hdcMem);
    
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    

    LoadImage 加载图标、光标、动画光标或位图。详情here

    要处理各种图像格式,您可以使用 Windows 映像组件(请参阅 IWICBitmapDecoder)或此处的代码 Loading JPEG and GIF pictures 或 3rd 方工具,如 FreeImageLeadTools

    希望这会有所帮助,问候

    【讨论】:

    • 嗨,Serge,它解决了我在窗口上绘制图像的问题。谢谢您的帮助。但由于这只需要 bmp、cur 和 ico 文件,我需要将 png 转换为 bmp,然后我会将 bmp 传递给这个函数
    • 谁能指导我在不使用任何 MFC 的情况下将 png 图像放在窗口上
    • 如果我可以为某人节省几分钟的搜索时间,我尝试使用这个答案,但它没有用。经过一段时间的戳我尝试将 sizeof(bitmap) 更改为 sizeof(BITMAP) 并且代码有效。我在 Windows 10 上使用 Visual Studio 2015。下面是整行:GetObject(hBitmap, sizeof(BITMAP), &bitmap);
    • 如果之后立即删除 DC,为什么还要保存旧的 HBITMAP 并再次调用 SelectObject?
    【解决方案2】:
    void LoadScreen(HWND hWnd) {
        RECT rect;
        HDC hdc = GetDC(hWnd);
        HBRUSH brush = CreatePatternBrush((HBITMAP)LoadImage(NULL, L"file.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE));
        GetWindowRect(hWnd, &rect);
        FillRect(hdc, &rect, brush);
        DeleteObject(brush);
        ReleaseDC(hWnd, hdc);
    }
    

    【讨论】:

    • 函数退出时从未释放的泄露的 HDC? Windows GDI 规则 101:如果你得到它,然后释放它;如果你创建它,然后删除它。您使用画笔正确执行此操作(创建/删除),但使用客户端 DC(获取/发布)未能这样做。
    • 啊,谢谢 :) 我解决了。在关闭大括号之前添加了一行。 ReleaseDC(hWnd, hdc);
    • 功能方面,这与serge_gubenko's answer相比如何?
    • 我不知道,但我发现我的解决方案更简单、干净、直接
    【解决方案3】:
    #include <windows.h>
    #include <string.h>
    
    HBITMAP hBitmap, hOldBitmap;
    HDC hdc, hdcMem;
    BITMAP bm;
    HINSTANCE hI;
    PAINTSTRUCT ps;
    RECT rect;
    RECT rc;
    
    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch (msg)
        {
        case WM_CREATE:
        hBitmap = (HBITMAP)LoadImage(hI, "1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        GetObject(hBitmap, sizeof(BITMAP), &bm);
        hdc = GetDC(hWnd);
        hdcMem = CreateCompatibleDC(hdc);
        hOldBitmap = SelectBitmap(hdcMem, hBitmap);
        ReleaseDC(hWnd, hdc);
        return 0;
    
        case WM_LBUTTONDOWN:
        //for dragging not only by the title, but also by any part of the window 
        ReleaseCapture();
        SendMessage(hWnd, 0xA1, 2, 0);
        break;
        case WM_PAINT:
        hdc=BeginPaint(hWnd,&ps);
        
        //overlay image with stretching to fit the window 
        GetClientRect(hWnd,&rect);
        SetStretchBltMode(hdc, STRETCH_HALFTONE);
        StretchBlt(hdc,0,0,rect.right,rect.bottom,
        hdcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
        
        EndPaint(hWnd,&ps);
        break;      
    
    
        case WM_DESTROY:
        PostQuitMessage(0);
          
        DeleteDC(hdcMem);
        DeleteObject(hBitmap);
        DeleteObject(hOldBitmap);
        break;
        }
    return DefWindowProc(hWnd, msg, wParam, lParam);
    }
     
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPInst, LPSTR lpCmdLine, int nCmdShow)
    {
    //copying a pointer to a running application instance (module)
    hI=hInstance;
    
    WNDCLASS wc;
    
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WindowProcedure;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
    wc.lpszClassName = "test_class";
    wc.lpszMenuName  = NULL;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    
    RegisterClass(&wc);
    
    HWND hWnd = CreateWindow(wc.lpszClassName, "Image Window", 
    //window with title (overlapping window) 
    WS_OVERLAPPEDWINDOW,
    //window without title
    //WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
    CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL);
    
    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);
    
    MSG msg;
    while(GetMessage (&msg, NULL, 0, 0))
        {
        DispatchMessage (&msg);
        TranslateMessage (&msg);
        }
    UnregisterClass(wc.lpszClassName, hInstance);
    return (int) msg.wParam;
    }
    

    【讨论】:

    • “宽普京”:P
    猜你喜欢
    • 2014-03-13
    • 2012-08-28
    • 2015-06-19
    • 1970-01-01
    • 2012-11-04
    • 2012-01-15
    • 2013-10-14
    • 2010-10-05
    • 2013-06-05
    相关资源
    最近更新 更多