3
Tags:
delphi
Skrevet af
Bruger #132
@ 26.10.2001
Translucent forms
Indledende bemærkninger.
Flg. er lavet med D5 under Win2000. Det virker, så vidt jeg ved, ikke under win9x eller WinMe. Jeg ved ikke med XP, men det vil sandsynligvis fungere.
Translucent, eller halvgennemsigtige, vinduer er, som navnet antyder, vinduer hvor man kan se det bagvedliggende igennem. Et eksempel på dette kan man se på muse-pointeren i Win2K. Hvis man kigger nøje på den, kan man se at der er en skygge til højre for. Det fænomen vil jeg prøve at lege lidt med i denne artikel.
Grader af gennemsigtighed.
Lad os først udforske gennemsigtigheden lidt. Start med en tom form med en TEdit og en TButton. Sæt TEdit.Text til
255. I TButton.OnClick skrives:
SetWindowLong(self.Handle, gwl_ExStyle, GetWindowLong(Handle, gwl_ExStyle) or ws_EX_Layered);
SetLayeredWindowAttributes(self.Handle, 0, strtoint(edit1.text), lwAlpha);
Nu er det sådan, at Delphi(I hvert fald ikke V5. Det kan være at det er med i V6, men så vil constanter/funktioner nok hedde noget andet) ikke kender noget til ws_EX_Layered, SetLayeredWindowAttributes eller lwAlpha. Vi må derfor definere dem selv med flg:
const
lwa_ColorKey = 1;
lwa_Alpha = 2;
ws_Ex_Layered = $80000;
function SetLayeredWindowAttributes (Wnd: hWnd; crKey: ColorRef; bAlpha: Byte; dwFlags:DWord):
Bool; stdcall; external 'user32.dll';
som placeres som globale konstanter (fx. lige efter Implementation).
Vores program ser nu således ud:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
const
//Constants for layered windows
lwa_Alpha = 2;
ws_Ex_Layered = $80000;
function SetLayeredWindowAttributes (Wnd: hWnd; crKey: ColorRef; bAlpha: Byte; dwFlags:DWord):
Bool; stdcall; external 'user32.dll';
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
SetWindowLong(self.Handle, gwl_ExStyle, GetWindowLong(Handle, gwl_ExStyle) or ws_EX_Layered);
SetLayeredWindowAttributes(self.Handle, 0, strtoint(edit1.text), lwa_alpha);
end;
end.
Kør det. Prøv at ændre tallet i editboksen og tryk på knappen. Tallet skal være under <=255 og >=0. Bemærk at alle
komponenter på formen også ændrer gennemsigtighed.
Skygger på forms
Det er jo meget sjovt. Det vi nu skal er at bruge denne teknik til at lave en skygge på en form. Det vil jeg gøre ved at lave to forms til skygger. En til højre og en nedenunder formen.
Start på en ny form. Kald Den ShadowForm. Koden til ShadowForm ser sådan ud (forklaring kommer efter):
unit TransForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls;
type
TShadowForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private declarations }
ShadowWidth: Integer;
RightShadow: TForm;
BotShadow: TForm;
FShadowIntensity: byte;
FShadowSize: integer;
procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message wm_WindowPosChanged;
procedure SetShadowIntensity(const Value: byte);
procedure SetShadowSize(const Value: integer);
public
{ Public declarations }
property ShadowSize: integer read FShadowSize write SetShadowSize;
property ShadowIntensity: byte read FShadowIntensity write SetShadowIntensity;
end;
var
ShadowForm: TShadowForm;
implementation
{$R *.DFM}
const
//Constants for layered windows
lwa_Alpha = 2;
ws_Ex_Layered = $80000;
function SetLayeredWindowAttributes (Wnd: hWnd; crKey: ColorRef; bAlpha: Byte; dwFlags:DWord):
Bool; stdcall;
external 'user32.dll';
procedure TShadowForm.FormCreate(Sender: TObject);
begin
FShadowSize := 7;
FShadowIntensity := 100;
RightShadow := TForm.Create(Self);
RightShadow.Parent := Application.MainForm;
RightShadow.BorderStyle := bsNone;
RightShadow.Width := ShadowSize;
RightShadow.Color := clBlack;
RightShadow.Visible := True;
SetWindowLong(RightShadow.Handle, gwl_ExStyle, GetWindowLong(Handle, gwl_ExStyle)
or ws_EX_Layered);
SetLayeredWindowAttributes(RightShadow.Handle, 0, ShadowIntensity, lwa_Alpha);
BotShadow := TForm.Create(Self);
BotShadow.Parent := Application.MainForm;
BotShadow.BorderStyle := bsNone;
BotShadow.Height := ShadowSize;
BotShadow.Color := clBlack;
BotShadow.Visible := True;
SetWindowLong(BotShadow.Handle, gwl_ExStyle, GetWindowLong(Handle, gwl_ExStyle)
or ws_EX_Layered);
SetLayeredWindowAttributes(BotShadow.Handle, 0, ShadowIntensity, lwa_Alpha);
FormResize(Sender);
end;
procedure TShadowForm.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
Inherited;
if Assigned(RightShadow) and RightShadow.Visible then
FormResize(Nil);
end;
procedure TShadowForm.FormResize(Sender: TObject);
begin
RightShadow.Height:= Height;
RightShadow.Left := Left + Width;
RightShadow.Top := Top + ShadowSize;
RightShadow.Width := ShadowSize;
BotShadow.Width := Width - ShadowSize;
BotShadow.Left := Left + ShadowSize;
BotShadow.Top := Top + Height;
BotShadow.Height := ShadowSize;
end;
procedure TShadowForm.SetShadowIntensity(const Value: byte);
begin
FShadowIntensity := Value;
SetLayeredWindowAttributes(RightShadow.Handle, 0, ShadowIntensity, lwa_Alpha);
SetLayeredWindowAttributes(BotShadow.Handle, 0, ShadowIntensity, lwa_Alpha);
end;
procedure TShadowForm.SetShadowSize(const Value: integer);
begin
FShadowSize := Value;
FormResize(Self);
end;
end.
I FormCreate sætter vi først nogle default-værdier for størrelse og intensitet af skyggen. Dernæst creater vi først den højre form, sætter dens parent til vores egen form, fjerner borderen, sætter bredden til størrelsen af vores skygge, gør den sort, synlig og translucent som i den første demo. Derefter laver vi den nederste skygge efter samme opskrift. Til sidst kalder vi FormResize for at placere skyggerne korrekt. I FormResize ligger udregningen af placering og størrelse af skygger. Grunden til dette er at disse udregninger skal foretages hver gang vi ændrer på størrelsen af vores vindue. Vi vil også gerne have vores skygger til at flytte rundt sammen med vinduet. Derfor fanger vi WMWindowPosChanged, som bliver sendt hver gang en form ændrer position. Når vi får den skal skyggerne gentegnes, hvilket sker med et kald til resize. Når vi ændrer på skyggens størrelse eller intensitet gennem de to properties, skal der ligeledes gentegnes, hvilket sker i de to set-rutiner.
Nu er vi klar til at bruge vores skygge-form. Start på et nyt program. Tilføj uniten med TShadowForm i uses-linien. Ret "TForm1 = class(TForm)" til "TForm1 = class(TShadowForm)" og kør programmet. Prøv at flytte rundt på vinduet og resize det. størrelse og intensitet kan ændres med ShadowSize := xxx og ShadowIntensity := yyy.
Jeg ved ikke om det her på nogen måde er brugbart, men det er da meget sjovt at lege med... :-) God Fornøjelse.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (0)
Du skal være
logget ind for at skrive en kommentar.