EmfToWmfBits API всегда возвращает 0

Я хочу использовать API EmfToWmfBits. И сначала я попытаюсь создать класс Metafile, а затем вызвать этот API. Я думаю, проблема в том, как я создаю класс.

 Metafile myMetafile(szArglist[1]);

Таким образом, я получаю объект myMetafile, но он ничего не содержит. Я имею в виду, что родное изображение в этом объекте имеет значение NULL, которое должно указывать на метафайл на моем диске. Поэтому позже, когда я вызываю API EmfToWmfBits, он дает мне ноль.

Я предполагаю, что проблема может заключаться в том, что класс Metafile должен принимать строку wchar. А имя файла на диске не wchar? Я пробовал так.

 Metafile myMetafile(L"bird.emf");

А также это.

 Metafile myMetafile(L"鸟.emf");

Я уверен, что файл emf находится в одном каталоге с exe. Но все они потерпели неудачу.

Это код, который я использовал.

#include <iostream>
#include <stdio.h>
#include <WINDOWS.H>
#include <shellapi.h>
#include <gdiplus.h>

#pragma comment(lib,"gdiplus.lib")
#pragma comment(lib, "shell32.lib")

using namespace Gdiplus;


int main(int argc, char **argv)
{
    UINT size1 = 0;
    int argcount;
    LPWSTR* szArglist;

    if (argc < 2) {
        std::cout << "Please input a file name" << std::endl;
        return 0;
    }


    szArglist = CommandLineToArgvW(GetCommandLineW(), &argcount);
    Metafile myMetafile(szArglist[1]);
    LocalFree(szArglist);
    HENHMETAFILE hEmf = myMetafile.GetHENHMETAFILE();
    size1 = Metafile::EmfToWmfBits(
        hEmf,
        0,
        NULL,
        MM_ANISOTROPIC,
        EmfToWmfBitsFlagsEmbedEmf);
    std::cout << size1 << std::endl;

}

Обычно этот API-интерфейс EmfToWmfBits должен возвращать длину преобразованного файла. Детали этого API здесь. https://docs.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nf-gdiplusheaders-metafile-emftowmfbits Буду признателен, если кто-нибудь поможет мне здесь.


person Xudong Shao    schedule 09.09.2019    source источник
comment
Как вы запускаете программу? Каков текущий рабочий каталог программы, когда вы ее запускаете? Если вы запускаете из среды IDE (например, Visual Studio), то рабочим каталогом обычно является корневой каталог проекта, а не каталог, в котором находится исполняемый файл. Вы можете использовать GetCurrentDirectory, чтобы найти out или попробуйте указать полный абсолютный путь к файлу.   -  person Some programmer dude    schedule 09.09.2019
comment
@Someprogrammerdude Спасибо за ваш ответ. Я на самом деле скомпилировал его, а затем запустил в cmd. Поэтому я убедился, что exe и файл emf находятся в одном каталоге.   -  person Xudong Shao    schedule 09.09.2019
comment
Классы-оболочки C++ для GDI+ не создают исключений. Это делает абсолютно необходимым писать явный код проверки ошибок, чтобы вы могли обнаруживать основные ошибки, такие как забывание инициализировать библиотеку. Или простые вещи, такие как файл не найден. Добавление myMetafile.GetLastStatus() не является обязательным.   -  person Hans Passant    schedule 09.09.2019


Ответы (1)


Вам нужно инициализировать GDI+.

Функция GdiplusStartup инициализирует Windows GDI+. Вызовите GdiplusStartup перед любыми другими вызовами GDI+ и вызовите GdiplusShutdown после завершения использования GDI+.

Добавлять:

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

Это измененный код, только для справки.

#include <iostream>
#include <stdio.h>
#include <WINDOWS.H>
#include <shellapi.h>
#include <gdiplus.h>
#include <Shlwapi.h>

#pragma comment (lib,"Shlwapi.lib")
#pragma comment(lib,"gdiplus.lib")
#pragma comment(lib, "shell32.lib")

using namespace Gdiplus;

int main(int argc, char **argv)
{
    UINT size1 = 0;
    WCHAR path[MAX_PATH];

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

    GetModuleFileNameW(NULL, path, MAX_PATH);
    PathRemoveFileSpecW(path);
    PathAppendW(path, L"temp.emf");
    Metafile myMetafile(path);

    HENHMETAFILE hEmf = myMetafile.GetHENHMETAFILE();
    size1 = Metafile::EmfToWmfBits(
        hEmf,
        0,
        NULL,
        MM_ANISOTROPIC,
        EmfToWmfBitsFlagsEmbedEmf);
    std::cout << size1 << std::endl;
    GdiplusShutdown(gdiplusToken);
    return 0;
}

Я использую GetModuleFileNameW для получения полный путь к файлу, содержащему указанный модуль.

person Strive Sun    schedule 09.09.2019
comment
Спасибо. Действительно полезное и подробное решение. Это решает мою проблему. - person Xudong Shao; 09.09.2019