先日、Windows のタスクバーに小さいスタートメニューみたいなサブメニューを追加するランチャーアプリケーションを WPF で作りまして。
で、作っている最中に、そのものズバリの日本語情報がネット検索ですぐに見つからなかったケースがいくつかありましたので、それらを4~5回に渡って記事化して放流しておこうと思います。
ということで、初回はまず小ネタから。
WindowSyle に None を指定した場合のウィンドウのドラッグ移動で、一瞬「ん?」となった件について見ていきます。
読み込み中です。少々お待ち下さい
どんな現象か
WindowStyle に None を指定すると、当たり前ですがタイトルバーが消えてしまうので、ウィンドウのどこかを掴んでドラッグで移動できるようにしたいですよね。
まぁ、別に WindowStyle が None の場合だけでなく、クライアント領域の表示部分でマウスの左ボタンを押したままドラッグで移動したい場合であれば、別になんでもいいんですが。
とまれ、そんな時は「xxx.MouseLeftButtonDown += (o, e) => DragMove();」みたいに書くと簡単に実現できる筈なのですが、何故かドラッグしても反応しない場合があります。
という現象について、まずは上手く動かない例から見てみましょう。
サンプルコード その1
以下のコードは、Visual Studio の「新規作成」>「WPF アプリケーション」で新しいプロジェクトを作成し、自動的に生成される MainWindow を少し修正しただけのものです。
そのままコピペで上書きすれば動きますが、いちおうこちらで追加した部分に色をつけておきますね。
MainWindow.xaml
<Window x:Class="WpfSample1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfSamples"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="#FF00ABA9" WindowStyle="None" Padding="0" ResizeMode="NoResize">
<DockPanel>
<Grid x:Name="TitleBar" DockPanel.Dock="Top" Height="44">
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="ウィンドウ上部をドラッグして移動" Foreground="#FFF7D10C" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
</Grid>
<Grid x:Name="MainContent">
</Grid>
</DockPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfSample1
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// これはサンプルなので、簡易的に ESC キーで終了できるようにこんな書き方をしていますが、実際は RoutedUICommand と CommandBindings なんかを使って、もっときちんと書いてください
this.KeyUp += (o, e) => { if (e.Key == Key.Escape) { Close(); } };
// ウィンドウの上部をドラッグして移動できるように
TitleBar.MouseLeftButtonDown += (o, e) => DragMove();
}
}
}
問題点
上のコードを実行すると、ウィンドウの上の方をドラッグして移動できる筈なのに、何故かできません。
ですが、運が良いと移動できることがあります(ぇ
移動できる時と出来ない時で、何が違うのでしょう。
何度か試していると、文字の部分を掴んだ時はドラッグしてウィンドウを移動できることが分かります。
一方、TitleBar の Background は、初期状態のまま特に何も指定していないので Null ですが、その場合は完全な透過扱いになってしまうようです。
つまり、要は背景色を指定してあげれば良かったんですね。
ただ、上のサンプルみたいなアプリの場合、背景色はベースとなるコンテナで一括して指定して、子供は透明にしておきたいケースも多いでしょう。
そのような場合は、背景色に完全な透明を指定してあげます。
色が透明であっても、ブラシさえ指定されていれば問題ありません。
サンプルコード その2
修正したコードが、こちら。赤字の背景色を追加しただけです。
MainWindow.xaml
<Window x:Class="WpfSample1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfSamples"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="#FF00ABA9" WindowStyle="None" Padding="0" ResizeMode="NoResize">
<DockPanel>
<Grid x:Name="TitleBar" DockPanel.Dock="Top" Height="44" Background="Transparent">
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="ウィンドウ上部をドラッグして移動" Foreground="#FFF7D10C" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
</Grid>
<Grid x:Name="MainContent">
</Grid>
</DockPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfSample1
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// これはサンプルなので、簡易的に ESC キーで終了できるようにこんな書き方をしていますが、実際は RoutedUICommand と CommandBindings なんかを使って、もっときちんと書いてください
this.KeyUp += (o, e) => { if (e.Key == Key.Escape) { Close(); } };
// ウィンドウの上部をドラッグして移動できるように
TitleBar.MouseLeftButtonDown += (o, e) => DragMove();
}
}
}
これで、ウィンドウ上部をドラッグして移動できるようになりました。
めでたしめでたし。
ちなみに、Transparent を #00000000 にしても同様に動作します。
おわりに
ちょっと当たり前のこと過ぎて、果たして記事にする必要があったのか、書きながら疑問を抱かざるを得ませんでしたが、万が一、困っている方のお役に立ちましたら。
それから、「後で記事化すること」メモを紛失してしまったので、全5回じゃなくて3回くらいで終わるかも(笑)