Listview avec un watermark

Il existe quelques dossiers spéciaux dans Windows XP qui possèdent un watermark, aussi appelé filigrane en français, en bas à droite. Voici l’exemple du dossier Ma musique:

Listview with a watermark

Le but de cet article est de vous aider à faire la même chose dans un TListview sous C++Builder. Pour que l’effet soit réussi, je vous suggère d’utiliser un fichier de type PNG ou icône car ces deux formats permettent l’utilisation du canal alpha. Si vous décidez d’utiliser le format PNG, je vous conseille de jeter un coup d’œil à mon article qui explique comment charger une image dans les ressources. Parce qu’il est plus simple de faire un code qui charge l’icône de l’application, c’est ce format que nous utiliserons.

La première étape est bien sûr de créer un nouveau projet auquel on ajoute un contrôle TListView. Vous pouvez y ajouter quelques TListColumns et TListItems pour faire un peu plus réel.

Étant donné que j’ai décidé d’utiliser un auto_ptr, il faut inclure l’entête suivant dans votre fichier cpp.

#include <memory>

Dans le constructeur de la Form, ajoutez le code suivant:

static std::auto_ptr<Graphics::TBitmap> Bitmap(new Graphics::TBitmap);
Bitmap->Canvas->Brush->Color = ListView1->Color;
Bitmap->SetSize(32, 32); // Le casque romain est seulement en 32x32 pixels
Bitmap->Canvas->Draw(0, 0, Application->Icon);
 
LVBKIMAGE lv;
lv.ulFlags = LVBKIF_TYPE_WATERMARK;
lv.hbm = Bitmap->Handle;
ListView_SetBkImage(ListView1->Handle, &lv);
ListView_SetTextBkColor(ListView1->Handle, CLR_NONE);

La première ligne sert à créer une image de type Bitmap. Ce format est nécessaire car la fonction qui va être utilisée plus tard nécessite comme paramètre un HBITMAP. Le seconde ligne va servir à définir la couleur de fond de l’image. Si on effectue cette tâche avant d’établir la grandeur de l’image, l’image sera alors automatiquement de cette couleur. Cela évite d’avoir à dessiner un rectangle de la grandeur du Bitmap par la suite. À la troisième ligne, on utilise une grandeur de 32 par 32 pixels, car c’est la grandeur de l’icône de l’application. L’image par défaut dans C++Builder 2010 est un casque romain. La ligne d’après est utilisée pour dessiner l’icône sur le Bitmap. Maintenant, l’image est prête à être utilisée.

Les lignes 6 à 8 servent à remplir une structure de type LVBKIMAGE qui sera utilisée par la fonction ListView_SetBkImage à la ligne 9.

On pourrait penser que l’on a terminé, eh bien non. Il reste un petit tour de passe nécessaire pour voir notre image dans la listview.

Dans votre fichier d’en-tête, ajoutez les déclarations suivantes dans la section private:

void __fastcall ListViewWndProc(Messages::TMessage &Message);
Classes::TWndMethod OldListViewProc;

Ensuite, on retourne dans le constructeur de la Form pour ajouter ce code qui sert à rediriger les appels de Windows à la listview vers la méthode ListViewWndProc:

OldListViewProc = ListView1->WindowProc;
ListView1->WindowProc = ListViewWndProc;

Il faut par la suite ajouter cette méthode:

void __fastcall TForm1::ListViewWndProc(Messages::TMessage &Message)
{
    if(Message.Msg == WM_ERASEBKGND)
    {
        ListView1->DefaultHandler(&Message);
        return;
    }
    OldListViewProc(Message);
}

Si ce code n’est pas utilisé, l’événement WMEraseBkgnd de la classe TWinControl, l’ancêtre de TListView, sera appelé. Cette méthode empêche le message WM_ERASEBKGND de se rendre à la procédure par défaut. C’est pourquoi la méthode DefaultHandler de la listview est appelée et que l’on interdit un appel à OldListViewProc si on reçoit ce message.

À présent, vous avez tout le code nécessaire pour faire votre propre watermark dans un contrôle de type listview.