9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Delphi] 半透明でクリックを透過するウィンドウの作り方

Last updated at Posted at 2023-08-21

はじめに

RADStudio Users Group に「Delphiでマウス・キーボード操作をスルーする方法はありますか?」という質問がありました。
そこで、この記事では VCL / FireMonkey で実現する方法を紹介します。

VCL の場合

VCL の場合、2つのプロパティとCreateWindowEx の dwExStyle に値を設定してやるだけで簡単に実現できます。

プロパティの設定

VCL の TForm には AlphaBlend というプロパティと AlphaBrendValue というプロパティがあります。
AlphaBlend プロパティを True にすると Form が Layered Window という特殊なウィンドウになります。
Layered Window は半透明にしたり背景を透過したりできます。

Layered Window の半透明の度合いは AlphaBlendValue で制御できます。
AlphaBlendValue に 0 を指定すると完全に透明、255 で完全に不透明になります。

下はこのプロパティの値を変更した例です。
値によって透け具合が異なっています。

また、必要であれば FormStyle プロパティを fsStayOnTop にして最前面ウィンドウにします。

CreateWindowEx のカスタマイズ

CreateWindowEx のパラメータは VCL の場合簡単に変更できます。
VCL の TForm には CreateParams というメソッドがあるためです。
このメソッドは CreateWindowEx を呼ぶ前にパラメータを変更する機会を提供してくれます。

そこで、このメソッドを override して ExStyle を変更します。

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

var
  Form1: TForm1;

implementation

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;

  Params.ExStyle :=
    Params.ExStyle
    or WS_EX_TRANSPARENT // 透明化
    or WS_EX_NOACTIVATE; // アクティブにならない
end;

肝は WS_EX_TRANSPARENT と WS_EX_NOACTIVATE です。
Layered Window の場合、この2つを指定する事で、マウスクリックを透過します。
(Layered Window ではない場合は透過しません)

完成

上記の CreateParams の変更と AlphaBlend / AlphaBlendValue を設定すると完成です。
こんな風にクリックが透過します

コード全文 (CreateParams があるだけ…)
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;

  Params.ExStyle :=
    Params.ExStyle
    or WS_EX_TRANSPARENT // 透明化
    or WS_EX_NOACTIVATE; // アクティブにならない
end;

end.

FireMonkey の場合

これはもう力づくです。
FormCreate で必要な Win32 API を呼んでやります。
基本は VCL と同じです。

ちなみに FireMonkey の TForm には Transparency というプロパティがあるのですが、これはフォームの背景色(Fill.Color)を透明にしてしまうので使えません。
(VCL の TransparentColor と同等)

uses
  Winapi.Windows
  , FMX.Platform.Win
  ;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Window Handle の取得
  var HWnd := FormToHWND(Self);

  // ExStyle の取得
  var ExStyle := GetWindowLong(HWnd, GWL_EXSTYLE);

  // ExStyle に追加
  ExStyle :=
    ExStyle
    or WS_EX_LAYERED     // Layered Window
    or WS_EX_TRANSPARENT // 透明化
    or WS_EX_NOACTIVATE; // アクティブにならない

  // ExStyle を設定
  SetWindowLong(HWnd, GWL_EXSTYLE, ExStyle);

  // Layered Window の透明度を指定
  SetLayeredWindowAttributes(HWnd, 0, 128, LWA_ALPHA);

  // 必要であれば Window を最前面に
  SetWindowPos(
    HWnd,
    HWND_TOPMOST,
    0,
    0,
    0,
    0,
    SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
end;

ということで無事 FireMonkey でもクリック透過するようになりました。

さいごに

ガジェット系のアプリを作る時にたまに使うテクニックです。
Windows オンリーのアプリになるのでわざわざ FireMonkey で作る必要は無いですね…!

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?