1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
| unit uHintSemiTransparent;
//******************************************************************************
// Pour créer des Hint rectangulaires personnalisés avec un fond semi-transparent
// et avec ombre style Windows XP si XP est détecté.
//
// - Le degré de transparence peut être réglé en modifiant la valeur du paramètre
// Delta lors de l'appel de la procédure EclaircirBmp. Attention une transparence
// trop nette peut altérer la lisibilité du texte du Hint.
// - La police de caractères et ses attributs peuvent être modifiés dans le Constructor TMonHint.Create
// - La couleur du contour du Hint et l'épaisseur de ses bords peuvent être modifiées
// dans la procedure TMonHint.Paint
//******************************************************************************
interface
uses
Windows, Classes, SysUtils, Graphics, Controls;
function BmpZoneEcran(xe,ye,w,h : integer) : tBitMap; // Copie zone d'écran
// (utilisé pour copier la zone-écran sous-jacente du Hint)
procedure EclaircirBmp(var Bmp : TBitMap; Delta : byte); // Augmente de Delta les composantes R,G,B du Bmp
// (utilisé pour créer l'effet de semi-transparence à partir de la copie d'écran)
// SUITE = code modifé à partir de http://nono40.developpez.com/sources/source0028/
// de façon à créer le Hint rectangulaire avec fond semi-transparent
//
// Pour créer une 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
BmpFond : TBitMap; //<- BitMap du Fond d'écran sous le Hint
Protected
FCreerRegion : Boolean; //<- Variable mise à TRUE à chaque affichage de la bulle
// pour recréer la région adaptée à la taille du texte
Procedure Paint;override; //<- Paint doit être surchargée de manière à personnaliser le dessin de la bulle
procedure CreateParams(var Params: TCreateParams);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é.
Public
constructor Create(AOwner: TComponent);override;
//<- Create est surchargé juste pour initialiser des variables
function CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; 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.
procedure ActivateHintData(Rect: TRect; const AHint: string; AData: Pointer); override;
//<- ActiveHintData est appelée à chaque nouvel affichage de bulle d'aide.
// Le fait de la surcharger permet d'être averti d'un nouveau texte
destructor Destroy; override;
End;
implementation
function BmpZoneEcran(xe,ye,w,h : integer) : tBitMap; // Copie zone d'écran
// xe,ye = coordonnées-écran de l'angle sup gauche
// w,h = width, height
var HandleDCBureau : HDC;
begin HandleDCBureau:=GetDC(GetDesktopWindow);
Result:=TBitMap.create;
try Result.Width := w;
Result.Height := h;
BitBlt( Result.Canvas.Handle,0,0,w,h,
HandleDCBureau,xe,ye,SrcCopy);
finally
ReleaseDC(GetDesktopWindow,HandleDCBureau);
end;
end;
procedure EclaircirBmp(var Bmp : TBitMap; Delta : byte); // Augmente de Delta les composantes R,G,B du Bmp
// si Delta = 0 alors transparence à 100%
// si Delta = 255 alors fond blanc opaque
type PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..0] of TRGBTriple;
var CPC : PRGBTripleArray; //Couleur Pixel Courant
R,G,B : byte; //Composantes R,G,B
x,y : integer;
begin //Force Bmp en 24 bits
Bmp.PixelFormat := pf24bit;
// Boucles d''éclaircissement :
for y := 0 to bmp.Height-1 do
begin CPC := Bmp.ScanLine[y];
for x := 0 to Bmp.Width-1 do
begin R:=CPC[x].rgbtRed; G:=CPC[x].rgbtGreen; B:=CPC[x].rgbtBlue;
if R+Delta<=255 then inc(R,Delta) else R:=255;
if G+Delta<=255 then inc(G,Delta) else G:=255;
if B+Delta<=255 then inc(B,Delta) else B:=255;
CPC[x].rgbtRed:=R; CPC[x].rgbtGreen:=G; CPC[x].rgbtBlue:=B;
end;
end;
end;
function IsWinXP: Boolean; // si true alors il s'agit de Windows XP
begin Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and
(Win32MajorVersion >= 5) and (Win32MinorVersion >= 1);
end;
Constructor TMonHint.Create(AOwner: TComponent);
begin Inherited Create(AOwner);
// Create n'est surchargé que pour initialiser des variables
FCreerRegion := False;
with Canvas.Font do
begin Name := 'Arial';
Style := [fsBold];
Color := clBlack;
end;
end;
procedure TMonHint.CreateParams(var Params: TCreateParams);
const CS_DROPSHADOW = $00020000; //<- ajout ombre style Windows XP si XP est détecté.
begin inherited CreateParams(Params);
// CreateParams est surchargée pour modifier les paramètres Windows de la bulle.
// Par défaut le stype est WS_POPUP OR WS_BORDER
if IsWinXP
then Params.WindowClass.Style := Params.WindowClass.Style or CS_DROPSHADOW
else Params.Style := WS_POPUP;
end;
// Cette méthode calcule la taille de la bulle en fonction du texte
function TMonHint.CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect;
begin // Limitation à 200 pixels de la taille en largeur, c'est plus joli
// pour les textes longs :
MaxWidth:=200;
Result:=Inherited CalcHintRect(MaxWidth,AHint,AData);
end;
// Cette méthode est appelée à chaque nouvelle bulle d'aide
procedure TMonHint.ActivateHintData(Rect: TRect; const AHint: string; AData: Pointer);
// Affiche le Hint aux coordonnées spécifiées par le paramètre Rect.
begin // Elargissement de Rect pour créer des marges gauche-droite :
with Rect do Right := Right + Canvas.TextWidth('oo');
if Assigned(BmpFond) then BmpFond.Free;
// Récup du BmpFond par copie d'écran :
BmpFond:=BmpZoneEcran(Rect.Left,Rect.Top,Rect.Right-Rect.Left,Rect.Bottom-Rect.Top+5);
EclaircirBmp(BmpFond, 160); //<- ici éclaircissement de 160 sur 255
Inherited;
FCreerRegion:=True;
end;
// Dessin de la bulle d''aide :
Procedure TMonHint.Paint;
const epBordVertical = 1; epBordHorizontal =1; //<Epaisseurs bords du contour
var Rect : TRect; Rgn1,Rgn2 : HRgn; DC : HDC;
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
Rgn2 :=CreateRectRgn(Rect.Left,Rect.Top,Rect.Right,Rect.Bottom);
// La forme de la bulle ( région ) est appliquée 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;
DeleteObject(rgn2);
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);
// Dessin du BmpFond semi-transparent sur le canvas du Hint :
Canvas.Brush.Bitmap:=BmpFond;
Canvas.FillRect(Rect);
// Dessin du contour autour du Hint :
DC := GetWindowDC(Handle);
// A) Soit avec FrameRgn utilisable même si la région est de forme complexe :
Canvas.Brush.Color:=clRed; //<- couleur rouge
FrameRgn(DC, rgn1, Canvas.Brush.Handle, epBordVertical, epBordHorizontal);
DeleteObject(rgn1);
// B) Soit avec DrawEdge si le Hint est rectangulaire (contour noir) :
//DrawEdge(DC, Rect, EDGE_ETCHED, BF_RECT or BF_MONO); //<- OK marche aussi
ReleaseDC(Handle, DC);
//Accentuation coin supérieur gauche du Hint :
with canvas do
begin pen.color:=clRed; pen.width:=4;
MoveTo(-2,3); LineTo(3,-2);
end;
// Dessin du texte au centre de la bulle :
InflateRect(Rect,-2,-2);
Canvas.Brush.Style:=bsClear;
DrawText(Canvas.Handle, PChar(Caption), -1, Rect , DT_CENTER or DT_NOPREFIX or DT_WORDBREAK);
End;
destructor TMonHint.Destroy;
begin if Assigned(BmpFond) then BmpFond.Free;
inherited;
end;
// La ligne suivante, au moins, doit être placée soit dans la procedure
// TForm1.FormCreate(Sender: TObject) de l'unité principale de l'application,
// soit dans sa partie Initialization :
// HintWindowClass:=TMonHint; //<- Pour déclarer la nouvelle bulle d'aide comme étant la classe utilisée par défaut
// Application.HintHidePause := 10000; //<- 10 secondes = Durée d'affichage du Hint, sinon valeur par défaut = 2 secondes 1/2
end. |
Partager