书接上文,我们已经实现了如何利用百度智能云实现文字OCR功能,WPF制作文字OCR软件(一):本地图片OCR识别,最后整体的效果是要呈现在一个窗口上的,而WPF的默认窗口并不能符合我们的需求,能够自己定义的内容少,所以这篇文章将介绍如何自定义窗口。
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
,代码段如下:<Window x:Class="SnipOCR.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:SnipOCR"
mc:Ignorable="d"
Height="400" Width="600" WindowStyle="None" AllowsTransparency="True" Background="Transparent" >
Window>
Grid
来显示标题、图标等<Grid Background="Wheat">
<Border BorderThickness="2" BorderBrush="#FF8FF172">Border>
<Grid HorizontalAlignment="Stretch" Margin="0,1,0,0" Height="26" VerticalAlignment="Top" MouseDown="Grid_MouseDown">
<Grid.Background>
<LinearGradientBrush EndPoint="1,1" MappingMode="RelativeToBoundingBox" StartPoint="0,0">
<GradientStop Color="#FF5BF1BA" Offset="1"/>
<GradientStop Color="#FFADCA82"/>
<GradientStop Color="#FF77D570" Offset="0.653"/>
LinearGradientBrush>
Grid.Background>
<Image Width="26" HorizontalAlignment="Left" Margin="5,0,0,0" Height="26" Source="resources/OCR.png">
Image>
<TextBlock Margin="40,0,0,0" FontSize="20">文字OCRTextBlock>
<Button Name="Close" Width="26" HorizontalAlignment="Right" Margin="0,0,0,0" BorderBrush="{x:Null}" Click="Close_Click">
<Button.Background>
<ImageBrush ImageSource="resources/Cancel.png" Stretch="UniformToFill"/>
Button.Background>
Button>
<Button Name="Max" HorizontalContentAlignment="Center" VerticalContentAlignment="Top" FontSize="28" Width="26" HorizontalAlignment="Right" Margin="0,0,27,0" BorderBrush="{x:Null}" Click="Max_Click">
<Button.Background>
<ImageBrush ImageSource="resources/max.png"/>
Button.Background>
Button>
<Button Name="Min" Width="26" FontSize="20" HorizontalAlignment="Right" Margin="0,0,54,0" BorderBrush="{x:Null}" Click="Min_Click">
<Button.Background>
<ImageBrush ImageSource="resources/min.png"/>
Button.Background>
Button >
Grid>
Grid>
可以看到上面用到了许多图片,所以需要新建一个文件夹来存放这些图片,这些图片可以在iconfont-阿里巴巴矢量图标库找到。同时可以看到这里有一些事件处理程序需要我们自己去写。
主要的事件处理程序为移动窗口(MouseDown="Grid_MouseDown"
)、窗口最小化(Click="Min_Click"
)、窗口最大化(Click=“Max_Click”)、窗口正常化(与窗口最大化为同一段程序)、关闭程序(Click="Close_Click"
)。
在MainWindow.xaml.cs
中添加以下程序:
// 图片资源声明
private string[] Image = new string[]
{
"pack://application:,,,/resources/Mini.png",
"pack://application:,,,/resources/max.png"
};
///
/// 关闭窗口
///
///
///
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
///
/// 窗口最大化/窗口正常化
///
///
///
private void Max_Click(object sender, RoutedEventArgs e)
{
if (this.WindowState != WindowState.Maximized)
{
this.WindowState = WindowState.Maximized;
Max.Background = new ImageBrush(new BitmapImage(new Uri(Image[0])));
}
else
{
this.WindowState = WindowState.Normal;
Max.Background = new ImageBrush(new BitmapImage(new Uri(Image[1])));
}
}
///
/// 窗口最小化
///
///
///
private void Min_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
///
/// 移动窗口
///
///
///
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
在MainWindow.xaml中添加以下代码
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2"/>
<RowDefinition/>
<RowDefinition Height="2"/>
Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2"/>
<ColumnDefinition/>
<ColumnDefinition Width="2"/>
Grid.ColumnDefinitions>
<Rectangle Name="ResizeTopLeft" Fill="#FF525151" Grid.Row="0" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeTop" Fill="#FF525151" Grid.Row="0" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeTopRight" Fill="#FF525151" Grid.Row="0" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeLeft" Fill="#FF525151" Grid.Row="1" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeRight" Fill="#FF525151" Grid.Row="1" Grid.Column="3" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottomLeft" Fill="#FF525151" Grid.Row="3" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottom" Fill="#FF525151" Grid.Row="3" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottomRight" Fill="#FF525151" Grid.Row="3" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
Grid>
在MainWindow.xaml.cs
中添加以下代码:
public MainWindow()
{
InitializeComponent();
this.SourceInitialized += delegate (object sender, EventArgs e)
{
this._HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
this.MouseMove += new MouseEventHandler(Window_MouseMove);
};
}
public enum ResizeDirection
{
///
/// 左
///
Left = 1,
///
/// 右
///
Right = 2,
///
/// 上
///
Top = 3,
///
/// 左上
///
TopLeft = 4,
///
/// 右上
///
TopRight = 5,
///
/// 下
///
Bottom = 6,
///
/// 左下
///
BottomLeft = 7,
///
/// 右下
///
BottomRight = 8,
}
// 图片资源声明
private string[] Image = new string[]
{
"pack://application:,,,/resources/Mini.png",
"pack://application:,,,/resources/max.png"
};
///
/// 拉伸窗口 Begin
///
private HwndSource _HwndSource;
private const int WM_SYSCOMMAND = 0x112;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private Dictionary<ResizeDirection, Cursor> cursors = new Dictionary<ResizeDirection, Cursor>
{
{ResizeDirection.Top, Cursors.SizeNS},
{ResizeDirection.Bottom, Cursors.SizeNS},
{ResizeDirection.Left, Cursors.SizeWE},
{ResizeDirection.Right, Cursors.SizeWE},
{ResizeDirection.TopLeft, Cursors.SizeNWSE},
{ResizeDirection.BottomRight, Cursors.SizeNWSE},
{ResizeDirection.TopRight, Cursors.SizeNESW},
{ResizeDirection.BottomLeft, Cursors.SizeNESW}
};
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton != MouseButtonState.Pressed)
{
FrameworkElement element = e.OriginalSource as FrameworkElement;
if (element != null && !element.Name.Contains("Resize")) this.Cursor = Cursors.Arrow;
}
}
private void ResizePressed(object sender, MouseEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize", ""));
this.Cursor = cursors[direction];
if (e.LeftButton == MouseButtonState.Pressed) ResizeWindow(direction);
}
private void ResizeWindow(ResizeDirection direction)
{
SendMessage(_HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);
}
///
/// 窗口拉伸 End
///
- 选中按钮时,会出现蓝色薄膜将按钮图片覆盖
解决方法1:
在MainWindow.xaml中加入以下代码:
<Window.Resources>
<Style TargetType="{x:Type Button}">
{ x:Type Button}">
{ TemplateBinding Background}">
Style>
Window.Resources>
解决方法2:
用特殊字符替代图片。用特殊字符代替图片可以更加容易改变颜色、大小等特征,但是一些特殊字符难以找到
- 按钮图片的白色背景可以通过PS消除
MainWindow.xaml
<Window x:Class="CSDNT.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:CSDNT"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="600" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
<Window.Resources>
<Style TargetType="{x:Type Button}">
{ x:Type Button}">
{ TemplateBinding Background}">
Style>
Window.Resources>
<Grid Background="Wheat">
<Border BorderThickness="2" BorderBrush="#FF8FF172">Border>
<Grid HorizontalAlignment="Stretch" Margin="0,1,0,0" Height="26" VerticalAlignment="Top" MouseDown="Grid_MouseDown">
<Grid.Background>
<LinearGradientBrush EndPoint="1,1" MappingMode="RelativeToBoundingBox" StartPoint="0,0">
<GradientStop Color="#FF5BF1BA" Offset="1"/>
<GradientStop Color="#FFADCA82"/>
<GradientStop Color="#FF77D570" Offset="0.653"/>
LinearGradientBrush>
Grid.Background>
<Image Width="26" HorizontalAlignment="Left" Margin="5,0,0,0" Height="26" Source="resources/OCR.png">
Image>
<TextBlock Margin="40,0,0,0" FontSize="20">文字OCRTextBlock>
<Button Name="Close" Width="26" HorizontalAlignment="Right" Margin="0,0,0,0" BorderBrush="{x:Null}" Click="Close_Click">
<Button.Background>
<ImageBrush ImageSource="resources/Cancel.png" Stretch="UniformToFill"/>
Button.Background>
Button>
<Button Name="Max" HorizontalContentAlignment="Center" VerticalContentAlignment="Top" FontSize="28" Width="26" HorizontalAlignment="Right" Margin="0,0,27,0" BorderBrush="{x:Null}" Click="Max_Click">
<Button.Background>
<ImageBrush ImageSource="resources/max.png"/>
Button.Background>
Button>
<Button Name="Min" Width="26" FontSize="20" HorizontalAlignment="Right" Margin="0,0,54,0" BorderBrush="{x:Null}" Click="Min_Click">
<Button.Background>
<ImageBrush ImageSource="resources/min.png"/>
Button.Background>
Button >
Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2"/>
<RowDefinition/>
<RowDefinition Height="2"/>
Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2"/>
<ColumnDefinition/>
<ColumnDefinition Width="2"/>
Grid.ColumnDefinitions>
<Rectangle Name="ResizeTopLeft" Fill="#FF525151" Grid.Row="0" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeTop" Fill="#FF525151" Grid.Row="0" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeTopRight" Fill="#FF525151" Grid.Row="0" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeLeft" Fill="#FF525151" Grid.Row="1" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeRight" Fill="#FF525151" Grid.Row="1" Grid.Column="3" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottomLeft" Fill="#FF525151" Grid.Row="3" Grid.Column="0" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottom" Fill="#FF525151" Grid.Row="3" Grid.Column="1" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
<Rectangle Name="ResizeBottomRight" Fill="#FF525151" Grid.Row="3" Grid.Column="2" MouseMove="ResizePressed" MouseDown="ResizePressed"/>
Grid>
Grid>
Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
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.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace CSDNT
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.SourceInitialized += delegate (object sender, EventArgs e)
{
this._HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
};
this.MouseMove += new MouseEventHandler(Window_MouseMove);
}
public enum ResizeDirection
{
///
/// 左
///
Left = 1,
///
/// 右
///
Right = 2,
///
/// 上
///
Top = 3,
///
/// 左上
///
TopLeft = 4,
///
/// 右上
///
TopRight = 5,
///
/// 下
///
Bottom = 6,
///
/// 左下
///
BottomLeft = 7,
///
/// 右下
///
BottomRight = 8,
}
// 图片资源声明
private string[] Image = new string[]
{
"pack://application:,,,/resources/Mini.png",
"pack://application:,,,/resources/max.png"
};
///
/// 关闭窗口
///
///
///
private void Close_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
///
/// 窗口最大化/窗口正常化
///
///
///
private void Max_Click(object sender, RoutedEventArgs e)
{
if (this.WindowState != WindowState.Maximized)
{
this.WindowState = WindowState.Maximized;
Max.Background = new ImageBrush(new BitmapImage(new Uri(Image[0])));
}
else
{
this.WindowState = WindowState.Normal;
Max.Background = new ImageBrush(new BitmapImage(new Uri(Image[1])));
}
}
///
/// 窗口最小化
///
///
///
private void Min_Click(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
///
/// 移动窗口
///
///
///
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
///
/// 拉伸窗口 Begin
///
private HwndSource _HwndSource;
private const int WM_SYSCOMMAND = 0x112;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private Dictionary<ResizeDirection, Cursor> cursors = new Dictionary<ResizeDirection, Cursor>
{
{ResizeDirection.Top, Cursors.SizeNS},
{ResizeDirection.Bottom, Cursors.SizeNS},
{ResizeDirection.Left, Cursors.SizeWE},
{ResizeDirection.Right, Cursors.SizeWE},
{ResizeDirection.TopLeft, Cursors.SizeNWSE},
{ResizeDirection.BottomRight, Cursors.SizeNWSE},
{ResizeDirection.TopRight, Cursors.SizeNESW},
{ResizeDirection.BottomLeft, Cursors.SizeNESW}
};
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (Mouse.LeftButton != MouseButtonState.Pressed)
{
FrameworkElement element = e.OriginalSource as FrameworkElement;
if (element != null && !element.Name.Contains("Resize")) this.Cursor = Cursors.Arrow;
}
}
private void ResizePressed(object sender, MouseEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
ResizeDirection direction = (ResizeDirection)Enum.Parse(typeof(ResizeDirection), element.Name.Replace("Resize", ""));
this.Cursor = cursors[direction];
if (e.LeftButton == MouseButtonState.Pressed) ResizeWindow(direction);
}
private void ResizeWindow(ResizeDirection direction)
{
SendMessage(_HwndSource.Handle, WM_SYSCOMMAND, (IntPtr)(61440 + direction), IntPtr.Zero);
}
///
/// 窗口拉伸 End
///
}
}
窗口的自定义到这里就结束了,下篇文章将介绍WPF如何实现截图效果。