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
| unit Frm_BackGround;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TFrmBackGround = class(TForm)
Background: TImage;
CkbBackGroundStretch: TCheckBox;
procedure FormCreate(Sender: TObject);
private
{ Déclarations privées }
FNewClientWP : TFarProc; // Pointer ça serait pareil, c'est juste plus lisible
FOldClientWP : TFarProc;
procedure FormWndProc(var Message: TMessage);
public
{ Déclarations publiques }
end;
var
FrmBackGround: TFrmBackGround;
implementation
{$R *.dfm}
procedure TFrmBackGround.FormCreate(Sender: TObject);
begin
if FileExists('.\Background.bmp') then
Background.Picture.Bitmap.LoadFromFile('.\Background.bmp');
// D'abord pour la nouvelle procédure de fenêre on crée une instance :
FNewClientWP := Classes.MakeObjectInstance(FormWndProc);
// la méthode MDIClientWndProc sera implémentée par la suite..
(*
On fait pointer le deuxième pointeur sur l'ancienne WindowProc
On établit la permutation des WindowProc avec la fonction API SetWindowLong
On remarque que l'on passe en argument le Handle de la fenêtre au complet
Pour une feneêtre MDI Main, cela serait le Handle de la zone Client et pas celui de la fenêtre au complet
*)
FOldClientWP := TFarProc(SetWindowLong(Handle, GWL_WNDPROC, Integer(FNewClientWP)));
end;
// Le but du jeu est d'intercepter les messages qui nous intéressent et de
// rediriger les autres vers l'ancienne WindowProc (par l'intermédiaire du
// pointeur OldWP)
procedure TFrmBackGround.FormWndProc(var Message: TMessage);
procedure BackGroungBlt(HDestDC: HDC; DestWidth, DestHeight: Integer; HSourceDC: HDC; SourceWidth, SourceHeight: Integer);
var
iH, iV: Integer;
DestHCount, DestVCount: Integer;
ClientRect: TRect;
begin
if CkbBackGroundStretch.Checked then
begin
StretchBlt(HDestDC, 0, 0, ClientWidth, ClientHeight, HSourceDC, 0, 0, SourceWidth, SourceHeight, SRCCOPY);
// appelle la fonction "copie en étirant une image"
end else
begin
DestHCount := DestWidth div SourceWidth;
DestVCount := DestHeight div SourceHeight;
// y = y + SourceHeight)
for iV := 0 to DestVCount do
begin
//x = x + SourceWidth)
for iH := 0 to DestHCount do
begin
BitBlt(HDestDC, iH*SourceWidth, iV*SourceHeight, SourceWidth, SourceHeight, HSourceDC, 0, 0, SRCCOPY);
// Copie l'image sur le "fond" de la zone client
end;
end;
end;
end;
procedure EraseBackGround(hWnd: HWND);
var
LocalHDC: HDC;
begin
LocalHDC := HDC(Message.WParam); // récupère le HDC du message
SelectPalette(LocalHDC, Background.Picture.Bitmap.Palette, True);
// récupère la palette de l'image que l'on a choisi pour fond
RealizePalette(LocalHDC); // applique la palette
// appelle la fonction "Affichage de l'image"
BackGroungBlt(LocalHDC, Width, Height, Background.Canvas.Handle,
Background.Picture.Bitmap.Width, Background.Picture.Bitmap.Height);
Message.Result := 0;// renvoie un message nul pour pas que l'ancienne WindowProc "intervienne"
end;
procedure QueryNewPalette(hWnd: HWND);
var
LocalHDC: HDC;
begin
LocalHDC := GetDC(hWnd); // récupère le Handle de la zone client
SelectPalette(LocalHDC, Background.Picture.Bitmap.Palette, True);
// récupère la palette de l'image que l'on a choisi pour fond
RealizePalette(LocalHDC);// applique la palette
InvalidateRect(hWnd, nil, true); // provoque le raffraichissement de la zone client
ReleaseDC(hWnd, LocalHDC); // relache le Handle
Message.Result := 0;// renvoie un message nul pour pas que l'ancienne WindowProc "intervienne"
end;
procedure PaletteChanged(hWnd: HWND);
var
LocalHDC: HDC;
begin
// si le Handle transmis par le message est différent du Handle de la zone client
if (Message.WParam <> hWnd) then
begin
LocalHDC := GetDC(hWnd); // récupère le Handle de la zone client
SelectPalette(LocalHDC, Background.Picture.Bitmap.Palette, True);
// récupère la palette de l'image que l'on a choisi pour fond
RealizePalette(LocalHDC); // applique la palette
UpdateColors(LocalHDC); // raffraichit les couleurs
ReleaseDC(hWnd, LocalHDC); // relache le Handle de la zone client
end;
Message.Result := 0; // renvoie un message nul pour pas que l'ancienne WindowProc "intervienne"
end;
begin
case Message.Msg of
WM_ERASEBKGND: EraseBackGround(Handle);
WM_QUERYNEWPALETTE: QueryNewPalette(Handle);
WM_PALETTECHANGED: PaletteChanged(Handle);
WM_HSCROLL, WM_VSCROLL, WM_SIZE : InvalidateRect(Handle, nil, True);
else
Message.Result := CallWindowProc(FOldClientWP, Handle, Message.Msg, Message.WParam, Message.LParam);
end;
end;
end. |
Partager