Bạn luôn có thể tạo ra hình thức vào mẫu. Nó không phải là giải pháp hạnh phúc nhất, nhưng nó hoạt động.Tôi tin rằng cách tốt nhất để giải quyết vấn đề này sẽ là bằng cách sử dụng GDI + hoặc D2D, nhưng không may, tôi không thể tìm ra, vì vậy tôi đã đi với "hình thức vào mẫu" cách tiếp cận:
dạng Layered:
unit uLayeredForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, System.Types,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Imaging.PngImage;
type
TfrmLayered = class(TForm)
procedure FormActivate(Sender: TObject);
private
FParentForm: TForm;
procedure SetAlphaBackground(const AResourceName: String);
public
constructor Create(AOwner: TComponent; const ABitmapResourceName: String); reintroduce;
procedure UpdatePosition;
end;
var
frmLayered: TfrmLayered;
implementation
{$R *.dfm}
constructor TfrmLayered.Create(AOwner: TComponent; const ABitmapResourceName: String);
begin
inherited Create(AOwner);
FParentForm := AOwner as TForm;
SetAlphaBackground(ABitmapResourceName);
end;
procedure TfrmLayered.FormActivate(Sender: TObject);
begin
if (Active) and (FParentForm.Visible) and (Assigned(FParentForm)) then
FParentForm.SetFocus;
end;
procedure TfrmLayered.UpdatePosition;
begin
if Assigned(FParentForm) then
begin
Left := FParentForm.Left - (ClientWidth - FParentForm.ClientWidth) div 2 - 1;
Top := FParentForm.Top - (ClientHeight - FParentForm.ClientHeight) div 2 - 1;
end;
end;
procedure TfrmLayered.SetAlphaBackground(const AResourceName: String);
var
blend_func: TBlendFunction;
imgpos : TPoint;
imgsize : TSize;
exStyle : DWORD;
png : TPngImage;
bmp : TBitmap;
begin
// enable window layering
exStyle := GetWindowLongA(Handle, GWL_EXSTYLE);
if ((exStyle and WS_EX_LAYERED) = 0) then
SetWindowLong(Handle, GWL_EXSTYLE, exStyle or WS_EX_LAYERED);
png := TPngImage.Create;
try
png.LoadFromResourceName(HInstance, AResourceName);
bmp := TBitmap.Create;
try
bmp.Assign(png);
// resize the form
ClientWidth := bmp.Width;
ClientHeight := bmp.Height;
// position image on form
imgpos := Point(0, 0);
imgsize.cx := bmp.Width;
imgsize.cy := bmp.Height;
// setup alpha blending parameters
blend_func.BlendOp := AC_SRC_OVER;
blend_func.BlendFlags := 0;
blend_func.SourceConstantAlpha := 255;
blend_func.AlphaFormat := AC_SRC_ALPHA;
UpdateLayeredWindow(Handle, 0, nil, @imgsize, bmp.Canvas.Handle, @imgpos, 0, @blend_func, ULW_ALPHA);
finally
bmp.Free;
end;
finally
png.Free;
end;
end;
end.
hình thức chính:
unit uMainForm;
interface
uses
uLayeredForm,
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TfrmMain = class(TForm)
imgClose: TImage;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure FormShow(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormHide(Sender: TObject);
procedure imgCloseClick(Sender: TObject);
private
FLayeredForm: TfrmLayered;
protected
procedure WMMove(var AMessage: TMessage); message WM_MOVE;
public
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
uses
uCommon, Vcl.Themes, Vcl.Styles.FormStyleHooks;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
{$IFDEF DEBUG} ReportMemoryLeaksOnShutdown := TRUE; {$ENDIF}
FLayeredForm := TfrmLayered.Create(self, 'MainBackground');
FLayeredForm.Visible := TRUE;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
FLayeredForm.Free;
end;
procedure TfrmMain.FormHide(Sender: TObject);
begin
FLayeredForm.Hide;
end;
procedure TfrmMain.WMMove(var AMessage: TMessage);
begin
if Assigned(FLayeredForm) then
FLayeredForm.UpdatePosition;
inherited;
end;
procedure TfrmMain.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FormMove(self, Button, Shift, X, Y);
end;
procedure TfrmMain.FormShow(Sender: TObject);
begin
if Assigned(FLayeredForm) then
begin
FLayeredForm.Show;
FLayeredForm.UpdatePosition;
end;
end;
procedure TfrmMain.imgCloseClick(Sender: TObject);
begin
Close;
end;
initialization
TStyleManager.Engine.RegisterStyleHook(TfrmMain, TFormStyleHookBackground);
TFormStyleHookBackground.BackGroundSettings.Color := clBlack;
TFormStyleHookBackground.BackGroundSettings.Enabled := TRUE;
end.
như bạn thấy, bạn sẽ phải làm một chút công việc thủ công để thực hiện hai hình thức cư xử như một, nhưng mã này sẽ giúp bạn bắt đầu.
Vì tôi cần biểu mẫu có đường viền tròn mượt mà, ảnh chụp màn hình sau đây là những gì tôi nhận được dưới dạng kết quả cuối cùng. Tôi màu phong độ tốt nhất trong màu xám, đặc biệt cho bài này, cho phân biệt dễ dàng hơn giữa nó và hình thức đen lớp:
Bạn có thể thấy rõ sự khác biệt giữa biên giới dưới hình thức màu xám bí danh (do SetWindowRgn() và CreateRoundRectRgn() API) và đường viền biểu mẫu màu đen chống răng cưa.
Chỉ cần một phụ trang. Tôi không làm thế nào để đạt được điều này, nhưng nếu bạn sẽ tạo ra một hình bán màu trong suốt mà không có bất kỳ hình dạng đặc biệt nào, bạn có thể chỉ cần đặt ['AlphaBlend'] (http://docwiki.embarcadero.com/Libraries /XE2/en/Vcl.Forms.TForm.AlphaBlend) thành True và ['AlphaBlendValue'] (http://docwiki.embarcadero.com/Libraries/XE2/en/Vcl.Forms.TForm.AlphaBlendValue) đến alpha mong muốn giá trị ;-) Nhưng đó là một câu hỏi hay trong quan điểm của tôi; +1. – TLama
Tôi nghĩ câu trả lời của bạn là ở đoạn thứ 4 và thứ 5 của [Layered Windows] (http://msdn.microsoft.com/en-us/library/ms632599%28v=vs.85%29.aspx#layered). Về cơ bản, nếu bạn muốn tiếp tục sử dụng mã vẽ đã có của bạn (VCL), hãy sử dụng 'SetLayeredWindowAttributes'. Nếu bạn sẽ tự mình vẽ, hãy sử dụng 'UpdateLayeredWindow'. –
@Sertac, giống như thuộc tính 'AlphaBlend' và' AlphaBlendValue' ;-) – TLama