連載
» 2015年10月07日 05時00分 UPDATE

.NET TIPS:WPF:ウィンドウを透明にするには?[C#/VB]

本稿では、WPFアプリでウィンドウ全体を透明にして表示する方法と、そのときに注意すべき事項を取り上げる。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Platform Development]
.NET TIPS
Insider.NET

 

「.NET TIPS」のインデックス

連載目次

対象:.NET 3.0以降


 Windows用のプログラムの中には、四角形以外のウィンドウのものがある。四隅とも角が丸くなっていたり、タイトルバーとウィンドウ本体が離れていたり、ウィンドウ全体が円形だったりと、いろいろだ。キャラクターの形をした不定形のものさえある。これらのプログラムはどうやって作っているのだろうか? その方法はいくつかあるが、WPFではウィンドウを透明にして自前でウィンドウを描画するのが簡単だ。

 そこで本稿では、WPFでウィンドウを透明/半透明にする方法を紹介しよう。なお、本稿のサンプルは「Windows desktop code samples:.NET Tips #1117」からダウンロードできる。

ウィンドウを透明/半透明にするには?

 XAMLコードの<Window>タグに、属性を三つ追加するだけである。実に簡単だ(次のコード)。

<Window x:Class=……省略……
        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent"
        >

ウィンドウを透明にする(XAML)
太字にした3行を追加するだけである。
Background属性にTransparent(=透明)ではなく半透明の色を指定すると、ウィンドウも半透明になる。半透明の色は、16進表記の色の先頭にアルファ値を追加して指定する。例えば、「#FF0000」(赤色)に対して、「#80FF0000」は半透明の赤色になる。ここで「80」がアルファ値である。アルファ値は「00」で透明、「FF」で不透明になる。
なお、Background属性の代わりにOpacity属性を指定してはいけない(後述)。

 AllowsTransparency属性にTrueを指定すれば、Background属性に指定した色の透明度が有効になる。注意しなければならないのは、AllowsTransparency属性をTrueに設定するときには、同時にWindowStyle属性をNoneに設定する必要があることだ。すなわち、タイトルバーやウィンドウ枠を持ったままでウィンドウを透明/半透明にすることはできないのである。

透明/半透明のウィンドウを移動/リサイズできるようにするには?

 上の方法でウィンドウを透明/半透明にすると、タイトルバーやウィンドウ枠がなくなってしまう。そのままではウィンドウを移動/リサイズできない。

 ウィンドウを移動できるようにするには、ウィンドウ上でマウスのボタンが押されたときのイベントハンドラーでウィンドウをドラッグさせればよい。何だか難しそうに思えるかもしれないが、次のコードのように1行追加するだけである。

public MainWindow()
{
  InitializeComponent();

  // ウィンドウをマウスのドラッグで移動できるようにする
  this.MouseLeftButtonDown += (sender, e) => { this.DragMove(); };
}

Public Sub New()
  ' この呼び出しはデザイナーで必要です。
  InitializeComponent()

  ' InitializeComponent() 呼び出しの後で初期化を追加します。

  ' ウィンドウをマウスのドラッグで移動できるようにする
  AddHandler Me.MouseLeftButtonDown, Sub(sender, e) Me.DragMove()
End Sub

