C# WPF自定义窗口

C# WPF自定义窗口

书接上文,我们已经实现了如何利用百度智能云实现文字OCR功能,WPF制作文字OCR软件(一):本地图片OCR识别,最后整体的效果是要呈现在一个窗口上的,而WPF的默认窗口并不能符合我们的需求,能够自己定义的内容少,所以这篇文章将介绍如何自定义窗口。

整体实现效果如下:
C# WPF自定义窗口_第1张图片

一、自定义标题栏

  1. 首先需要在窗口定义的时候加上 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>
  1. 在窗口上定义一个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. 选中按钮时,会出现蓝色薄膜将按钮图片覆盖

C# WPF自定义窗口_第2张图片解决方法1:
在MainWindow.xaml中加入以下代码:

<Window.Resources>
        <Style TargetType="{x:Type Button}">
            
                
                    {x:Type Button}">
                        {TemplateBinding Background}">
                        
                    
                
            
        Style>
    Window.Resources>

解决方法2:
用特殊字符替代图片。用特殊字符代替图片可以更加容易改变颜色、大小等特征,但是一些特殊字符难以找到

  1. 按钮图片的白色背景可以通过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如何实现截图效果。

你可能感兴趣的:(wpf)