C++ WinApi如何将.jpg图片绘制到新窗口?

3

我对Windows API还不熟悉。我使用了Winapi教程中提供的一些Windows示例代码:

Graphics.DrawImage(Image*,const Rect) 方法

我想打开一个 .jpg 图像并将其绘制到我创建的新窗口上。问题在于,我不确定如何在现有的窗口中使用 VOID Example_DrawImage9(HDC hdc) 方法。我的第一反应是在回调过程中的 case WM_PAINT 中调用它并使用那里的 hdc,但图像没有显示出来。我应该如何知道正确的 hdc 以及在哪里调用这个方法?

#include <windows.h>
#include "stdafx.h" 
#include <objidl.h>
#include <gdiplus.h>

using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

//*************************************************** added for gdiplus
HWND hEdit;

//************************************************how do I use this method   with the window I have created below?
VOID Example_DrawImage9(HDC hdc){
    Graphics graphics(hdc); // Create an Image object.
    Image image(L"C:/Users/Me/Desktop/fuzz.jpg"); // Create a Pen object.
    Pen pen(Color(255, 255, 0, 0), 2); // Draw the original source image.
    graphics.DrawImage(&image, 10, 10); // Create a Rect object that specifies the destination of the image.
    Rect destRect(200, 50, 150, 75); // Draw the rectangle that bounds the image.
    graphics.DrawRectangle(&pen, destRect); // Draw the image.
    graphics.DrawImage(&image, destRect);
}
//*********************************************************************************************



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

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    const wchar_t CLASS_NAME[] = L"Sample Window Class";
    WNDCLASS wc = {}; 
    wc.lpfnWndProc = WindowProc; //attach this callback procedure
    wc.hInstance = hInstance; //handle to application instance
    wc.lpszClassName = CLASS_NAME; 
    RegisterClass(&wc); //register wc
    // Create the window.
    HWND hwnd = CreateWindowEx( 
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

                                        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
        );

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

    ShowWindow(hwnd, nCmdShow);

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

//callback procedure for this window, takes in all the window details
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);
            //***************************************************************
            //do we call DrawImage here? what do we need to pass as hdc?
            //Example_DrawImage9(HDC hdc);//?????????????
            //***************************************************************
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
            EndPaint(hwnd, &ps);
        }
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

不要凭直觉编码。相反,阅读在您之前的问题的评论中提供给您的资源。 - IInspectable
我认为Graphics在超出作用域时会尝试销毁你传递给它的HDC。如果它没有这样做,那么你认为紧接着立即填充一个矩形的结果会是什么? - Mark Ransom
@MarkRansom:Graphics 类不会销毁提供的 HDC - Remy Lebeau
@RemyLebeau 很好知道,谢谢。我在文档中也没有找到任何明示或暗示。 - Mark Ransom
2个回答

7

你走上了正确的道路。使用BeginPaint()提供的HDC。不要忘记在使用之前初始化GDI+。

#include <windows.h>
#include "stdafx.h" 
#include <objidl.h>
#include <gdiplus.h>

using namespace Gdiplus;
#pragma comment (lib, "Gdiplus.lib")

void Example_DrawImage9(HDC hdc)
{
    Graphics graphics(hdc);
    // Create an Image object.
    Image image(L"C:/Users/Me/Desktop/fuzz.jpg");
    // Create a Pen object.
    Pen pen(Color(255, 255, 0, 0), 2);
    // Draw the original source image.
    graphics.DrawImage(&image, 10, 10);
    // Create a Rect object that specifies the destination of the image.
    Rect destRect(200, 50, 150, 75);
    // Draw the rectangle that bounds the image.
    graphics.DrawRectangle(&pen, destRect);
    // Draw the image.
    graphics.DrawImage(&image, destRect);
}

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

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    ULONG_PTR token;
    GdiplusStartupInput input = {0};
    input.GdiplusVersion = 1;
    GdiplusStartup(&token, &input, NULL);

    const wchar_t CLASS_NAME[] = L"Sample Window Class";
    WNDCLASS wc = {}; 
    wc.lpfnWndProc = &WindowProc; //attach this callback procedure
    wc.hInstance = hInstance; //handle to application instance
    wc.lpszClassName = CLASS_NAME; 
    RegisterClass(&wc); //register wc
    // Create the window.
    HWND hwnd = CreateWindowEx( 
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd != NULL)
    {
        ShowWindow(hwnd, nCmdShow);

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

    GdiplusShutdown(token);
    return 0;
}

//callback procedure for this window, takes in all the window details
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));
            Example_DrawImage9(hdc);
            EndPaint(hwnd, &ps);
            return 0;
        }
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

3

在程序退出前,您需要初始化GDI+并关闭它。

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    //...

    Gdiplus::GdiplusShutdown(gdiplusToken);

    return 0;
}

graphics.DrawImage(&image, 10, 10);足以绘制图像。一旦你绘制了图像,请不要在其上面绘制任何其他内容。

您可以在WM_PAINT中使用Example_DrawImage9(hdc)。在绘制图像之前,请使用FillRect


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接