C++Builder logo
GDI+ and C++Builder GDI+ et C++Builder

1. What is GDI+? GDI+, qu'est-ce que c'est?
GDI+ is the Microsoft new technology which will replace the old GDI from the old win32 API
Basically it's a set of .NET classes which hides all the video driver's details so you don't have to worry about which graphic card is used.
GDI+ is part of XP and redistributable for 98/ME/NT/2k. In other words, the gdiplus.dll is available in XP and you have to install it in the system directory with all other versions of Windows.
GDI+ est la nouvelle technologie de Microsoft destinée à remplacer l'ancienne GDI. Il s'agit essentiellement d'une série de classes .NET qui permettent de s'affranchir des détails du pilote de carte graphique utilisée.
GDI+ fait partie de XP et est redistribuable pour 98/ME/NT/2k. Pratiquement cela veut dire que la DLL gdiplus.dll existe sous XP mais qu'il faut l'installer dans le répertoire système pour les autres systèmes d'exploitation.

2. What's new? Qu'y a-t'il de neuf?
The more relevant news in GDI+ are:
- Alpha blending
- Gradient brushes
-Transformations and rotations
- Scalable regions
- Support for several image formats
Les nouveautés les plus marquantes sont:
- Alpha blending (transparence)
- Les dégradés
- Les transformations et rotations
- Scalable regions
- Support pour plusieurs formats d'image.

3. How to get GDI+? Comment obtenir GDI+?
If you have XP or .NET server, you don't have to do anything. For Windows 98/ME/NT/2k, you have to download gdiplus.dll and copy it to your system directory. You can get the DLL with the platform SDK on the Microsoft web site:
http://www.microsoft.com/msdownload/platformsdk/
sdkupdate/psdkredist.htm

Alternatively, you can download it from my site here. The zip file comes with the DLL, the Borland lib file, the header files and the help file
Si vous avez XP ou .NET serveur, vous ne devez rien faire du tout. Par contre, pour les autres systèmes d'exploitation, vous devez copier gdiplus.dll dans le directory système. Vous pouvez obtenir cette DLL sur le site de Microsoft:
http://www.microsoft.com/msdownload/platformsdk/
sdkupdate/psdkredist.htm

Vous pouvez aussi la downloader depuis mon site, ici. Le fichier .zip contient la DLL, le fichier .lib Borland correspondant, les fchiers d'entête et d'aide.

4. Can I use GDI+ with C++ Builder? Puis-je utiliser GDI+ avec C++ Builder?
Yes, at least for BCB version 5&6. The header files provided by Microsoft are incompatible with BCB4, though. First, you have to create a lib file from the DLL so that it can be used with Borland. Just type from a command line:
Bien sûr, du moins pour BCB version 5 et 6. Par contre, les fichiers d'entête de Microsoft sont incompatibles avec BCB4. Vous devez d'abord créer un fichier .lib compatible Borland. Pour cela, tapez la commande suivante:

implib -c -f gdiplus.lib gdiplus.dll


Include the path to the header files in your project's settings and define STRICT in your project's conditional defines.
Then, in your .cpp file, before including gdiplus.h, add these lines:
Ajoutez le path des fichiers d'entête dans les options de votre projet et STRICT dans les defines conditionels.
Ensuite, ajoutez ces lignes ci-dessous au début de votre fichier .cpp:

#define STRICT
#include <windows.h>
#include <algorithm>
using std::min;
using std::max;
#include <gdiplus.h>


Add the following declarations in the private section of your form (Unit.h):
Ajoutez dans la section private de votre form les déclarations suivantes:

Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR  gdiplusToken;


Now, add the code to initialize GDI+ in the constructor of your form for instance: Vous devez encore ajoutez le code pour initialiser GDI+ dans le constructeur de votre forme:

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


Add the code to shutdown GDI+ in the destructor:
Ajoutez le code pour fermer GDI+ dans le destructeur:

//shutdown GDI+
Gdiplus::GdiplusShutdown(gdiplusToken);


5. Code samples Exemples
The first sample just show you how to draw a picture on a canvas (device context). If you use a TImage on your form, replace the hdc parameter with Image1->Canvas->Handle:
Le premier exemple vous montre juste comment afficher une image sur un canevas (device context). Si vous avez placé un composant TImage sur votre forme, remplacez hdc par Image1->Canvas->Handle:

