2005. október 18., kedd
Create a transparent form using regions
Problem/Question/Abstract:
When I override the CreateParams method of the TForm class and put an "or" clause to include a WS_EX_TRANSPARENT effect, all work fine. My Form appears with a transparent effect (or better, it does not appear. Only controls appear). But if I change the icons positions on the Desktop screen, my form does not get the changes and redraws itself. Well, I call redraw manually, but the form cannot get the desktop screen rectangle to correct the background of the form. How do I solve this problem? Is there a way to get a selected rectangle of the desktop screen to be copied to the canvas on the form?
Answer:
Here's a transparent form method that uses regions. It's so transparent, you can click right through to the underlying windows:
unit Unit1;
{The transparent form effect is done with regions. First create a region that encompasses the entire form. Then, find the client area of the form (Client vs. non-Client) and combine with the full region with RGN_DIFF to make the borders and title bar visible. Then create a region for each of the controls and combine them with the original (FullRgn) region.}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Panel1: TPanel;
Button2: TButton;
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private declarations }
procedure DoVisible;
procedure DoInvisible;
public
{ Public declarations }
end;
var
Form1: TForm1;
FullRgn, ClientRgn, CtlRgn: THandle;
implementation
{$R *.DFM}
procedure TForm1.DoInvisible;
var
AControl: TControl;
A, Margin, X, Y, CtlX, CtlY: Integer;
begin
Margin := (Width - ClientWidth) div 2;
{First, get form region}
FullRgn := CreateRectRgn(0, 0, Width, Height);
{Find client area region}
X := Margin;
Y := Height - ClientHeight - Margin;
ClientRgn := CreateRectRgn(X, Y, X + ClientWidth, Y + ClientHeight);
{'Mask' out all but non-client areas}
CombineRgn(FullRgn, FullRgn, ClientRgn, RGN_DIFF);
{Now, walk through all the controls on the form and 'OR' them into the existing Full region}
for A := 0 to ControlCount - 1 do
begin
AControl := Controls[A];
if (AControl is TWinControl) or (AControl is TGraphicControl) then
with AControl do
begin
if Visible then
begin
CtlX := X + Left;
CtlY := Y + Top;
CtlRgn := CreateRectRgn(CtlX, CtlY, CtlX + Width, CtlY + Height);
CombineRgn(FullRgn, FullRgn, CtlRgn, RGN_OR);
end;
end;
end;
{When the region is all ready, put it into effect:}
SetWindowRgn(Handle, FullRgn, TRUE);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{Clean up the regions we created}
DeleteObject(ClientRgn);
DeleteObject(FullRgn);
DeleteObject(CtlRgn);
end;
procedure TForm1.DoVisible;
begin
{To restore complete visibility:}
FullRgn := CreateRectRgn(0, 0, Width, Height);
CombineRgn(FullRgn, FullRgn, FullRgn, RGN_COPY);
SetWindowRgn(Handle, FullRgn, TRUE);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{We start out as a transparent form ...}
DoInvisible;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
{This button just toggles between transparent and not transparent}
if Button1.Caption = 'Show Form' then
begin
DoVisible;
Button1.Caption := 'Hide Form';
end
else
begin
DoInvisible;
Button1.Caption := 'Show Form';
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.Terminate;
end;
procedure TForm1.FormResize(Sender: TObject);
begin
{Need to address the transparency if the form gets resized. Also, note that Form1 scroll bars are set to VISIBLE/FALSE. I did that to save a little coding here....}
if Button1.Caption = 'Show Form' then
DoInvisible
else
DoVisible;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése