C#、WPF图片查看器
项目中需要用到图片查看器功能,记录一下自己的WPF实现,支持鼠标拖动、滑轮放大缩小和改变窗体大小。因为本文代码是整个工程中的一部分,有些变量没有删除。
1、界面
界面非常的简单,只有六个按键:
- 打开图片:选择自己想要预览的图片,支持多选。
- 还原:将图片还原回最初状态。
- 放大:本设计有所不同,这里是以上次鼠标点击位置为中心进行放大。
- 缩小:同上。
- 上一张、下一张:支持循环浏览图片。
下载链接:https://download.csdn.net/download/qq_44845723/20212511.
2、代码部分
2.1、MainWindow.xaml
<Window x:Class="WpfApplication2.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:WpfApplication2"
mc:Ignorable="d"
Title="图片查看器" Height="600" Width="1000" Loaded="Window_Loaded"
SizeChanged="Window_SizeChanged" DragEnter="Window_DragEnter" Drop="Window_Drop">
<Grid x:Name="mainGrid" >
<Grid.Resources>
<!--- 将多中变化组合到一起-->
<TransformGroup x:Key="TfGroup">
<!--- 将多中变化组合到一起-->
<ScaleTransform ScaleX="1" ScaleY="1"/>
<!--缩放操作-->
<TranslateTransform X="0" Y="0"/>
<!--移动操作-->
</TransformGroup>
<!--按钮样式-->
<Style x:Key="ImageToolBtn" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Chrome" BorderBrush="Transparent" Background="Transparent" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#FF288ADD"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<!--分割页面-->
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<!--上侧显示区-->
<ScrollViewer x:Name="mainScrollv" HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Disabled" Cursor="SizeAll" Margin="0" Focusable="False" Grid.Row="0">
<ContentControl MouseLeftButtonDown="ContentControl_MouseLeftButtonDown"
MouseLeftButtonUp="ContentControl_MouseLeftButtonUp"
MouseMove="ContentControl_MouseMove"
MouseWheel="ContentControl_MouseWheel"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Image x:Name="IMG" Margin="0" RenderTransform="{StaticResource TfGroup}" RenderOptions.BitmapScalingMode="NearestNeighbor" />
</ContentControl>
</ScrollViewer>
<!--按钮项-->
<Border x:Name="border" BorderThickness="0" Margin="0,0,0,0" VerticalAlignment="Bottom" HorizontalAlignment="Center" Background="White" Grid.Row="1">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="46" Orientation="Horizontal" Margin="0">
<Button x:Name="btnOpenFiles" Click="btnOpenFiles_Click" Width="50" Height="30" Content="打开图片" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
<Button x:Name="btnActualsize" Click="btnActualsize_Click" Width="50" Height="30" Content="还原" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
<Button x:Name="btnEnlarge" Click="btnEnlarge_Click" Width="50" Height="30" Content="放大" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
<Button x:Name="btnNarrow" Click="btnNarrow_Click" Width="50" Height="30" Content="缩小" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
<Button x:Name="btnUpImg" Click="btnUpImg_Click" Width="50" Height="30" Content="上一张" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
<Button x:Name="btnDownImg" Click="btnDownImg_Click" Width="50" Height="30" Content="下一张" Margin="10,0,0,10" Cursor="Hand" Background="Transparent" BorderThickness="0"/>
</StackPanel>
</Border>
</Grid>
</Window>
2.2、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;
using System.IO;
namespace WpfApplication2
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private bool mouseDown; //鼠标是否按下
private Point mouseXY; //鼠标坐标
private double min = 0.1, max = 3.0;//最小/最大放大倍数
List<string> fileNames = new List<string>();
int nowShowImgNumber = 0; //当前显示的是第几张图片
double translateX = 0; //图片在 x y 方向上的移动距离
double translateY = 0;
private void Domousemove(ContentControl img, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
{
return;
}
var group = IMG.FindResource("TfGroup") as TransformGroup;
var transform = group.Children[1] as TranslateTransform;
var position = e.GetPosition(img);
transform.X -= mouseXY.X - position.X; translateX += transform.X;
transform.Y -= mouseXY.Y - position.Y; translateY += transform.Y;
mouseXY = position;
}
private void DowheelZoom(TransformGroup group, Point point, double delta)
{
var pointToContent = group.Inverse.Transform(point);
var transform = group.Children[0] as ScaleTransform;
if (transform.ScaleX + delta < min) return;
if (transform.ScaleX + delta > max) return;
transform.ScaleX += delta;
transform.ScaleY += delta;
var transform1 = group.Children[1] as TranslateTransform;
transform1.X = -1 * ((pointToContent.X * transform.ScaleX) - point.X); translateX += transform1.X;
transform1.Y = -1 * ((pointToContent.Y * transform.ScaleY) - point.Y); translateY += transform1.Y;
}
//图像显示区,左键按下
private void ContentControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
img.CaptureMouse();
mouseDown = true;
mouseXY = e.GetPosition(img);
}
//图像显示区,左键抬起
private void ContentControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
img.ReleaseMouseCapture();
mouseDown = false;
}
//图像显示区, 鼠标移动
private void ContentControl_MouseMove(object sender, MouseEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
if (mouseDown) //鼠标左键按下
{
Domousemove(img, e);
}
}
//鼠标滑轮滚动
private void ContentControl_MouseWheel(object sender, MouseWheelEventArgs e)
{
var img = sender as ContentControl;
if (img == null)
{
return;
}
var point = e.GetPosition(img); //获得鼠标在控件中的位置
mouseXY = point; //鼠标当前位置
var group = IMG.FindResource("TfGroup") as TransformGroup;
var delta = e.Delta * 0.001; //放大倍数
DowheelZoom(group, point, delta);
}
//打开文件,选择要读取的文件
private void btnOpenFiles_Click(object sender, RoutedEventArgs e)
{
// 在WPF中, OpenFileDialog位于Microsoft.Win32名称空间
Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
dialog.Multiselect = true;//可以选择多个选项
dialog.Title = "选择图片";
dialog.Filter = "jpg文件(*.jpg)|*.jpg|png文件 (*.png)|*.png|全部(*.all)|*.*";
if (dialog.ShowDialog() == true)
{
//MessageBox.Show(dialog.FileName);
fileNames.RemoveRange(0, fileNames.Count());
foreach (string name in dialog.FileNames)
{
fileNames.Add(name);
}
nowShowImgNumber = 0; //显示第一张图片
this.IMG.Source = new BitmapImage(new Uri(fileNames[0]));
RestoreImgShowRuler(); RestoreImgShowRuler();
}
}
//将图像显示尺寸还原为 1:1,原图大小
private void RestoreImgShowRuler()
{
var group = IMG.FindResource("TfGroup") as TransformGroup;
var transform = group.Children[0] as ScaleTransform; // 首先研究缩放
transform.ScaleX = 1;
transform.ScaleY = 1;
var translate = group.Children[1] as TranslateTransform;
translate.X = -translateX;
translate.Y = -translateY;
translateX = 0;
translateY = 0;
mouseXY.X = 0;
mouseXY.Y = 0;
}
//将图片尺寸还原为 1:1
private void btnActualsize_Click(object sender, RoutedEventArgs e)
{
var img = sender as ContentControl;
if (img == null) //当前没有图片
{
return;
}
RestoreImgShowRuler(); RestoreImgShowRuler();
}
//图片放大按钮
private void btnEnlarge_Click(object sender, RoutedEventArgs e)
{
var img = sender as ContentControl;
if (img == null) //当前没有图片
{
return;
}
var group = IMG.FindResource("TfGroup") as TransformGroup;
DowheelZoom(group, mouseXY, 0.1);
}
//图片缩小按钮
private void btnNarrow_Click(object sender, RoutedEventArgs e)
{
var img = sender as ContentControl;
if (img == null) //当前没有图片
{
return;
}
var group = IMG.FindResource("TfGroup") as TransformGroup;
DowheelZoom(group, mouseXY, -0.1);
}
//上一张图片
private void btnUpImg_Click(object sender, RoutedEventArgs e)
{
int imgNumber = fileNames.Count();
if (imgNumber == 0)
{
MessageBox.Show("没有选择任何图片!");
}
else //图片数量不为 0
{
if ((double)nowShowImgNumber / imgNumber > 0)
{
nowShowImgNumber--;
}
else
{
nowShowImgNumber = imgNumber - 1;
}
this.IMG.Source = new BitmapImage(new Uri(fileNames[nowShowImgNumber]));
RestoreImgShowRuler(); RestoreImgShowRuler();
}
}
//下一张图片
private void btnDownImg_Click(object sender, RoutedEventArgs e)
{
int imgNumber = fileNames.Count();
if (imgNumber == 0)
{
MessageBox.Show("没有选择任何图片!");
}
else
{
if (imgNumber > 1)
{
if ((double)nowShowImgNumber / (imgNumber - 1) == 1)
{
nowShowImgNumber = 0;
}
else
{
nowShowImgNumber++;
}
}
else
{
nowShowImgNumber = 0;
}
this.IMG.Source = new BitmapImage(new Uri(fileNames[nowShowImgNumber]));
RestoreImgShowRuler(); RestoreImgShowRuler();
}
}
//窗口加载,设置显示区窗口的尺寸
private void Window_Loaded(object sender, RoutedEventArgs e)
{
setViewSize();
}
//显示区窗口尺寸设置
private void setViewSize()
{
mainScrollv.Width = this.ActualWidth; // 图像显示区 宽度 = 当前窗口的宽度
mainScrollv.Height = this.ActualHeight - 50; // 图像显示区的 高度 = 当前窗口的高度 - 其他高度
}
// 窗口尺寸发生变化后,重新设置显示区的尺寸
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
setViewSize();
}
//直接拖动文件到窗口,相当于 ButtonDown
private void Window_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effects = DragDropEffects.Link;//WinForm中为e.Effect = DragDropEffects.Link 拖动时的图标
else e.Effects = DragDropEffects.None;//WinFrom中为e.Effect = DragDropEffects.None
}
//拖动文件到窗口松开按键,相当于ButtonUp
private void Window_Drop(object sender, DragEventArgs e)
{
string filename = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
this.IMG.Source = new BitmapImage(new Uri(filename));
}
}
}