首页 > 解决方案 > 从文件资源管理器中选择图像后将图像放在屏幕上

问题描述

我正在尝试编写用户能够从他们的计算机中选择图像的代码。我能够让一段代码在用户选择图像时窗口会自行更新的地方工作。所以,我继续在屏幕上添加了一些按钮,现在,图像甚至不会加载到屏幕上。我很困惑为什么。这不是图像大小,因为我也选择了一个小图像来加载。

这是我放置图像的功能:

void putImage(HDC hdc, HWND hWnd)
{
    Graphics graphic(hdc);
    Image* image = Image::FromFile(filePath);
    Status status = graphic.DrawImage(image, 10, 20);
    RECT updateRect = { 0 };
    updateRect.left = 10;
    updateRect.top = 10;
    updateRect.right = updateRect.left + image->GetWidth();
    updateRect.bottom = updateRect.top + image->GetHeight();
    RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
}

这是我的油漆:

case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC screen = BeginPaint(hWnd, &ps);
            HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
            if (hbuff)
            {
                RECT rc;
                GetClientRect(hWnd, &rc);
                FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
                putImage(screen, hWnd);
                hr = EndBufferedPaint(hbuff, TRUE);
            }
            EndPaint(hWnd, &ps); } break;

我刚刚添加了带有 WS_VISIBLE 和 WS_CHILD 的 CreateWindowW 按钮。

标签: c++winapi

解决方案


如果您设置文件的绝对路径,您的代码将起作用。值得一提的是,您可以评论RedrawWindow,因为此功能会反复刷新窗口并导致闪烁。

这是一个可重现的示例,您可以尝试:

 #include <Windows.h>
    #include <ObjIdl.h>
    #include <gdiplus.h>
    #include <uxtheme.h>
    #include <shobjidl_core.h>

    #pragma comment (lib,"Gdiplus.lib")
    #pragma comment(lib,"Uxtheme")

    #define MAX_LOADSTRING 100
    #define IDB_BUTTON1 101

    using namespace Gdiplus;
    using namespace std;


    void putImage(HDC, HWND);
    void Opendialog();

    HWND hwnd;
    PWSTR pszFilePath;
    BOOL flag = 0;

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message)
        {
        case WM_CREATE:
        {
            HWND hwndButton = CreateWindow(
                L"BUTTON",  // Predefined class; Unicode assumed 
                L"OK",      // Button text 
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
                500,         // x position 
                10,         // y position 
                100,        // Button width
                100,        // Button height
                hwnd,     // Parent window
                (HMENU)IDB_BUTTON1,       // No menu.
                (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
                NULL);      // Pointer not needed.
        }
        break;
        case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDB_BUTTON1:
                Opendialog();
                flag = 1;
                InvalidateRect(hwnd, NULL, FALSE);
            default:
                return DefWindowProc(hwnd, message, wParam, lParam);
            }
        }
        break;
        case WM_PAINT:
        {
            HRESULT hr = S_OK;
            PAINTSTRUCT ps;
            HDC screen = BeginPaint(hwnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            if (flag == 1)
            {
                HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
                if (hbuff)
                {
                    RECT rc;
                    GetClientRect(hwnd, &rc);
                    FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
                    putImage(screen, hwnd);
                    hr = EndBufferedPaint(hbuff, TRUE);
                }
                flag = 0;
            }

            EndPaint(hwnd, &ps);
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    };

    HINSTANCE hinst;

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;

        //Initialize GDI+
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

        hinst = GetModuleHandle(NULL);
        // create a window class:
        WNDCLASS wc = {};
        wc.lpfnWndProc = WndProc;
        wc.hInstance = hinst;
        wc.lpszClassName = L"win32";

        // register class with operating system:
        RegisterClass(&wc);

        // create and show window:
        hwnd = CreateWindow(L"win32", L"My program", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 1000, 800, NULL, NULL, hinst, NULL);

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

        ShowWindow(hwnd, SW_SHOW);


        MSG msg = {};

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

    }

    void putImage(HDC hdc, HWND hWnd)
    {
        Graphics graphic(hdc);
        Image* image = Image::FromFile(pszFilePath);
        Status status = graphic.DrawImage(image, 10, 20);
        RECT updateRect = { 0 };
        updateRect.left = 10;
        updateRect.top = 10;
        updateRect.right = updateRect.left + image->GetWidth();
        updateRect.bottom = updateRect.top + image->GetHeight();
    //    RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
    }

    void Opendialog()
    {
        HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
            COINIT_DISABLE_OLE1DDE);
        if (SUCCEEDED(hr))
        {
            IFileOpenDialog* pFileOpen;

            // Create the FileOpenDialog object.
            hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
                IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));

            if (SUCCEEDED(hr))
            {
                // Show the Open dialog box.
                hr = pFileOpen->Show(NULL);

                // Get the file name from the dialog box.
                if (SUCCEEDED(hr))
                {
                    IShellItem* pItem;
                    hr = pFileOpen->GetResult(&pItem);
                    if (SUCCEEDED(hr))
                    {
                        hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

                        // Display the file name to the user.
                        if (SUCCEEDED(hr))
                        {
                            //                        MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
                            CoTaskMemFree(pszFilePath);
                        }
                        pItem->Release();
                    }
                }
                pFileOpen->Release();
            }
            CoUninitialize();
        }
    }

