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 API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,423 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Tong Xu - MSFT 1,211 Reputation points Microsoft Vendor
    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.