■はじめに
キーワード:画像表示, 複数画面表示, ファイル選択ダイアログ, 子画面全終了, マウスホイール
[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。
■開発環境
- Windows 10
- Visual Studio Community 2019 (Version 16.4.2)
- .NET Framework 4.5.2 / .NET Core 3.1
■作ってみる
◇プロジェクトの作成
WPFアプリの.NET Frameworkまたは.NET Coreを選択してプロジェクトを作成します。
この記事では.NET Frameworkを選択しました。
※.NET Core版でも動作することは確認済みです。
◇メイン画面のレイアウト作成
メイン画面のレイアウト用コントロールをGridからViewboxに変更します。
StackPanel, Buttonを配置してプロパティやスタイルの設定をします。
<Windowx:Class="ImageView.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:ImageView"mc:Ignorable="d"Title="画像ビューア"Height="150"Width="450"MinHeight="100"MinWidth="150"ResizeMode="CanResizeWithGrip"><Window.Resources><!-- ボタンの既定スタイル --><StyleTargetType="Button"><SetterProperty="Margin"Value="5"/><SetterProperty="Padding"Value="5"/></Style></Window.Resources><Viewbox><StackPanelOrientation="Horizontal"><ButtonContent="画像を開く"IsDefault="True"/><ButtonContent="画像をすべて閉じる"/></StackPanel></Viewbox></Window>◇画像表示用画面のレイアウト作成
ソリューションエクスプローラーでプロジェクトを右クリックし、ウィンドウを追加します。
名前はImageWindowにします。
Imageコントロールやボタン等を配置、プロパティ設定をします。+, -ボタンはリピートボタンを使います。ボタンを押し続けている間、Clickイベントが連続して発生します。RepeatButtonはツールボックスに無いのでタグを手打ちしてください。
<Windowx:Class="ImageView.ImageWindow"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:ImageView"mc:Ignorable="d"Title="ImageWindow"Height="220"Width="200"MinHeight="100"MinWidth="100"ResizeMode="CanResizeWithGrip"><Window.Resources><!-- リピートボタンの既定スタイル --><StyleTargetType="RepeatButton"><SetterProperty="Margin"Value="2"/><SetterProperty="Width"Value="20"/></Style></Window.Resources><Grid><Grid.RowDefinitions><RowDefinitionHeight="Auto"/><RowDefinition/></Grid.RowDefinitions><StackPanelOrientation="Horizontal"><RepeatButtonx:Name="plusButton"Content="+"/><RepeatButtonx:Name="minusButton"Content="-"/><Buttonx:Name="closeButton"Content="閉じる"Margin="2"IsCancel="True"/></StackPanel><Imagex:Name="img"Grid.Row="1"/></Grid></Window>◇画像表示ロジック作成
画像を指定して表示する処理、各ボタンクリック、ウィンドウのマウスホイール回転、ウィンドウのマウス左ボタンダウン処理を書きます。
マウスホイール回転時に拡大または縮小するようにします。
左ボタンダウン時の処理は、タイトルバーだけでなく画像部分をドラッグしてもウィンドウを移動できるようにします。
usingSystem;usingSystem.Windows;usingSystem.Windows.Input;usingSystem.Windows.Media.Imaging;namespaceImageView{/// <summary>/// ImageWindow.xaml の相互作用ロジック/// </summary>publicpartialclassImageWindow:Window{/// <summary>/// コンストラクタ/// </summary>publicImageWindow(){InitializeComponent();}/// <summary>/// 画像設定処理(他の画面からこれを呼ぶ)/// </summary>/// <param name="filePath">画像ファイルパス</param>/// <returns>読み込み成功時true</returns>publicboolSetImage(stringfilePath){// パスが空if(string.IsNullOrEmpty(filePath)){returnfalse;}varbmp=newBitmapImage();bmp.BeginInit();bmp.UriSource=newUri(filePath);bmp.EndInit();// 画像設定img.Source=bmp;// タイトルバーにファイル名設定this.Title=System.IO.Path.GetFileName(filePath);returntrue;}/// <summary>/// ウィンドウサイズ拡大・縮小/// </summary>/// <param name="isZoom">true:拡大, false:縮小</param>privatevoidChangeWindowSize(boolisZoom){intplusMinus=isZoom?1:-1;// ウィンドウサイズを10%単位で変更this.Height+=(this.Height*0.1)*plusMinus;this.Width+=(this.Width*0.1)*plusMinus;// ウィンドウサイズが小さくなりすぎた場合、最小値に戻すif(this.Height<this.MinHeight||this.Width<this.MinWidth){this.Height=this.MinHeight;this.Width=this.MinWidth;}}/// <summary>/// 拡大ボタンクリック時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidplusButton_Click(objectsender,RoutedEventArgse){// ウィンドウサイズ拡大ChangeWindowSize(true);}/// <summary>/// 縮小ボタンクリック時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidminusButton_Click(objectsender,RoutedEventArgse){// ウィンドウサイズ縮小ChangeWindowSize(false);}/// <summary>/// 閉じるボタンクリック時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidcloseButton_Click(objectsender,RoutedEventArgse){this.Close();}/// <summary>/// マウスホイール回転時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidWindow_MouseWheel(objectsender,MouseWheelEventArgse){// ウィンドウサイズ拡大・縮小ChangeWindowSize(e.Delta>0);}/// <summary>/// マウス左ボタンダウン時の処理/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidWindow_MouseLeftButtonDown(objectsender,MouseButtonEventArgse){// タイトルバー以外でもウィンドウ移動を可能にするDragMove();}}}最終的にXamlは以下のようになりました。
<Windowx:Class="ImageView.ImageWindow"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:ImageView"mc:Ignorable="d"Title="ImageWindow"Height="220"Width="200"MinHeight="100"MinWidth="100"ResizeMode="CanResizeWithGrip"MouseWheel="Window_MouseWheel"MouseLeftButtonDown="Window_MouseLeftButtonDown"><Window.Resources><!-- リピートボタンの既定スタイル --><StyleTargetType="RepeatButton"><SetterProperty="Margin"Value="2"/><SetterProperty="Width"Value="20"/></Style></Window.Resources><Grid><Grid.RowDefinitions><RowDefinitionHeight="Auto"/><RowDefinition/></Grid.RowDefinitions><StackPanelOrientation="Horizontal"><RepeatButtonx:Name="plusButton"Content="+"Click="plusButton_Click"/><RepeatButtonx:Name="minusButton"Content="-"Click="minusButton_Click"/><Buttonx:Name="closeButton"Content="閉じる"Margin="2"IsCancel="True"Click="closeButton_Click"/></StackPanel><Imagex:Name="img"Grid.Row="1"/></Grid></Window>◇メイン画面ロジック作成
画像表示用画面を使って画像表示する処理、画像表示用画面を閉じる処理を書きます。
usingSystem;usingSystem.Windows;namespaceImageView{/// <summary>/// MainWindow.xaml の相互作用ロジック/// </summary>publicpartialclassMainWindow:Window{/// <summary>/// コンストラクタ/// </summary>publicMainWindow(){InitializeComponent();}/// <summary>/// 画像ファイルを選択し、表示/// </summary>privatevoidOpenImageFile(){vardlg=newMicrosoft.Win32.OpenFileDialog();dlg.Title="画像を選択してください。";dlg.Filter="画像ファイル|*.gif;*.png;*.jpeg;*.jpg;*.bmp|すべてのファイル|*.*";if(dlg.ShowDialog()==true){// 画像表示画面生成varwindow=newImageWindow();// 画像表示画面に画像設定if(window.SetImage(dlg.FileName)){// 画面表示window.Show();}}}/// <summary>/// 画像を開くボタンクリック時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidButton_Click(objectsender,RoutedEventArgse){OpenImageFile();}/// <summary>/// 子画面全終了/// </summary>privatevoidCloseSubWindows(){foreach(WindowwinApp.Current.Windows){if(w!=this){// 自身(メイン画面)以外なら終了させるw.Close();}}}/// <summary>/// 画像をすべて閉じるボタンクリック時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidButton_Click_1(objectsender,RoutedEventArgse){// 子画面全終了CloseSubWindows();}/// <summary>/// ウィンドウ終了時/// </summary>/// <param name="sender"></param>/// <param name="e"></param>privatevoidWindow_Closed(objectsender,EventArgse){// 開きっぱなしの子画面があったら終了CloseSubWindows();}}}最終的にXamlは以下のようになりました。
<Windowx:Class="ImageView.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:ImageView"mc:Ignorable="d"Title="画像ビューア"Height="150"Width="450"MinHeight="100"MinWidth="150"ResizeMode="CanResizeWithGrip"Closed="Window_Closed"><Window.Resources><!-- ボタンの既定スタイル --><StyleTargetType="Button"><SetterProperty="Margin"Value="5"/><SetterProperty="Padding"Value="5"/></Style></Window.Resources><Viewbox><StackPanelOrientation="Horizontal"><ButtonContent="画像を開く"IsDefault="True"Click="Button_Click"/><ButtonContent="画像をすべて閉じる"Click="Button_Click_1"/></StackPanel></Viewbox></Window>■動かしてみる
ウィンドウサイズを大きくしてみます。
Viewboxを使っているので拡大縮小してもきれいに表示されます。
「画像を開く」ボタンを押すと、ファイル選択ダイアログが表示されるので、画像を選択します。
続けて他にも画像を開いてみます。
画像の上でマウスホイールを奥に回すと拡大、手前に回すと縮小します。+ボタン、-ボタンでも拡大、縮小できます。このボタンは長押しに対応しています。
「画像をすべて閉じる」ボタンを押すと、画像ウィンドウが一気に全部閉じます。
おしまい








