I. Afficher une image dans le fond d'une application MDI▲
La stratégie est la suivante : nous allons détourner la méthode originale qui gère la zone client de la fenêtre MDI pour la remplacer par une méthode de substitution qui mettra en place une mosaïque d'image.
Dans le code qui va suivre, j'ai appelé ma Form principale « Main ». Bien sur sa propriété FormStyle est à fsMDIForm;
On en profite pour placer l'image de fond dans un TImage que l'on appelle Background.( attention, il est impératif que l'image placée dans le fond soit un Bitmap que l'on place dans la propriété : Picture.Bitmap du TImage).
Premièrement on va définir deux pointeurs de fonctions que l'on va utiliser pour le traitement des procédures de fenêtres : NewClientWP etOldClientWP ;
On va aussi définir la méthode de dessin qui permet d'afficher une mosaïque à partir de l'image :
Et enfin la nouvelle procédure de fenêtre :
Soit :
Ensuite dans le constructeur de la Form on va initialiser les pointeurs de fonctions :
Ensuite on va implémenter la nouvelle méthode qui gère la procédure de fenêtre de la zone client
Dans l'événement OnDestroy on libère la procédure de substitution
Enfin nous allons implémenter la fonction qui affiche la mosaïque.
Voilà tout est là. Pour ceux qui ne veulent pas d'une mosaïque mais une image étirée (voir n'importe quoi d'autre…)
Il faut bien sûr modifier MDIClientWndProc en conséquence.
Par exemple pour l'image étirée voici la partie de code à modifier :
Bon courage !
Dans le code qui va suivre, j'ai appelé ma Form principale « Main ». Bien sur sa propriété FormStyle est à fsMDIForm;
On en profite pour placer l'image de fond dans un TImage que l'on appelle Background.( attention, il est impératif que l'image placée dans le fond soit un Bitmap que l'on place dans la propriété : Picture.Bitmap du TImage).
Premièrement on va définir deux pointeurs de fonctions que l'on va utiliser pour le traitement des procédures de fenêtres : NewClientWP etOldClientWP ;
On va aussi définir la méthode de dessin qui permet d'afficher une mosaïque à partir de l'image :
Sélectionnez
procedure
TileBlt( HDestDC :HDC, DestWidth,int DestHeight,HDC HSourceDC,int SourceWidth,int SourceHeight);
Sélectionnez
MDIClientWndProc(var
Msg:TMessage );
Sélectionnez
type
TMain = class
(TForm)
Background: TImage;
procedure
FormDestroy(Sender: TObject);
private
{
Déclarations
privées
}
NewClientWP : FARPROC;
OldClientWP : FARPROC ;
procedure
TileBlt(HDestDC : HDC; DestWidth : integer
; DestHeight : integer
;
HSourceDC : HDC; SourceWidth : integer
; SourceHeight:integer
);
procedure
MDIClientWndProc(var
Msg :TMessage);
public
{
Déclarations
publiques
}
constructor
Create(AOwner : TComponent);override
;
end
;
Sélectionnez
constructor
TMain.Create(AOwner : TComponent);
begin
inherited
;
//
D'abord
pour
la
nouvelle
procédure
de
fenêtre
on
crée
une
instance
NewClientWP := FARPROC(MakeObjectInstance(MDIClientWndProc));
//
On
fait
pointer
le
deuxième
pointeur
sur
l'ancienne
WindowProc
et
on
établit
la
permutation
des
//
WindowProc
avec
la
fonction
API
SetWindowLong.
//
On
remarque
que
l'on
passe
en
argument
le
Handle
de
la
zone
Client
et
pas
celui
de
la
fenêtre
au
complet
OldClientWP := FARPROC(SetWindowLong(ClientHandle, GWL_WNDPROC,LONGint
(NewClientWP)));
end
;
Sélectionnez
procedure
TMain.MDIClientWndProc(var
Msg :TMessage);
var
ThisHdc : HDC ;
begin
case
(Msg.Msg) of
//
traitement
classique
du
message
WM_ERASEBKGND: //
message
"efface
le
fond"
begin
ThisHdc := HDC(Msg.WParam); //
récupère
le
HDC
de
la
fenêtre
SelectPalette(ThisHdc, Background.Picture.Bitmap.Palette, true
);
{
récupère
la
palette
de
l'image
que
l'on
a
choisi
pour
fond
}
RealizePalette(ThisHdc); //
applique
la
palette
TileBlt(ThisHdc, Width, Height,
Background.Canvas.Handle,
Background.Picture.Bitmap.Width,
Background.Picture.Bitmap.Height); //
appelle
la
fonction
"Mosaique
de
l'image"
Msg.Result := 0
;//
renvoie
un
message
nul
pour
pas
que
l'ancienne
WindowProc
"intervienne"
end
;//
fin
case
WM_ERASEBKGND
WM_QUERYNEWPALETTE :
begin
ThisHdc := GetDC(ClientHandle); //
récupère
le
HDC
de
la
fenêtre
SelectPalette(ThisHdc, Background.Picture.Bitmap.Palette,true
);
{
récupère
la
palette
de
l'image
que
l'on
a
choisi
pour
fond
}
RealizePalette(ThisHdc);//
applique
la
palette
InvalidateRect(ClientHandle, nil
, true
); //
provoque
le
rafraichissement
de
la
zone
client
ReleaseDC(ClientHandle, ThisHdc); //
relache
le
Handle
Msg.Result := 0
;//
renvoie
un
message
nul
pour
pas
que
l'ancienne
WindowProc
"intervienne"
end
;
WM_PALETTECHANGED: //
message
palette
changée
begin
if
HWND(Msg.WParam) <> ClientHandle then
{
si
le
Handle
transmis
par
le
message
est
différent
du
Handle
de
la
zone
client
}
begin
ThisHdc := GetDC(ClientHandle); //
récupére
le
Handle
de
la
zone
client
SelectPalette(ThisHdc, Background.Picture.Bitmap.Palette, true
); {
récupère
la
palette
de
l'image
choisie
pour
fond
}
RealizePalette(ThisHdc); //
applique
la
palette
UpdateColors(ThisHdc); //
raffraichit
les
couleurs
ReleaseDC(ClientHandle, ThisHdc); //
relache
le
Handle
de
la
zone
client
end
;
Msg.Result := 0
; //
renvoie
un
message
nul
pour
pas
que
l'ancienne
WindowProc
"intervienne"
end
;
WM_HSCROLL:
begin
InvalidateRect(ClientHandle, nil
, true
); //
provoque
le
rafraichissement
de
la
zone
client
end
;
WM_VSCROLL://
message
scroll
vertical
begin
InvalidateRect(ClientHandle, nil
, true
); //
provoque
le
rafraichissement
de
la
zone
client
end
;
WM_SIZE :
begin
InvalidateRect(ClientHandle, nil
, true
); //
provoque
le
rafraichissement
de
la
zone
client
end
else
begin
//
Si
le
message
ne
rentre
dans
aucun
des
cas
suivant,
on
appelle
l'ancienne
procédure
pour
//
le
traitement
"classique"
des
messages
Msg.Result := CallWindowProc(OldClientWP, ClientHandle, Msg.Msg,
Msg.WParam, Msg.LParam);
end
;
end
;
end
;
Sélectionnez
procedure
TMain.FormDestroy(Sender: TObject);
begin
SetWindowLong(ClientHandle, GWL_WNDPROC, LONGINT
(OldClientWP));
//
remise
en
place
de
l'ancienne
WindowProc
FreeObjectInstance(NewClientWP);
//
relachement
de
la
WindowProc
de
"remplacement"
end
;
Sélectionnez
procedure
TMain.TileBlt(HDestDC : HDC;DestWidth : integer
;DestHeight : integer
;
HSourceDC : HDC;SourceWidth : integer
;SourceHeight:integer
);
var
x,y :integer
;
RelativeX,RelativeY:integer
;
begin
RelativeX:=0
;
RelativeY:=0
;
for
y := 0
to
(DestHeight div
SourceHeight) do
begin
for
x:= 0
to
(DestWidth div
SourceWidth) do
begin
BitBlt(HDestDC,RelativeX, RelativeY, SourceWidth, SourceHeight, HSourceDC, 0
, 0
, SRCCOPY);
//
Copie
l'image
sur
le
"fond"
de
la
zone
client
inc(RelativeX, SourceWidth );
end
;
inc(RelativeY, SourceHeight );
RelativeX:=0
;
end
;
end
;
Il faut bien sûr modifier MDIClientWndProc en conséquence.
Par exemple pour l'image étirée voici la partie de code à modifier :
Sélectionnez
WM_ERASEBKGND : //
message
"efface
le
fond"
begin
Hdc: = (HDC)Msg.WParam; //
Récupère
le
HDC
du
message
SelectPalette(Hdc, Background.Picture.Bitmap.Palette, true
);
//
Récupère
la
palette
de
l'image
que
l'on
a
choisi
pour
fond
RealizePalette(Hdc); //
applique
la
palette
StretchBlt(Hdc, 0
, 0
, Width, Height, Background.Canvas.Handle, 0
, 0
,
Background.Picture.Bitmap.Width,Background.Picture.Bitmap.Height, SRCCOPY);
//
appelle
la
fonction
"copie
en
étirant
une
image"
Msg.Result = 0
;//
renvoie
un
message
nul
pour
pas
que
l'ancienne
WindowProc
"intervienne"
end
;
0 commentaires:
Enregistrer un commentaire