启用VCL样式时如何制作透明表单?

发布于 2024-12-18 15:58:50 字数 1010 浏览 2 评论 0原文

我使用以下代码使表单透明,但是当应用程序启用了 VCL 样式时,表单将使用 VCL 样式的背景颜色进行绘制,而不是透明。

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure CreateParams(var Params:TCreateParams); override;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
 //Params.ExStyle := Params.ExStyle or WS_EX_LAYERED;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Brush.Style:=bsClear;
 BorderStyle:=bsNone;
 //SetLayeredWindowAttributes(Handle, 0, 230, $00000002);
end;

仅供参考,如果 vcl 样式设置为 Windows,则代码可以正常工作。

是否存在另一种使表单透明来解决此问题的方法?

I'm using the following code to make a form transparent, but when the application has a VCL style enabled the form is paint with the background color of the VCL style instead of be transparent.

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure CreateParams(var Params:TCreateParams); override;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
 //Params.ExStyle := Params.ExStyle or WS_EX_LAYERED;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Brush.Style:=bsClear;
 BorderStyle:=bsNone;
 //SetLayeredWindowAttributes(Handle, 0, 230, $00000002);
end;

FYI The code works fine if the the vcl style is set to Windows.

Exist another way to make a form transparent to workaround this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

老子叫无熙 2024-12-25 15:58:50

对我来说这似乎是一个错误。 VCL 样式使用样式钩子来拦截绘制方法以及与这些操作相关的 Windows 消息,因此在这种情况下,您必须将注意力集中在 PaintBackground 方法上。 a href="http://docwiki.embarcadero.com/VCL/en/Forms.TFormStyleHook">TFormStyleHook 类位于 Vcl.Forms 中,从这里你创建一个新的样式钩子类(源自TFormStyleHook),重写PaintBackground方法,修复代码,最后在使用它之前调用RegisterStyleHook方法来注册New < em>样式钩子。检查这篇文章 修复 TPageControl 和 TTabControl 组件中的 VCL 样式错误 查看示例。

更新
检查此示例

unit Unit138;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm138 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure CreateParams(var Params:TCreateParams); override;
  public
  end;


var
  Form138: TForm138;

implementation

 Uses
   Vcl.Themes,
   Vcl.Styles,
   uPatch;

{$R *.dfm}

procedure TForm138.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;

procedure TForm138.FormCreate(Sender: TObject);
begin
 Brush.Style:=bsClear;
 BorderStyle:=bsNone;
end;

initialization
 TStyleManager.Engine.UnRegisterStyleHook(TForm, TFormStyleHook);//unregister the original style hook
 TStyleManager.Engine.RegisterStyleHook(TForm, TMyStyleHookClass); //register the new style hook

end.

新样式 Hook 类

unit uPatch;

interface

uses
  Vcl.Graphics,
  Vcl.Forms;

type
  TMyStyleHookClass= class(TFormStyleHook)
  protected
   procedure PaintBackground(Canvas: TCanvas); override;
  end;

implementation

uses
  Winapi.Windows,
  System.Types,
  Vcl.Themes;


procedure TMyStyleHookClass.PaintBackground(Canvas: TCanvas);
{This is only a basic sample for fix a specific scenario}
var
  Details: TThemedElementDetails;
  R: TRect;
begin
  if StyleServices.Available then
  begin
    if (GetWindowLong(Form.Handle,GWL_EXSTYLE) AND WS_EX_TRANSPARENT) = WS_EX_TRANSPARENT  then
    if Form.Brush.Style = bsClear then Exit;

    Details.Element := teWindow;
    Details.Part := 0;
    R := Rect(0, 0, Control.ClientWidth, Control.ClientHeight);
    StyleServices.DrawElement(Canvas.Handle, Details, R);
  end;
end;

end.

It seems like a bug to me. The VCL Styles use Style hooks to intercept the paint methods and the Windows messages related to these operations, So in this case you must focus your atention in the PaintBackground method of the TFormStyleHook class located in the Vcl.Forms, from here you create a new style hook class (which descends from TFormStyleHook), override the PaintBackground method, fix the code and finally before to use it call the RegisterStyleHook method to register the New style hook. check this article Fixing a VCL Style bug in the TPageControl and TTabControl components to see an example.

UPDATE
Check this sample

unit Unit138;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm138 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure CreateParams(var Params:TCreateParams); override;
  public
  end;


var
  Form138: TForm138;

implementation

 Uses
   Vcl.Themes,
   Vcl.Styles,
   uPatch;

{$R *.dfm}

procedure TForm138.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;

procedure TForm138.FormCreate(Sender: TObject);
begin
 Brush.Style:=bsClear;
 BorderStyle:=bsNone;
end;

initialization
 TStyleManager.Engine.UnRegisterStyleHook(TForm, TFormStyleHook);//unregister the original style hook
 TStyleManager.Engine.RegisterStyleHook(TForm, TMyStyleHookClass); //register the new style hook

end.

The New Style Hook Class

unit uPatch;

interface

uses
  Vcl.Graphics,
  Vcl.Forms;

type
  TMyStyleHookClass= class(TFormStyleHook)
  protected
   procedure PaintBackground(Canvas: TCanvas); override;
  end;

implementation

uses
  Winapi.Windows,
  System.Types,
  Vcl.Themes;


procedure TMyStyleHookClass.PaintBackground(Canvas: TCanvas);
{This is only a basic sample for fix a specific scenario}
var
  Details: TThemedElementDetails;
  R: TRect;
begin
  if StyleServices.Available then
  begin
    if (GetWindowLong(Form.Handle,GWL_EXSTYLE) AND WS_EX_TRANSPARENT) = WS_EX_TRANSPARENT  then
    if Form.Brush.Style = bsClear then Exit;

    Details.Element := teWindow;
    Details.Part := 0;
    R := Rect(0, 0, Control.ClientWidth, Control.ClientHeight);
    StyleServices.DrawElement(Canvas.Handle, Details, R);
  end;
end;

end.
淡淡的优雅 2024-12-25 15:58:50

另外,您是否尝试过使用 TransparentColorTranparentColorValue 属性而不是在 CreateParams() 中操作窗口样式?

On a separate note, have you tried using the TransparentColor and TranparentColorValue properties instead of manipulating the window styles in CreateParams()?

各空 2024-12-25 15:58:50

我使用 OverridePaintNC := False 来防止在 NC 区域上绘制样式。还有 OverrideEraseBkgnd 。也许这有帮助。

I use OverridePaintNC := False to prevent draw Styles on NC area. And there is OverrideEraseBkgnd too. Maybe this help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文