调试:

1

更新:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <string>
#include<string.h>
#include <iostream>
#include <uxtheme.h>
#include <shobjidl.h>
#include <objidl.h>
#include <gdiplus.h>
#include <gdiplusheaders.h>
#pragma comment (lib,"Gdiplus.lib")
#pragma comment (lib, "uxtheme.lib")
#pragma comment(lib, "user32.lib")
#pragma warning(disable:4996)

using namespace Gdiplus;

#define FILE_OPEN 1
#define FILE_MENU_EXIT 3
#define MENU_HELP 4

static TCHAR szWindowClass[] = _T("DesktopApp");
static TCHAR szTitle[] = _T("Multi-Purpose Media Editor");
HINSTANCE hInst;
HMENU hMenu;
PWSTR filePath;
int flag = 0;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);
void AddControls(HWND);
void OpenFileWindow(HWND);
void putImage(HDC, HWND);
std::wstring s2ws(const std::string&);

//Main Function for Windows Desktop Application
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = 0;
    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 = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex))
    {
        MessageBox(NULL,
            _T("Call to RegisterClassEx failed!"),
            _T("Windows Desktop Guided Tour"),
            NULL);

        return 1;
    }

    hInst = hInstance;
    DEVMODE settings;
    EnumDisplaySettings(NULL, 0, &settings);

    HWND hWnd = CreateWindow(
        szWindowClass,
        szTitle,
        WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT,
        GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
        NULL,
        NULL,
        hInstance,
        NULL
    );

    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    if (!hWnd)
    {
        MessageBox(NULL,
            _T("Call to CreateWindow failed!"),
            _T("Windows Desktop Guided Tour"),
            NULL);

        return 1;
    }

    ShowWindow(hWnd, nCmdShow);

    // Main message loop:
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HRESULT hr;
    PAINTSTRUCT ps;
    HDC hdc;


    switch (message)
    {
    case WM_CREATE:
        AddMenus(hWnd);
        AddControls(hWnd);
        hr = BufferedPaintInit();
        break;
    case WM_COMMAND:
        switch (wParam)
        {
        case FILE_MENU_EXIT:
            // File Menu Exit
            DestroyWindow(hWnd);
            break;
        case FILE_OPEN:
            OpenFileWindow(hWnd);
            flag = 1;
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        }
        break;
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC screen = BeginPaint(hWnd, &ps);
        /*Gdiplus::Graphics gf(screen);
        Gdiplus::Bitmap jpgicon(L"jpg-icon.png");
        Gdiplus::Bitmap pdficon(L"pdf-icon.png");
        gf.DrawImage(&jpgicon, 10, 10);
        gf.DrawImage(&pdficon, 900, 10);*/
        if (flag)
        {
            HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
            if (hbuff)
            {
                RECT rc;
                GetClientRect(hWnd, &rc);
                FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
                //DrawText(screen, L"Multi-Purpose Media Editor", -1, &rc, DT_BOTTOM | DT_VCENTER | DT_SINGLELINE); 
                putImage(screen, hWnd);
                hr = EndBufferedPaint(hbuff, TRUE);
            }
            flag = 0;
        }
        EndPaint(hWnd, &ps); } break;
    case WM_DESTROY:
        BufferedPaintUnInit();
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}

