同じ大きさの2つの画像を並べて拡大して見比べたい
今回のアプリのダウンロード先
デザイン画面
<feff><Window x:Class="_20181111_2つの画像を拡大とスクロール同期.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:_20181111_2つの画像を拡大とスクロール同期"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="540">
<Grid Margin="0 10 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="0" Grid.RowSpan="1"
Orientation="Horizontal">
<TextBlock Text="{Binding ElementName=SliderScale, Path=Value, StringFormat=表示倍率 : 0}" Margin="10 0"/>
<Slider Name="SliderScale" Value="1.0" Minimum="1.0" Maximum="5.0" SmallChange="1.0" LargeChange="1.0"
IsMoveToPointEnabled="False" IsSnapToTickEnabled="True"
Width="100"/>
<TextBlock Text="{Binding ElementName=MyCanvas1, Path=Width, StringFormat=横 : 0}" Margin="10 0"/>
<TextBlock Text="{Binding ElementName=MyCanvas1, Path=Height, StringFormat=縦 : 0}" Margin="10 0"/>
<TextBlock Text="{Binding ElementName=MyScroll1,Path=VerticalOffset,StringFormat= vOffset \= 0}" Margin="10,0"/>
<TextBlock Text="{Binding ElementName=MyScroll1,Path=ScrollableHeight,StringFormat= height \= 0}" Margin="10,0"/>
<TextBlock Name="MyText"/>
</StackPanel>
<ScrollViewer Name="MyScroll1" Grid.Column="0" Grid.Row="1"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Canvas Name="MyCanvas1">
<Image Name="MyImage1" Stretch="None"/>
</Canvas>
</ScrollViewer>
<ScrollViewer Name="MyScroll2" Grid.Column="1" Grid.Row="1"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Canvas Name="MyCanvas2">
<Image Name="MyImage2" Stretch="None"/>
</Canvas>
</ScrollViewer>
</Grid>
</Window>
25行目から30行目は確認用だからか要らない
33行目から
ScrollViewer (スクロールバー表示)
┗Canvas (パネル系要素なら他のでもいいかも)
┗Image (画像表示用)
これを左右で2つ
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace _20181111_2つの画像を拡大とスクロール同期
{
public partial class MainWindow : Window
{
ScaleTransform MyScale;
public MainWindow()
{
InitializeComponent();
Title = this.ToString();
Loaded += MainWindow_Loaded;
MyInitialize();
}
private void MyInitialize()
{
string filePath1 = @"D:\ブログ用\チェック用2\NEC_5899_2018_10_28_午後わてん_.jpg";
string filePath2 = @"D:\ブログ用\チェック用2\NEC_5899_2018_10_28_午後わてん_16color.png";
MyImage1.Source = new BitmapImage(new Uri(filePath1));
MyImage2.Source = new BitmapImage(new Uri(filePath2));
SliderScale.ValueChanged += SliderScale_ValueChanged;
MyScroll1.ScrollChanged += MyScroll1_ScrollChanged;
MyScroll2.ScrollChanged += MyScroll2_ScrollChanged;
MyScale = new ScaleTransform();
MyImage1.RenderTransform = MyScale;
MyImage2.RenderTransform = MyScale;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
MyCanvas1.Width = MyImage1.ActualWidth;
MyCanvas1.Height = MyImage1.ActualHeight;
MyCanvas2.Width = MyImage2.ActualWidth;
MyCanvas2.Height = MyImage2.ActualHeight;
RenderOptions.SetBitmapScalingMode(MyImage1, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetBitmapScalingMode(MyImage2, BitmapScalingMode.NearestNeighbor);
}
private void MyScroll2_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e.VerticalOffset != MyScroll1.VerticalOffset)
{
MyScroll1.ScrollToVerticalOffset(e.VerticalOffset);
}
if (e.HorizontalOffset != MyScroll1.HorizontalOffset)
{
MyScroll1.ScrollToHorizontalOffset(e.HorizontalOffset);
}
}
private void MyScroll1_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (e.VerticalOffset != MyScroll2.VerticalOffset)
{
MyScroll2.ScrollToVerticalOffset(e.VerticalOffset);
}
if (e.HorizontalOffset != MyScroll2.HorizontalOffset)
{
MyScroll2.ScrollToHorizontalOffset(e.HorizontalOffset);
}
}
private void SliderScale_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
MyScale.ScaleX = e.NewValue;
MyScale.ScaleY = e.NewValue;
var bounds = MyScale.TransformBounds(new Rect(MyImage1.RenderSize));
MyCanvas1.Height = bounds.Height;
MyCanvas1.Width = bounds.Width;
bounds = MyScale.TransformBounds(new Rect(MyImage2.RenderSize));
MyCanvas2.Height = bounds.Height;
MyCanvas2.Width = bounds.Width;
}
}
}
スクロールバーの表示
スクロールバーを付けるにはScrollViewerを使う
ScrollViewerは一個だけ中に小要素(コン
トロール)を入れることができる、今回の小要素は
Canvas
ScrollViewerより小要素のサイズが大きいときスクロールバーが表示される
2つのスクロールバーの同期
ScrollViewerのScrollChangedイベント発生時に同期しているだけなんだけど、これがわからなくて参考になったのがこちら
UWPのScrollViewerでスクロール位置の同期を行うメモ
ありがとうございます
最初は
1:Scroll1のScrollChangedイベントが発生したのでScroll2の値を変更
2:Scroll2のScrollChangedイベントが発生したのでScroll1の値を変更
3:1に戻る
っていう永久ループだった
こうならないために相手の値と比較して同じだったら変更しないって処理が必要だった、78行目
if (e.VerticalOffset != MyScroll1.VerticalOffset)
簡単なことだけど、全く思いつかなかったw
拡大倍率の変更にスクロールバーも同期させる
画像の拡大は画像を表示しているImageのRenderTransformにScaleTransformのScaleを変更するだけでいいとして
スクロールバーは小要素のサイズを変更する必要がある
指定するサイズは拡大された後の画像の大きさで、それを取得しているのが
107行目
var bounds = MyScale.TransformBounds(new Rect(MyImage1.RenderSize));
変数の型をvarで取っているけど実際はRectだわ
TransformクラスのTransformBoundsメソッドを使ってImageの拡大後のRect(四角形サイズ)を取得できる
でもこれをつかわなくても、画像の縦横
ピクセル数に拡大倍率をかけてもいいかも
取得できた値で
Canvasのサイズを変更すると、スクロールバーも変更される
うまく動かなかった例1
ScrollViewer
┗Canvas
┗Image
ScrollViewer
┗Image
こうしてみたら
拡大倍率を変更しなければ正しく表示、正しい動作
だけど
拡大倍率を変更して2倍にすると
画像は拡大されたけどスクロールバーが拡大に対応していない
これはImageのサイズを変更していないからなので
変更するようにして
こうしてみたら今度は
スクロールバーは正しい動作だけど画像が表示されない
なのでScrollViewerに中に直接Imageを入れるよりも
Canvasを挟んだほうがいいみたいだった
うまく動かなかった例2
スクロールバーの同期はBinding使えばいいんじゃね?
こうして2つのScrollViewerのVerticalOffsetを
バインディングしようとしたんだけど
実行したら
双方向をやめて、
TextBlockのTextにバインディングしてみたら
これは正しく動作した
うーん、ScrollViewer同士もできたらいいのにねえ
減色アプリももう少し便利にしたい、作り直したいなあと思って
減色前後を見比べたかった
参照したところ
ギットハブ
関連記事
次、2018/11/16
2018/4/10
半年後2019/03/11