Delphiで作る透明アナログ時計ガジェット|Windowsで前面表示
Delphiを使って、透明背景のアナログ時計ガジェットを作ってみませんか?
このページでは、VCLアプリケーションとして軽快に動作し、Windows上で前面表示できる時計ウィジェットの作成手順を、サンプルコードとともに詳しく解説します。
TTimerによる描画処理や、SetWindowPosを活用したウィンドウスタイルの工夫も紹介します。
Delphiを起動して新規作成を行う
Delphiを起動し、ファイル→新規作成→Windows VCLアプリケーションをクリックする。
ソースコードの記述
TTimerをフォームにドラッグドロップします。
ここで一旦「すべて保存」をクリックしてプロジェクトとユニットを保存します。
F12キーを押して「コード」モードに切り替え以下ソースコードを記述します。
F12キーを押して「デザイン」モードに切り替え、左下ペイン「オブジェクト インスペクタ」の「イベント」タグをクリックします。
イベント「Form1.OnCreate」 に 「FormCreate」
イベント「Form1.OnMouseDown」 に 「FormMouseDown」
イベント「Timer1.OnTimer」 に 「Timer1Timer」
を設定します。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
procedure draw_clock;
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 and not WS_EX_APPWINDOW;
Params.WndParent := Application.Handle;
end;
procedure TForm1.draw_clock;
var wh:integer;
h,m,s,ms:word;
c:TPoint;
rh,rm,rs:integer;
i:integer;
begin
//現在時刻を取り出す
DecodeTime(GetTime(),h,m,s,ms);
wh:=self.Width;//幅も高さも同じ
rh:=wh div 2 * 6 div 10;//短針長さ
rm:=wh div 2 * 7 div 10;//長針長さ
rs:=wh div 2 * 8 div 10;//秒針長さ
c.X:=wh div 2;
c.Y:=wh div 2;
//フォーム内部を塗りつぶす
self.Canvas.Brush.Style:=bsSolid;
self.Canvas.Brush.Color:=Self.Color;
self.Canvas.Pen.Style:=psClear;
self.Canvas.FillRect(Rect(0,0,self.ClientWidth,self.ClientHeight));
//円を描画する
self.Canvas.Brush.Style:=bsClear;
self.Canvas.Pen.Style:=psSolid;
self.Canvas.Pen.Width:=4;
self.Canvas.Pen.Color:=RGB($80,$80,$80);
self.Canvas.Ellipse(
wh*2 div 100, wh*2 div 100,
wh*98 div 100, wh*98 div 100
);
//目盛りの描画
for i := 0 to 11 do
begin
self.Canvas.MoveTo(
round(c.X+cos(i*30*pi/180)*wh/2*96/100),
round(c.Y+sin(i*30*pi/180)*wh/2*96/100)
);
self.Canvas.LineTo(
round(c.X+cos(i*30*pi/180)*wh/2*86/100),
round(c.Y+sin(i*30*pi/180)*wh/2*86/100)
);
end;
//短針を描く
self.Canvas.Pen.Color:=RGB($60,$60,$FF);
self.Canvas.Pen.Width:=12;
self.Canvas.MoveTo(c.X,c.Y);
self.Canvas.LineTo(
round(c.X+rh*cos((h+m/60)/6*pi()-pi()/2)),
round(c.Y+rh*sin((h+m/60)/6*pi()-pi()/2))
);
//長針を描く
self.Canvas.Pen.Color:=RGB($80,$80,$FF);
self.Canvas.Pen.Width:=6;
self.Canvas.MoveTo(c.X,c.Y);
self.Canvas.LineTo(
round(c.X+rm*cos((m+s/60)/30*pi()-pi()/2)),
round(c.Y+rm*sin((m+s/60)/30*pi()-pi()/2))
);
//秒針を描く
self.Canvas.Pen.Color:=RGB($90,$90,$FF);
self.Canvas.Pen.Width:=3;
self.Canvas.MoveTo(c.X,c.Y);
self.Canvas.LineTo(
round(c.X+rs*cos((s+ms/1000)/30*pi()-pi()/2)),
round(c.Y+rs*sin((s+ms/1000)/30*pi()-pi()/2))
);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
self.TransparentColor:=true;
self.TransparentColorValue:=Self.Color;
self.BorderStyle:=bsNone;
self.ClientWidth:=200;
self.ClientHeight:=self.ClientWidth;
draw_clock;
//100ミリ秒ごとに描画
timer1.Interval:=100;
timer1.Enabled:=True;
//常に最前面にウィンドウ位置を設定する
SetWindowPos(self.Handle,HWND_TOPMOST,0,0,0,0,
SWP_NOMOVE+SWP_NOSIZE
);
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button=mbLeft then
begin
//短針や長針や秒針等を左ボタンドラッグ時に移動させる
ReleaseCapture;
SendMessage(self.Handle, WM_SYSCOMMAND, SC_MOVE or 2, MakeLong(X, Y));
end
else if Button=mbRight then
begin
//短針や長針や秒針等を右ボタンクリック時はアプリ終了
Application.Terminate;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
draw_clock;
end;
end.
実行する
実行すると、透明なウィンドウ内でアナログ時計が常に前面に表示されます。タスクバーには表示されません。短針や長針等をマウス左ボタンドラッグで、表示位置(ウィンドウ位置)を移動できます。
短針や長針等をマウス右ボタンクリックでアプリケーションが終了します。