void AddMenus(HWND hWnd)
{
    hMenu = CreateMenu();
    HMENU hFileMenu = CreateMenu();
    HMENU hSubMenu = CreateMenu();

    // File Open Submenu
    /*AppendMenu(hSubMenu, MF_STRING, FILE_OPEN_JPG, s2ws("JPG").c_str());
    AppendMenu(hSubMenu, MF_STRING, FILE_OPEN_PDF, s2ws("PDF").c_str());*/

    // File Popup Menu
    // (UINT_PTR)hSubMenu <- for submenu
    AppendMenu(hFileMenu, MF_POPUP, FILE_OPEN, s2ws("Open").c_str());
    AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
    AppendMenu(hFileMenu, MF_STRING, FILE_MENU_EXIT, s2ws("Exit").c_str());

    // Main Menu
    AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, s2ws("File").c_str());
    AppendMenu(hMenu, MF_STRING, MENU_HELP, s2ws("Help").c_str());

    SetMenu(hWnd, hMenu);
}

void AddControls(HWND hWnd)
{
    // Static and Edit Controls
    CreateWindowW(L"static", L"Multi-Purpose Media Editor", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, GetSystemMetrics(SM_CXSCREEN) / 2, 10, 180, 30, hWnd, NULL, NULL, NULL);
    // Button on Window
    //CreateWindowW(L"button", L"JPG Editor", WS_VISIBLE | WS_CHILD, 190, 150, 100, 30, hWnd, NULL, NULL, NULL);
    //CreateWindowW(L"button", L"PDF Editor", WS_VISIBLE | WS_CHILD, 770, 150, 100, 30, hWnd, NULL, NULL, NULL);
    CreateWindowW(L"button", L"Edit Image", WS_VISIBLE | WS_CHILD, GetSystemMetrics(SM_CXSCREEN) / 4, 3 * GetSystemMetrics(SM_CYSCREEN) / 4, 100, 30, hWnd, (HMENU)FILE_OPEN, NULL, NULL);
    CreateWindowW(L"button", L"Edit PDF", WS_VISIBLE | WS_CHILD, 3 * GetSystemMetrics(SM_CXSCREEN) / 4, 3 * GetSystemMetrics(SM_CYSCREEN) / 4, 100, 30, hWnd, NULL, NULL, NULL);
}

void OpenFileWindow(HWND hWnd)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr))
    {
        IFileOpenDialog* pFileOpen;

        // Create the FileOpenDialog object.
        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
            IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));

        if (SUCCEEDED(hr))
        {
            // Show the Open dialog box.
            hr = pFileOpen->Show(NULL);

            // Get the file name from the dialog box.
            if (SUCCEEDED(hr))
            {
                IShellItem* pItem;
                hr = pFileOpen->GetResult(&pItem);
                if (SUCCEEDED(hr))
                {
                    PWSTR pszFilePath;
                    hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

                    // Display the file name to the user.
                    if (SUCCEEDED(hr))
                    {
                        char szBuffer[255];
                        WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
                        // JPG/JPEG/PNG
                        if (1)
                        {
                            filePath = pszFilePath;
                        }
                        // PDF
                        //else if ()
                        //{

                        //}
                        // Error MSG
                        else
                        {
                            MessageBox(NULL, L"Not a supported media!", L"Error", MB_OK);
                        }
                        //LoadImageW(hInst, pszFilePath, 0, 0, 0, LR_DEFAULTSIZE);
                        //MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
                        CoTaskMemFree(pszFilePath);
                    }
                    pItem->Release();
                }
            }
            pFileOpen->Release();
        }
        CoUninitialize();
    }
}

void putImage(HDC hdc, HWND hWnd)
{
    Graphics graphic(hdc);
    Image* image = Image::FromFile(filePath);
    Status status = graphic.DrawImage(image, 10, 20);
    RECT updateRect = { 0 };
    updateRect.left = 10;
    updateRect.top = 10;
    updateRect.right = updateRect.left + image->GetWidth();
    updateRect.bottom = updateRect.top + image->GetHeight();
    //RedrawWindow(hWnd, &updateRect, NULL, RDW_INVALIDATE);
    //RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

推荐阅读