Gdiplus::Graphics graphics(hdc); //Handle to the device context
//Load the image from a file
Gdiplus::Image image(L"YourPicture.gif");
graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());


The second sample shows you one way to change the transparency of your image:
Le second exemple montre une méthode pour changer la transparence d'une image:

Gdiplus::Graphics graphics(hdc); //Handle to the device context
//Load the image from a file
Gdiplus::Image image(L"YourPicture.gif");

// Create an ImageAttributes object and set its color matrix.
Gdiplus::ImageAttributes imageAtt;
Gdiplus::ColorMatrix cm = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                           0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                           0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                           0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
cm.m[3][3]+=0.01f; //transparency

imageAtt.SetColorMatrix(&cm, Gdiplus::ColorMatrixFlagsDefault,
    Gdiplus::ColorAdjustTypeBitmap);

graphics.DrawImage(&image,
                   Gdiplus::Rect(0, 0, image.GetWidth(), image.GetHeight()),
                   0,
                   0,
                   image.GetWidth(),
                   image.GetHeight(),
                   Gdiplus::UnitPixel,
                   &imageAtt);


Here is how to draw a rotated string on a canvas:
Pour écrire du texte sur le canevas en effectuant une rotation:

Gdiplus::Graphics graphics(hdc); //Handle to the device context
//draw a rotated string
Gdiplus::graphics.RotateTransform (45);
Gdiplus::StringFormat format;
format.SetAlignment(Gdiplus::StringAlignmentCenter);
format.SetLineAlignment(Gdiplus::StringAlignmentCenter);
Gdiplus::Font myFont(L"Arial", 16);
Gdiplus::PointF origin(0,0);
Gdiplus::SolidBrush black(Gdiplus::Color(255, 0, 0, 0));
graphics.DrawString(L"String rotation",-1,&myFont,origin,&black);

The last sample show you how to load an image from a specific format and save it to another format. In this case, load a .gif file and save it to .png:
Le dernier exemple montre comment charger une image dans un certain format et la sauver sous un autre format. Ici, de .gif vers .png:

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
  unsigned int  num = 0;    // number of image encoders
  unsigned int  size = 0;   // size of the image encoder array in bytes
  
  Gdiplus::GetImageEncodersSize(&num, &size);
  if(size == 0)return -1;
  
  Gdiplus::ImageCodecInfo* imageCodecInfo = new Gdiplus::ImageCodecInfo[size];
  Gdiplus::GetImageEncoders(num, size, imageCodecInfo);
  
  for(unsigned int i = 0; i < num; ++i)
  {
    if( wcscmp(imageCodecInfo[i].MimeType, format) == 0 )
    {
       *pClsid = imageCodecInfo[i].Clsid;
       delete[] imageCodecInfo;
       return i;
    }    
  }
  delete[] imageCodecInfo;
  return -1;
}

Gdiplus::Graphics graphics(hdc); //Handle to the device context
//Load the image from a file
Gdiplus::Image image(L"YourPicture.gif");
//save image as .png
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
image.Save(L"slider.png", &pngClsid, NULL);


Note: You might have problems compiling code using GDI+. If some functions repeatedly return an error, check the following points: Put the STRICT define in the Project/Options/Conditionnal defines instead of putting it in your code. Graham Thompson reported that with BCB5  functions including enumerated parameters failed returning 'invalid parameter' error. Setting 'Treat enum types as ints' to true in the project's compiler options took the error off. Others reported that building the application in release mode helped too.

In my article about bitmap rotation, I give an example on how to rotate a bitmap using GDI+
Note: Si vous avez des erreurs lors de la compilation de certaines fonctions, vérifiez les points suivants: Placez la directive STRICT dans les 'conditionnal defines' du projet au lieu de le mettre dans le code. Graham Thompson signale aussi que les fonctions utilisant des paramètres de type enum retournaient une erreur. Dans son cas, la solution consista à mettre à true l'option 'Treat enum types as ints' dans les options du compilateur. D'autres personnes m'ont dit que compiler leur projet en release au lieu de debug a fait disparaître les erreurs.

Dans mon article sur la rotation des bitmaps, je donne aussi un exemple qui utilise GDI+.