ウィンドウをマウスで移動できるようにする(上:C#、下:VB)
ウィンドウのコンストラクターに太字の部分を追加した。
ここでは、プログラムの実行中に、このウィンドウの破棄/生成を繰り返さないものと仮定している。破棄/生成を繰り返す場合は、破棄されるときにイベントハンドラーを外すようにする。
なお、このコードでは、イベントハンドラーにセットするデリゲートとしてラムダ式*1を記述している。

*1 ラムダ式について詳しくは、次のMSDNのドキュメントを参照していただきたい。


 ウィンドウをリサイズ可能にする方法はいくつかあるが、簡単なのはウィンドウの右下にグリップハンドルを出すやり方だ(次のコードと画像)。

<Window x:Class=……省略……
        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent"
        ResizeMode="CanResizeWithGrip"
        >

ウィンドウをリサイズ可能にする(XAML)
太字にした1行を追加するだけである。

リサイズに使うグリップハンドル(XAMLエディター) リサイズに使うグリップハンドル(XAMLエディター)
上で示したXAMLコードで、ウィンドウの右下にグリップハンドルが表示される(赤丸内)。
なお、本稿で使っているのは無償のVisual Studio Express 2012 for Windows Desktopである。

Opacityプロパティと背景色のアルファ値の違い

 ウィンドウやUIコントロールを透明/半透明にするには、色指定のアルファ値を変える方法と、Opacityプロパティを設定する方法がある。前述したウィンドウの透明化ではアルファ値を使い(色のTransparentはアルファ値が0である)、Opacityプロパティは使わなかった。その違いは何だろうか?

 ひと言でいうなら、Opacityプロパティは子要素に伝播(でんぱ)するのである。例えば、親要素でOpacityプロパティに0.2(=かなり透明)をセットしたとする。そして、その子要素のOpacityプロパティに0.5(=半分の透明度)をセットしたとすると、実際のopacity(不透明度)は0.2に0.5を掛けた0.1(=ほとんど透明)になってしまうのだ。ウィンドウのOpacityプロパティを0(=透明)に設定すると、その中のUIコントロールも全て見えなくなってしまうのである。対して、アルファ値を背景色に設定した場合は、子要素に伝播しない。

  • Opacityプロパティ: 子要素も透明になってしまう
  • 背景色のアルファ値: 子要素には影響しない

 その違いを実際に試してみよう(次のコード)。

<Window x:Class=……省略……
        WindowStyle="None"
        AllowsTransparency="True"
        Background="Transparent"
        ResizeMode="CanResizeWithGrip"
        >
  <Grid>

    <!--
    このBorderコントロール(青色の四角形)には、Opacityプロパティを設定する。
    Opacityプロパティの値は、下のSliderコントロールで調整できる
    -->
    <Border Grid.RowSpan="2" Background="#00a2e8" 
            Opacity="{Binding ElementName=slider1, Path=Value}" >
      <!--
      このEllipseコントロール(楕円形)には透明度の指定はしていない。
      しかし、親要素にはOpacityプロパティが設定されているため、
      親要素と同じ透明度になる
      -->
      <Ellipse Fill="SkyBlue" Width="40" Height="30" Margin="16,32"
               HorizontalAlignment="Left" VerticalAlignment="Top" />
    </Border>

    <!-- このViewboxコントロールは、上のBorderコントロールの子要素ではない -->
    <Viewbox >
      <Image Source="penguin.png" Margin="16" Opacity="0.85" />
    </Viewbox>

    <!--
    このBorderコントロールも、上のBorderコントロールの子要素ではない
    このBorderコントロールには、Opacityプロパティは設定していないが、
    BackgroundプロパティはTransparentにしてある(アルファ値は0)
    -->
    <Border Background="Transparent" BorderBrush="#400000ff" BorderThickness="4"
            VerticalAlignment="Bottom"
            >
      <!-- 親要素の背景色がアルファ値0(=透明)であっても、子要素には影響しない -->
      <Slider x:Name="slider1" Background="#80a0a0a0"
              Margin="24,16" VerticalAlignment="Bottom"
              Value="0.5" Maximum="1.0" ……省略……
              />
    </Border>

    <TextBlock Text=".NET TIPS #1117" ……省略……
               />
    
    <!-- [×](閉じる)ボタン -->
    <Button Click="closeButton_Click" 
            Content="X" ……省略……
            />
  </Grid>
</Window>

Opacityとアルファ値の違いを確かめるコード(XAML)
Opacityプロパティと背景色にアルファ値を設定している部分を太字にした。
WPFのプロジェクトを作成し、「MainWindows.xaml」ファイルをこのように書き変える。また、ボタンのクリックイベントハンドラーには、ウィンドウを閉じるコードを記述する。詳しくは別途公開のサンプルコードをご覧いただきたい。

 このコードは、ウィンドウの背景色を透明にしてある。しかし、ウィンドウの子要素であり、ウィンドウの全面を覆う青色のBorderコントロール(System.Windows.Controls名前空間)には、ウィンドウの背景色は伝播しない。そのため、青色のBorderコントロールのOpacityプロパティを1.0にすると、不透明になる(次の画像)。

青色部分のOpacity=1.0(Windows 10) 青色部分のOpacity=1.0(Windows 10)
ウィンドウは透明になっていてタイトルバーも枠線もなくなっているが、ウィンドウの全面を覆う青色のBorderコントロールは不透明なので、タイトルバーと枠線がないだけのウィンドウに見える。
下部にあるスライダーコントロールの親要素は背景色を透明にしてあるのだが、子要素には影響していない(=スライダーコントロールが見えている)。
ウィンドウ左上の文字列のすぐ下にある楕円(だえん)形に注目しておいてほしい。これは、青色のBorderコントロールの子要素である。また、ウィンドウの右下隅には、リサイズのためのグリップが表示されている。

 ウィンドウ下部のSliderコントロール(System.Windows.Controls名前空間)を動かすと、青色のBorderコントロールのOpacityプロパティが変わる。ちょうど半分にした状態が次の画像だ。

青色部分のOpacity=0.5(Windows 10) 青色部分のOpacity=0.5(Windows 10)
ウィンドウの全面を覆う青色のBorderコントロールのOpacityプロパティが0.5の状態である。ウィンドウ自体は完全な透明になっているため、このように半透明となってウィンドウの下にある他のアプリが見える。
左上の楕円形を除くコントロールは、青色のBorderコントロールの子要素ではないため、その影響を受けていない。ただし、ペンギンのイラストの部分にはOpacity="0.85"と設定してあるので、わずかに下が透けて見えている(翼の白い部分が分かりやすい)。また、スライダーコントロールの背景色はアルファ値として16進で80(=ちょうど半透明)を指定してあるので、やはり下が透けて見えている(少々見づらいが、壁紙の濃い青色の部分と、左のアプリの灰色部分とが、スライダーコントロールの背景のところでも区別できるだろう)。

 青色のBorderコントロールを完全に透明にすると、次の画像のようになる。

青色部分のOpacity=0.0(Windows 10) 青色部分のOpacity=0.0(Windows 10)
ウィンドウの全面を覆う青色のBorderコントロールのOpacityプロパティを0.0(=完全な透明)にした状態である。ウィンドウを透明にしてあるので、青色のBorderコントロールとその子要素は透明になる。完全に透明になった部分は、マウスでクリックしてもイベントが発生しない(その下のアプリをクリックしたことになる)。
前の画像と見比べてみると、ウィンドウ左上の文字列の下にあった楕円形も完全に透明になっているのが分かる。楕円形のコントロールは青色のBorderコントロールの子要素なので、親要素のOpacityプロパティに影響されるのだ。
また、この状態でもウィンドウ右下のリサイズ用グリップは見えているので、リサイズ可能である。

まとめ

 WPFではウィンドウを透明/半透明にするのは簡単だ。マウスで移動/リサイズできるようにするのも難しくない。Opacityプロパティと背景色のアルファ値の違いには注意しよう。

利用可能バージョン:.NET Framework 3.0以降
カテゴリ:WPF/XAML 処理対象:Windowコントロール
使用ライブラリ:Windowコントロール(System.Windows名前空間)
関連TIPS:[WPF、Silverlight 2]角を丸くして画像を表示するには?[XAML]


「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。