Understanding how to display an image

Willard 45 Reputation points
2024-04-16T02:24:51.8066667+00:00

I'm attempting to understand how to display an image onto a window using the code from "Loading and displaying bitmaps"

Image image(L"Grapes.jpg");

graphics.DrawImage(&image, 60, 10);

I have been able to get the first line working by including gdiplusheaders.h , but I haven't found a way to fix "graphics unidentified". I attempted to use the AI helper, but it claims it couldn't find headers for it. Any help to solving or explaining how the two lines work is appreciated.

Windows development Windows API - Win32
{count} votes

2 answers

Sort by: Most helpful
  1. Tong Xu - MSFT 2,546 Reputation points Microsoft External Staff
    2024-04-16T03:38:55.7066667+00:00

    Hi, @Willard
    Welcome to Microsoft Q&A!

    I remember graphics.DrawImage used 5 parameters. Your usage is wrong.
    When "graphics unidentified" occurred, you should add namespace and library.
    using namespace Gdiplus;
    #pragma comment(lib,"gdiplus.lib")

    Also, I made a code sample to show how to use GDI+ to show images.

    #ifndef UNICODE
    #define UNICODE
    #endif 
    #include <windows.h>
    #include <gdiplus.h>
    using namespace Gdiplus;
    #pragma comment(lib,"gdiplus.lib")
    ULONG_PTR gdiplusStartupToken;
    Gdiplus::GdiplusStartupInput gdiInput;
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
    {
        // Register the window class.
        const wchar_t CLASS_NAME[] = L"Sample Window Class";
        WNDCLASSEX wincl = { };
        wincl.hInstance = hInstance;
        wincl.lpszClassName = CLASS_NAME;
        wincl.lpfnWndProc = WindowProc;
        wincl.style = CS_DBLCLKS;
        wincl.cbSize = sizeof(WNDCLASSEX);
        wincl.hIcon = NULL;
        wincl.hIconSm = NULL;
        wincl.hCursor = NULL;
        wincl.lpszMenuName = NULL;
        wincl.cbClsExtra = 0;
        wincl.cbWndExtra = 0;
        wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        RegisterClassEx(&wincl);
        // Create the window.
        HWND hwnd = CreateWindowEx(
            WS_EX_LAYERED ,
            (LPCWSTR)CLASS_NAME,
            L"PNGDialog Example Application",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            500,
            500,
            0,
            NULL,
            hInstance,
            NULL
        );
        RECT wndRect;
        SIZE wndSize;
        HDC hdc;
        POINT ptSrc;
        BLENDFUNCTION blendFunction;
        HDC screenDC;
        HDC memDC;
        HBITMAP memBitmap;
        GetWindowRect(hwnd, &wndRect);
        wndSize = { wndRect.right - wndRect.left,wndRect.bottom - wndRect.top };
        hdc = GetDC(hwnd);
        memDC = CreateCompatibleDC(hdc);
        memBitmap = ::CreateCompatibleBitmap(hdc, wndSize.cx, wndSize.cy);
        ::SelectObject(memDC, memBitmap);
        Gdiplus::Image image(L"001.bmp");
        Gdiplus::Graphics graphics(memDC);
        graphics.DrawImage(&image, 0, 0, wndSize.cx, wndSize.cy);
        // Run the message loop.
        screenDC = GetDC(NULL);
        ptSrc = { 0,0 };
        UpdateLayeredWindow(hwnd, screenDC, &ptSrc, &wndSize, memDC, &ptSrc, 0, &blendFunction, 4);
        ShowWindow(hwnd, SW_SHOW);
        UpdateWindow(hwnd);
      
        MSG msg = { };
        while (GetMessage(&msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return 0;
    }
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        Gdiplus::GdiplusStartup(&gdiplusStartupToken, &gdiInput, NULL);
        switch (uMsg)
        {
        case WM_DESTROY:
            Gdiplus::GdiplusShutdown(gdiplusStartupToken);
            PostQuitMessage(0);
            return 0;
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            SIZE wndSize;
            HBITMAP memBitmap;
            HDC memDC;
            HDC hdc = BeginPaint(hwnd, &ps);
           
            // All painting occurs here, between BeginPaint and EndPaint.
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
            EndPaint(hwnd, &ps);
        }
        return 0;
        }
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }  
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Willard 45 Reputation points
    2024-04-17T20:55:10.83+00:00

    Thank you @Tong Xu - MSFT , but the code you provided only created a black window regardless if I changed the path to an image. However your code gave me ideas on how to rephrase my question and the AI posted this. I must also emphasize that I am still learning Win32 and am not knowledgeable in all terminology, headers, classes etc.

    #include <windows.h>
    #include <gdiplus.h>
    
    using namespace Gdiplus;
    //Next line was missing
    #pragma comment(lib, "gdiplus.lib")
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                Graphics graphics(hdc);
                Image image(L"C:\\path\\to\\image.jpg");
                graphics.DrawImage(&image, 0, 0);
                EndPaint(hWnd, &ps);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
            break;
        }
        return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
        WNDCLASSEX wcex;
        wcex.cbSize = sizeof(WNDCLASSEX);
        wcex.style = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc = WndProc;
        wcex.cbClsExtra = 0;
        wcex.cbWndExtra = 0;
        wcex.hInstance = hInstance;
        wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
        wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName = NULL;
        wcex.lpszClassName = L"WindowClass";
        wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
    
        if (!RegisterClassEx(&wcex))
        {
            MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    
        HWND hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"WindowClass", L"Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
    
        if (hWnd == NULL)
        {
            MessageBox(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
    
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
    
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        GdiplusShutdown(gdiplusToken);
        return msg.wParam;
    }
    
    

    As far as I understand you will need to include gdiplus.h, using namespace gdiplus, and #pragma comment (lib, "gdiplus.lib") or linking to the library itself. That will allow it to access code it needs for the Image and Graphics classes under GDI+. Then before creating the window, you must initialize GDI+ then shutdown GDI+ at the end (which I'm assuming is to free up resources.). It produces the image when given a path to one, but will allow the window to stretch up to the image's size.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.