0

I want to use the EmfToWmfBits api. And first I will try to create a Metafile class then call this api. I think the problem is in the way I create the class.

 Metafile myMetafile(szArglist[1]);

This way gives me the object myMetafile, but it contains nothing. I mean the nativeimage in this object is NULL, which is supposed to point to the metafile on my disk. So later when I call the EmfToWmfBits api, it gives me zero.

I guess the problem might be the Metafile class should take a wchar string. And the filename on the disk is not wchar? I tried like this.

 Metafile myMetafile(L"bird.emf");

And also this.

 Metafile myMetafile(L"鸟.emf");

I am sure that the emf file is in the same directory with the exe. But all of them failed.

This is the code I used.

#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;

}

Normally, this EmfToWmfBits api should return the length of the converted file. The detail of this api is here. https://learn.microsoft.com/en-us/windows/win32/api/gdiplusheaders/nf-gdiplusheaders-metafile-emftowmfbits I would appreciate if anyone can help me here.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
Xudong Shao
  • 199
  • 3
  • 12
  • How do you run the program? What is the current working directory of the program when you run it? If you run from inside an IDE (like Visual Studio) then the working directory is usually the project root directory, not the directory where the executable file is located. You can use [`GetCurrentDirectory`](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcurrentdirectory) to find out, or try to provide a full absolute path to the file. – Some programmer dude Sep 09 '19 at 04:19
  • @Someprogrammerdude Thanks for your reply. I actually compiled it and then ran it in the cmd. So I made it sure the exe and the emf file is in the same directory. – Xudong Shao Sep 09 '19 at 05:42
  • 1
    The C++ wrapper classes for GDI+ don't throw exceptions. That makes it absolutely crucial to write explicit error checking code so you can detect basic mishaps like forgetting to initialize the library. Or simple stuff like file-not-found. Adding myMetafile.GetLastStatus() is not optional. – Hans Passant Sep 09 '19 at 07:16

1 Answers1

2

You need to initialize GDI+.

The GdiplusStartup function initializes Windows GDI+. Call GdiplusStartup before making any other GDI+ calls, and call GdiplusShutdown when you have finished using GDI+.

Add:

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

This is the modified code, for reference only.

#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;
}

I use GetModuleFileNameW to retrieve the fully qualified path for the file that contains the specified module.

Strive Sun
  • 5,988
  • 1
  • 9
  • 26