ブログでアプリケーションの実行画面の説明をする時、GIF アニメーションをよく使います。
パソコンの画面を撮影して GIF アニメーションを簡単に保存できる無料ツールの「ScreenToGif」という神アプリをよく利用しています。
このアプリの画面中央部分は透明になっていて、背面が見えるようになっています。この透明な部分が録画されるという仕組みになっています。画面のサイズも自由自在に調整可能で、好きなサイズで録画ができるので使い勝手が良く重宝しています。
このアプリのように「Windowの背景の一部を透明にするのってどうやってするんだろう?」という好奇心から、ScreenToGif と同じような画面構成のアプリを WPF で作成してみました。
この記事では、ウィンドウの特定の部分の背景を透過させる方法について記述しています。ぜひ参考にしてみて下さい。
ウィンドウの一部背景を透明にする
まず、WPF には特定の部分だけを透過するプロパティはありませんが、ウィンドウの全体を透明にするプロパティは存在します。
そこで、透明にしたいウィンドウの背景以外は何かしら色が付いた Grid などで隙間を埋めるという方法で実現しようと思います。
イメージとして次のような感じです。
色付きの Grid はウィンドウの左端・右端・下端にそれぞれ配置します。
背景を透明にする
WPF で Window の背景を透過するには3つのプロパティを次のように設定をします。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] Background プロパティを”Transparent”にする。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] WindowStyle プロパティを”None”にする。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] AllowsTransparency プロパティを”True”にする。
プロパティの説明は次の通りです。こちらの公式サイトを参照しています。
プロパティ | 説明 |
Background | コントロールの背景を表すブラシを取得または設定します。 |
WindowStyle | ウィンドウの枠線のスタイルを取得または設定します。 |
AllowsTransparency | ウィンドウのクライアント領域が透過性をサポートするかどうかを示す値を取得または設定します。 |
Window の背景を透明にするには、AllowsTransparency プロパティを”True”にして、透明を許可する設定に変更する必要があります。
また、AllowsTransparency プロパティを”True”にする場合は、WindowStyle プロパティを”None”にしなければなりません。
WindowStyle プロパティを”None”にするということは、タイトルバーや枠線、最大化・最小化ボタン、閉じるボタンが存在しないウィンドウになります。つまりタイトルバーや枠線、ボタンを自作してウィンドウへ配置する必要があります。
ということで先ほど示したイメージを修正します。
色付きの Grid を上端に配置し、ラベル(タイトル)とボタンを追加しました。それとウィンドウの周りを囲む枠線も追加しました。
タイトルバーや枠線、ボタンを配置する
Window の枠線を Border コントロールで作ります。
続いて Border の子要素として Grid を配置して、Label コントロールと Button コントロールをいい感じに調整してタイトルバーを作ります。
<Window
x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowTransparent"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="450"
Height="350"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None"
mc:Ignorable="d">
<Border BorderBrush="#c6c6c6" BorderThickness="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="#ffffff">
<Label
Margin="5,0,0,0"
Content="Sample Window"
FontSize="14" />
<Button
Name="btnClose"
Width="32"
Margin="0,0,5,0"
Padding="0,-5,0,0"
HorizontalAlignment="Right"
Background="Transparent"
BorderThickness="0"
Content="×"
FontSize="26" />
</Grid>
</Grid>
</Border>
</Window>
window.xaml.cs のコンストラクタで、左クリックのイベントハンドラに DragMove 関数を記述します。これでドラッグ&ドロップした時に Window を動かすことができるようになります。
また、ボタンをクリックした時に Window が閉じるように、ボタンのクリックイベントに Close 関数を記述します。
public MainWindow()
{
InitializeComponent();
// ドラッグ&ドロップで移動する処理
MouseLeftButtonDown += (s, e) => { DragMove(); };
// ウィンドウを閉じる処理
btnClose.Click += (s, e) => { Close(); };
}
この状態で実行すると次の画面になります。
ウィンドウの背景が透明になっていることが分かるように、アプリの背面にメモ帳を配置しています。それっぽい画面にはなっていますが、更に仕上げていきます。
枠を配置する
今のままだとウィンドウの枠線が細く、アプリの境界が分かりづらいので左右と下に枠(Grid)を配置します。
HorizontalAlignment プロパティ、Width プロパティなどで配置する位置や幅を調整します。
<Window
x:Class="WindowTransparent.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowTransparent"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="450"
Height="350"
AllowsTransparency="True"
Background="Transparent"
WindowStyle="None"
mc:Ignorable="d">
<Border BorderBrush="#c6c6c6" BorderThickness="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Background="#ffffff">
<Label
Margin="5,0,0,0"
Content="Sample Window"
FontSize="14" />
<Button
Name="btnClose"
Width="32"
Margin="0,0,5,0"
Padding="0,-5,0,0"
HorizontalAlignment="Right"
Background="Transparent"
BorderThickness="0"
Content="×"
FontSize="26" />
</Grid>
<Grid Grid.Row="1">
<Border
Margin="5,0,5,32"
BorderBrush="#c6c6c6"
BorderThickness="1" />
<Grid
Width="5"
HorizontalAlignment="Left"
Background="#ffffff" />
<Grid
Width="5"
HorizontalAlignment="Right"
Background="#ffffff" />
<Grid
Height="32"
VerticalAlignment="Bottom"
Background="#ffffff">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
Width="50"
Background="Transparent"
BorderThickness="0"
Content="設定" />
<Separator
Margin="5,2,5,2"
BorderBrush="#c6c6c6"
BorderThickness="0.5"
Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<Button
Width="50"
Margin="0,0,5,0"
Background="Transparent"
BorderThickness="0"
Content="録画" />
</StackPanel>
</Grid>
</Grid>
</Grid>
</Border>
</Window>
ここまで記述して実行すると次の画面になります。
最初にイメージしていた状態にまでUI画面を仕上げることが出来ました。
リサイズを設定する
アプリのサイズを変更できるように、window.xaml で ResizaMode プロパティの設定を行います。ResizaMode プロパティは”CanResizeWithGrip”を指定すれば、グリップを使ったリサイズが可能になります。
ResizeMode="CanResizeWithGrip"
最終的には次の画面になります。
アプリの画面右下にサイズを変更するグリップが表示されます。このグリップをドラッグ&ドロップすることで任意のサイズに調整することができます。
まとめ
WPFではウィンドウの特定の部分の背景を透明にする為に、3つのプロパティの設定を行い、背景を透明にしない箇所には色付きのGridを配置しました。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] Background プロパティを”Transparent”にする。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] WindowStyle プロパティを”None”にする。
[jin_icon_checkcircle color=”#e9546b” size=”14px”] AllowsTransparency プロパティを”True”にする。
ウィンドウ全体を透過した時に、タイトルバーや枠線などが消えてしまうデメリットはあるものの、やりたいことは実現することができました。
今回作成したアプリにスクリーンショット機能を追加した記事を作成しました。スクショした画面を画像ファイルとして自動で保存することもできるので、興味がある方は確認してみて下さい。
以上、最後まで読んで頂きありがとうございました。