Skip to content

Instantly share code, notes, and snippets.

@Grabacr07
Last active November 17, 2021 20:39
Show Gist options
  • Save Grabacr07/988bc04fb7f16aaa4fdc to your computer and use it in GitHub Desktop.
Save Grabacr07/988bc04fb7f16aaa4fdc to your computer and use it in GitHub Desktop.
WPF の Thumb コントロールで Photoshop のナビゲーターを再現するやつ
<Window x:Class="ThumbsScrollViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="1200"
Height="600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Canvas Width="{Binding ElementName=Thumbnail, Path=ActualWidth}"
Height="{Binding ElementName=Thumbnail, Path=ActualHeight}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10"
UseLayoutRounding="True">
<Image x:Name="Thumbnail"
Width="100"
Stretch="Uniform" />
<Path Fill="#7FFFFFFF">
<Path.Data>
<CombinedGeometry x:Name="CombinedGeometry"
GeometryCombineMode="Xor" />
</Path.Data>
</Path>
<Thumb x:Name="Viewport"
DragDelta="OnDragDelta">
<Thumb.Template>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border BorderBrush="Red"
BorderThickness="2"
Background="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
<ScrollViewer x:Name="ScrollViewer"
Grid.Column="1"
HorizontalScrollBarVisibility="Visible"
VerticalScrollBarVisibility="Visible"
ScrollChanged="UpdateThumbnailViewport">
<Image x:Name="Image" />
</ScrollViewer>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ThumbsScrollViewer
{
public partial class MainWindow
{
public MainWindow()
{
this.InitializeComponent();
var image = new BitmapImage(new Uri("http://www.hitachinoki.net/download/wp/2015_ta.jpg"));
image.DownloadCompleted += (sender, e) =>
{
var rect = new Rect(0, 0, this.Thumbnail.ActualWidth, this.Thumbnail.ActualHeight);
this.CombinedGeometry.Geometry1 = new RectangleGeometry(rect);
};
this.Image.Source = this.Thumbnail.Source = image;
}
private void OnDragDelta(object sender, DragDeltaEventArgs e)
{
this.ScrollViewer.ScrollToHorizontalOffset(
this.ScrollViewer.HorizontalOffset + (e.HorizontalChange * this.ScrollViewer.ExtentWidth / this.Thumbnail.ActualWidth));
this.ScrollViewer.ScrollToVerticalOffset(
this.ScrollViewer.VerticalOffset + (e.VerticalChange * this.ScrollViewer.ExtentHeight / this.Thumbnail.ActualHeight));
}
private void UpdateThumbnailViewport(object sender, ScrollChangedEventArgs e)
{
// ExtentWidth/Height が ScrollViewer 内の広さ
// ViewportWidth/Height が ScrollViewer で実際に表示されているサイズ
var xfactor = this.Thumbnail.ActualWidth / e.ExtentWidth;
var yfactor = this.Thumbnail.ActualHeight / e.ExtentHeight;
var left = e.HorizontalOffset * xfactor;
var top = e.VerticalOffset * yfactor;
var width = e.ViewportWidth * xfactor;
if (width > this.Thumbnail.ActualWidth) width = this.Thumbnail.ActualWidth;
var height = e.ViewportHeight * yfactor;
if (height > this.Thumbnail.ActualHeight) height = this.Thumbnail.ActualHeight;
// Canvas (親パネル) 上での Thumb の位置を、Left/Top 添付プロパティで設定
// (XAML で言う <Thumb Canvas.Left="0" ... \> みたいなやつ)
Canvas.SetLeft(this.Viewport, left);
Canvas.SetTop(this.Viewport, top);
this.Viewport.Width = width;
this.Viewport.Height = height;
this.CombinedGeometry.Geometry2 = new RectangleGeometry(new Rect(left, top, width, height));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment