Creation de bulles d'aide ( hint ) personnalisées

Description

Comme le titre l'indique, voici comment modifier la forme de la bulle d'aide de windows affichée quand la propriété ShowHint est à True sur un composant.

Cette méthode utilise des région afin de dessiner une fenêtre non rectangulaire ( voir aperçu ). C'est donc aussi un exemple de création et d'utilisation des régions de windows.

Source / Exemple :


Unit Unit1;
// Source écrit par Nono40   http://nono40.fr.st

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

Type
  TForm1 = Class(TForm)
    Button1: TButton;
    Label1: TLabel;
  Private
    { Déclarations privées }
  Public
    { Déclarations publiques }
  End;

Var
  Form1: TForm1;

Implementation

{$R *.dfm}

// Pour créer un bulle d'aide personnalisée, il faut créer une
// classe descendante de THintWindow et l'affecter à la variable
// globale HintWindowClass.
Type TMonHint = Class( THintWindow )
       Private
       Protected
         // Variable mise à TRUE à chaque affichage de la bulle
         // pour recréer la région adaptée à la taille du texte
         FCreerRegion  : Boolean;
         // Principalement Paint doit être surchargé pour pouvoir modifier le dessin de la bulle
         Procedure Paint;override;
         // La surcharge de CreateParams permet de modifier les propriété de la
         // fenêtre Windows encapsulée par le THintWindow
         // Ce n'est pas obligatoire, tout dépend du dessin souhaité
         Procedure CreateParams(Var Params: TCreateParams);Override;
       Public
         // Create est surchargé juste pour initialiser les variables
         Constructor Create(AOwner: TComponent); override;
         // ActiveHintData est appelée à chaque nouvel affichage de bulle d'aide.
         // Le fait de la surchargée permet d'être averti d'un nouveau texte
         Procedure ActivateHintData(Rect: TRect; Const AHint: String; AData: Pointer); override;
         // Si la taille par défaut de la bulle doit être modifiée
         // il faut surcharger CalcHintRect. Car cette méthode est appelée avant l'affichage de
         // la bulle pour en déterminer la taille.
         Function CalcHintRect(MaxWidth: Integer; Const AHint: String; AData: Pointer): TRect; override;
     End;

Constructor TMonHint.Create(AOwner: TComponent);
Begin
  Inherited Create(AOwner);
  // Create n'est surchargé que pour initialiser les variables
  FCreerRegion := False;
End;

Procedure TMonHint.CreateParams(Var Params: TCreateParams);
Begin
  Inherited CreateParams(Params);
  // CreateParams est surcharge pour modifier les paramètre Windows de la bulle.
  // Par défaut le stype est WS_POPUP OR WS_BORDER
  // La fenêtre n'étant pas carrée, il est inutile de dessiner le bord
  Params.Style := WS_POPUP;
End;

// Cette méthode est appelée à chaque nouvelle bulle d'aide
// On ne fait que signaler que la région de la fenêtre doit être changée
Procedure TMonHint.ActivateHintData(Rect: TRect; Const AHint: String; AData: Pointer);
Begin
  Inherited;
  FCreerRegion:=True;
End;

// Cette méthode calcul la taille de la bulle en fonction du texte
Function TMonHint.CalcHintRect(MaxWidth: Integer; Const AHint: String; AData: Pointer): TRect;
Begin
  // La taille est largeur est limitée à 200 pixels
  // C'est plus joli pour les textes longs
  MaxWidth:=200;

  // La valeur par défaut est mofiée afin de d'avoir la place de dessiner
  // les contours et la flêche suppérieure.
  Result:=Inherited CalcHintRect(MaxWidth,AHint,AData);
  Inc(Result.Right ,10);
  Inc(Result.Bottom,30);
End;

// Paint est la méthode de dessin de la bulle
Procedure TMonHint.Paint;
Const Points:Array[1..3]Of TPoint=(( x:18 ; y:20 ),( x:23 ; y:0 ),( x:33;y:20 ));
Var Rect : TRect;
    Rgn1 : HRgn;
    Rgn2 : HRgn;
Begin
  // ClientRect à été déterminé par la méthode CalcHintRect.
  // On se sert alors de la zone Client pour calculer la région
  Rect := ClientRect;

  // FCreerRegion est mis à true à chaque apparition de la bulle d'aide.
  // Donc s'il est à True il faut recalculer la région de la fenêtre en
  // fonction du nouveau texte
  If FCreerRegion Then
  Begin
    // Création d'une région rectangulaire avec les coins arrondis.
    Rgn2 :=CreateRoundRectRgn(Rect.Left,Rect.Top+20,Rect.Right,Rect.Bottom,30,30);
    // Création d'une région sous forme de triangle placé au dessus de la région
    // précédente
    Rgn1 :=CreatePolygonRgn  (Points,3,ALTERNATE);
    // Les deux régions sont ajoutées afin de créer la forme finale de la bulle
    CombineRgn(Rgn2,Rgn2,Rgn1,RGN_OR);
    // Rgn1 n'est plus utile...
    DeleteObject(Rgn1);
    // La forme de la bulle ( région ) est appliqué afin que la fenêtre Windows
    // en prenne la forme.
    SetWindowRgn(Handle,Rgn2,True );
    // Ceci n'est effectué qu'une fois pour chaque appartion de la bulle
    // Car la fenêtre Windows conserve sa région jusqu'a la destruction
    // ou l'association d'une autre région
    FCreerRegion:=False;
  End;

  // Pour effectuer le dession lui-même, on récupère la région de base
  // Rgn1 est créé avec une région "bidon" car il faut seulement qu'elle existe
  // avant l'appel de GetWindowRgn
  rgn1:=CreateRectRgn(0,0,10,10);
  GetWindowRgn(Handle,rgn1);

  // FrameRgn() est une fonction qui dessine un contour autour de la région
  // même si celle-ci est d'une forme complexe.
  Canvas.Brush.Color:=$606060;
  FrameRgn(Canvas.Handle,rgn1,Canvas.Brush.Handle,2,2);
  Canvas.Brush.Color:=$A0A0A0;
  FrameRgn(Canvas.Handle,rgn1,Canvas.Brush.Handle,1,1);
  DeleteObject(rgn1);

  // Il re reste qu'a dessiner le texte au centre de la partie basse de la bulle
  InflateRect(Rect,-5,-5);
  Inc(Rect.Top,22);
  // La couleur du fond est la couleur par défaut
  Canvas.Brush.Color:=Application.HintColor;
  // Et dessin effectif du texte
  DrawText(Canvas.Handle, PChar(Caption), -1, Rect , DT_CENTER Or DT_NOPREFIX Or DT_WORDBREAK);
End;

Initialization
  // Il faut bien sur définir notre nouvelle bulle d'aide comme étant
  // classe utilisée par défaut.
  HintWindowClass:=TMonHint;
End.

Conclusion :


Cette source et quelques autres sur : http://nono40.developpez.com

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.