Search code examples
cwinapigdi+gdi

How to use GDI+ in C?


Disclaimer: I'm only getting started in C, so it's likely that I'm missing something obvious, or not thinking the right way! :)

How exactly would I go about using GDI+ in pure C? As I understand it, GDI+ has wrapped objects made for C++, but underneath it lies a flat API which is accessible through gdiplusflat.h, a C-friendly header.

My problem is that when I #include it, I get the following errors:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(30) : error C2143: syntax error : missing '{' before '__stdcall'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2146: syntax error : missing ')' before identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2061: syntax error : identifier 'brushMode'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ';'
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ','
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include\gdiplusflat.h(31) : error C2059: syntax error : ')'
and 100 more...

Now, I think these errors are due to GpStatus not being defined because peeking into GdiPlusFlat.h shows that all the functions are of the style:

// WINGDIAPI is #defined as __stdcall
GpStatus WINGDIPAPI
GdipCreatePath(GpFillMode brushMode, GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2(GDIPCONST GpPointF*, GDIPCONST BYTE*, INT, GpFillMode,
                                    GpPath **path);
GpStatus WINGDIPAPI
GdipCreatePath2I(GDIPCONST GpPoint*, GDIPCONST BYTE*, INT, GpFillMode,
                                     GpPath **path);
etc...

The problem is that GpStatus is a typedef to Status in GdiPlusGpStubs.h (a C++ header), and Status is itself an enum defined in GdiPlusTypes.h (also a C++ header). I tried defining the enum myself, but for some reason the compiler wouldn't take it!

So... how does one exactly use GDI+ functions in C? Should I just load gdiplus.dll dynamically?


Solution

  • The problem is that gdiplusflat.h really needs many more gdi*.h header files included before it. But many of these header files that have the needed typedef declarations referenced by gdiplusflat.h also contain "class" declarations and other C++ keywords. The C compiler will error out when it sees these lines.

    You have two choices.

    1. Simple. Accept the fact that C++ is essentially a superset of C. Then just rename your ".c" file you are trying to compile to have a ".cpp" extension. Your C code will get compiled as C++, but that likely won't change a line of code you write. Then #include gdiplus.h before you #include gdiplusflat.h

    2. Harder. depends on typedef definitions in other header files. The problem is that many of these header files have "class" definitions and C++ keywords that the C compiler will error out on. You'll have to manually port over many of the C declarations into your own header file that gets included before gdiplusflat.h. Here's my feeble attempt. It's not quite done. It gets half of the compilation errors out. But I got too tired and just went with option #1. You could finish it, but option 1 above is so much easier.

    x

    enum Status
    {
        Ok = 0,
        GenericError = 1,
        InvalidParameter = 2,
        OutOfMemory = 3,
        ObjectBusy = 4,
        InsufficientBuffer = 5,
        NotImplemented = 6,
        Win32Error = 7,
        WrongState = 8,
        Aborted = 9,
        FileNotFound = 10,
        ValueOverflow = 11,
        AccessDenied = 12,
        UnknownImageFormat = 13,
        FontFamilyNotFound = 14,
        FontStyleNotFound = 15,
        NotTrueTypeFont = 16,
        UnsupportedGdiplusVersion = 17,
        GdiplusNotInitialized = 18,
        PropertyNotFound = 19,
        PropertyNotSupported = 20,
    #if (GDIPVER >= 0x0110)
        ProfileNotFound = 21,
    #endif //(GDIPVER >= 0x0110)
    };
    
    
    
    typedef Status GpStatus;
    
    enum FillMode
    {
        FillModeAlternate,        // 0
        FillModeWinding           // 1
    };
    
    typedef FillMode GpFillMode;
    
    struct GpPath {};
    
    typedef float REAL;
    
    struct GpPointF
    {
        REAL x;
        REAL y;
    };
    
    struct GpPoint
    {
        int x;
        int y;
    };
    #include <gdiplusflat.h>