博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox
阅读量:5944 次
发布时间:2019-06-19

本文共 11067 字,大约阅读时间需要 36 分钟。

原文:

一.前言

  申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接。

  本文主要内容:

  • 自定义Window窗体样式;
  • 基于自定义窗体实现自定义MessageBox消息提示框;

二.自定义Window窗体样式

  自定义的Window窗体效果:

 

  因为WPF默认的窗体比较简陋,大都需要自己实现Window窗体样式效果,基本思路很简单:

  • 第一步:干掉默认样式:WindowStyle = WindowStyle.None;
  • 第二步:设置窗体透明:AllowsTransparency = true;
  • 第三步:设置自己的窗体样式;

  这样从外观样式上可以满足,但做为窗体该具备的基本功能还没有,需要另外来实现了:

  • 窗体Icon、标题栏(可以通过样式实现);
  • 窗体的基本按钮:最小化、最大化、关闭按钮;
  • 窗体的鼠标拖动;
  • 好像Win8、Win10的功能吧,窗体拖动到桌面边缘自动最大化、还原;
  • 鼠标调整窗口大小;
  • 双击标题栏最大化、还原;

  上面的功能在本文中,一部分是自定义实现的,还有一部分是用了一个开源库(Microsoft.Windows.Shell)用于实现窗体大小、拖放等窗体基本功能,Microsoft.Windows.Shell文件下载:。

  进入正题,自定义窗体WindowBase的后台C#代码:  

///     /// WindowBase.xaml 的交互逻辑    ///     public class WindowBase : Window    {        #region 默认Header:窗体字体图标FIcon        public static readonly DependencyProperty FIconProperty =            DependencyProperty.Register("FIcon", typeof(string), typeof(WindowBase), new PropertyMetadata("\ue62e"));        ///         /// 按钮字体图标编码        ///         public string FIcon        {            get { return (string)GetValue(FIconProperty); }            set { SetValue(FIconProperty, value); }        }        #endregion        #region  默认Header:窗体字体图标大小        public static readonly DependencyProperty FIconSizeProperty =            DependencyProperty.Register("FIconSize", typeof(double), typeof(WindowBase), new PropertyMetadata(20D));        ///         /// 按钮字体图标大小        ///         public double FIconSize        {            get { return (double)GetValue(FIconSizeProperty); }            set { SetValue(FIconSizeProperty, value); }        }        #endregion        #region CaptionHeight 标题栏高度        public static readonly DependencyProperty CaptionHeightProperty =            DependencyProperty.Register("CaptionHeight", typeof(double), typeof(WindowBase), new PropertyMetadata(26D));        ///         /// 标题高度        ///         public double CaptionHeight        {            get { return (double)GetValue(CaptionHeightProperty); }            set            {                SetValue(CaptionHeightProperty, value);                //this._WC.CaptionHeight = value;            }        }        #endregion        #region CaptionBackground 标题栏背景色        public static readonly DependencyProperty CaptionBackgroundProperty = DependencyProperty.Register(            "CaptionBackground", typeof(Brush), typeof(WindowBase), new PropertyMetadata(null));        public Brush CaptionBackground        {            get { return (Brush)GetValue(CaptionBackgroundProperty); }            set { SetValue(CaptionBackgroundProperty, value); }        }        #endregion        #region CaptionForeground 标题栏前景景色        public static readonly DependencyProperty CaptionForegroundProperty = DependencyProperty.Register(            "CaptionForeground", typeof(Brush), typeof(WindowBase), new PropertyMetadata(null));        public Brush CaptionForeground        {            get { return (Brush)GetValue(CaptionForegroundProperty); }            set { SetValue(CaptionForegroundProperty, value); }        }        #endregion        #region Header 标题栏内容模板,以提高默认模板,可自定义        public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(            "Header", typeof(ControlTemplate), typeof(WindowBase), new PropertyMetadata(null));        public ControlTemplate Header        {            get { return (ControlTemplate)GetValue(HeaderProperty); }            set { SetValue(HeaderProperty, value); }        }        #endregion        #region MaxboxEnable 是否显示最大化按钮        public static readonly DependencyProperty MaxboxEnableProperty = DependencyProperty.Register(            "MaxboxEnable", typeof(bool), typeof(WindowBase), new PropertyMetadata(true));        public bool MaxboxEnable        {            get { return (bool)GetValue(MaxboxEnableProperty); }            set { SetValue(MaxboxEnableProperty, value); }        }        #endregion        #region MinboxEnable 是否显示最小化按钮        public static readonly DependencyProperty MinboxEnableProperty = DependencyProperty.Register(            "MinboxEnable", typeof(bool), typeof(WindowBase), new PropertyMetadata(true));        public bool MinboxEnable        {            get { return (bool)GetValue(MinboxEnableProperty); }            set { SetValue(MinboxEnableProperty, value); }        }        #endregion        public WindowBase()        {            this.WindowStyle = WindowStyle.None;            this.AllowsTransparency = true;            this.WindowStartupLocation = WindowStartupLocation.CenterScreen;            this.Style = this.FindResource("DefaultWindowStyle") as Style;            this.Icon = Images.CreateImageSourceFromImage(Properties.Resources.logo);            //12=6+6//Margin=6,Border.Effect.BlueRadius=6            this.MaxHeight = SystemParameters.WorkArea.Height + 12 + 2;            //bind command            this.BindCommand(SystemCommands.CloseWindowCommand, this.CloseCommand_Execute);            this.BindCommand(ApplicationCommands.Close, this.CloseCommand_Execute);            this.BindCommand(SystemCommands.MaximizeWindowCommand, this.MaxCommand_Execute);            this.BindCommand(SystemCommands.MinimizeWindowCommand, this.MinCommand_Execute);        }        private void CloseCommand_Execute(object sender, ExecutedRoutedEventArgs e)        {            SystemCommands.CloseWindow(this);        }        private void MaxCommand_Execute(object sender, ExecutedRoutedEventArgs e)        {            this.WindowState = this.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;            e.Handled = true;        }        private void MinCommand_Execute(object sender, ExecutedRoutedEventArgs e)        {            this.WindowState = WindowState.Minimized;            e.Handled = true;        }        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)        {            base.OnMouseLeftButtonDown(e);            if (e.ButtonState == MouseButtonState.Pressed)            {                this.DragMove();            }        }    }
View Code

  绑定命令的扩展方法:

///         /// 绑定命令和命令事件到宿主UI        ///         public static void BindCommand(this UIElement @ui, ICommand com, Action
call) { var bind = new CommandBinding(com); bind.Executed += new ExecutedRoutedEventHandler(call); @ui.CommandBindings.Add(bind); }

  WindowBase的样式有两个,一个是基础样式BaseWindowStyle,可以自定义头部标题栏,提供更多定制需求。另一个样式DefaultWindowStyle为默认窗体样式,用于大多数不要特别定制的窗体需求。BaseWindowStyle样式代码:  

  DefaultWindowStyle样式代码:  

View Code

  上面效果的背景色彩、边框的资源:  

 

三.实现自定义MessageBox消息提示框

  基于第二节自定义的窗体WindowBase,实现自定义的MessageBox就简单了,效果图:

  仔细观察,不难发现上面的窗体大小是根据内容的多少自适应的。窗体自适应内容的的关键设置就是SizeToContent="WidthAndHeight",但为了达到更好的效果控制,还需要控制内容的大小范围,范围可以自己调整,看了样式代码你就了解了:  

新建一个WPF程序在Windows8下面就会出现左边的窗口边框,颜色取决于Windows主题我想在想创建一个右边那样的窗口,要么是窄边,要么没有边
确定
取消

  上面不同消息类型的颜色资源:  

  后台C#代码  

///     /// MessageBoxXxaml.xaml 的交互逻辑    ///     public partial class MessageBoxX : WindowBase    {        ///         /// 结果,用户点击确定Result=true;        ///         public bool Result { get; private set; }        private static readonly Dictionary
_Brushes = new Dictionary
(); public MessageBoxX(EnumNotifyType type, string mes) { InitializeComponent(); this.txtMessage.Text = mes; //type btnCancel.Visibility = Visibility.Collapsed; this.SetForeground(type); switch (type) { case EnumNotifyType.Error: this.ficon.Text = "\ue644"; break; case EnumNotifyType.Warning: this.ficon.Text = "\ue60b"; break; case EnumNotifyType.Info: this.ficon.Text = "\ue659"; break; case EnumNotifyType.Question: this.ficon.Text = "\ue60e"; this.btnCancel.Visibility = Visibility.Visible; break; } } private void SetForeground(EnumNotifyType type) { string key = type.ToSafeString() + "Foreground"; if (!_Brushes.ContainsKey(key)) { var b = this.TryFindResource(key) as Brush; _Brushes.Add(key, b); } this.Foreground = _Brushes[key]; } private void btnOK_Click(object sender, RoutedEventArgs e) { this.Result = true; this.Close(); e.Handled = true; } private void btnCancel_Click(object sender, RoutedEventArgs e) { this.Result = false; this.Close(); e.Handled = true; } /********************* public static method **************************/ ///
/// 提示错误消息 /// public static void Error(string mes, Window owner = null) { Show(EnumNotifyType.Error, mes, owner); } ///
/// 提示普通消息 /// public static void Info(string mes, Window owner = null) { Show(EnumNotifyType.Info, mes, owner); } ///
/// 提示警告消息 /// public static void Warning(string mes, Window owner = null) { Show(EnumNotifyType.Warning, mes, owner); } ///
/// 提示询问消息 /// public static bool Question(string mes, Window owner = null) { return Show(EnumNotifyType.Question, mes, owner); } ///
/// 显示提示消息框, /// owner指定所属父窗体,默认参数值为null,则指定主窗体为父窗体。 /// private static bool Show(EnumNotifyType type, string mes, Window owner = null) { var res = true; Application.Current.Dispatcher.Invoke(new Action(() => { MessageBoxX nb = new MessageBoxX(type, mes) { Title = type.GetDescription() }; nb.Owner = owner ?? Application.Current.MainWindow; nb.ShowDialog(); res = nb.Result; })); return res; } ///
/// 通知消息类型 /// public enum EnumNotifyType { [Description("错误")] Error, [Description("警告")] Warning, [Description("提示信息")] Info, [Description("询问信息")] Question, } }
View Code

 

附录:参考引用

 

  

版权所有,文章来源:

个人能力有限,本文内容仅供学习、探讨,欢迎指正、交流。

转载地址:http://flzxx.baihongyu.com/

你可能感兴趣的文章
POJ-2251 Dungeon Master
查看>>
tortoisesvn的安装
查看>>
大S变"汪太"!与汪小菲注册结婚
查看>>
我是怎么使用最短路径算法解决动态联动问题的
查看>>
sublime Text 2 配置以及 Python环境搭建
查看>>
[2778]小明的花费预算 (二分查找)SDUT
查看>>
Runnable接口介绍(中文文档)
查看>>
URAL 1353 Milliard Vasya's Function DP
查看>>
速读《构建之法:现代软件工程》提问
查看>>
在iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式
查看>>
Android onclicklistener中使用外部类变量时为什么需要final修饰【转】
查看>>
Matlab2012a下配置LibSVM—3.18
查看>>
SpringBoot 搭建
查看>>
中信国健临床通讯2011年7月期目录
查看>>
iOS开发之设计模式篇
查看>>
电信运营商 IT 系统介绍
查看>>
简单粗暴的“Debug模式”
查看>>
汇编实验一
查看>>
Python 面试总结
查看>>
ansible register when: result | succeeded when: item.rc != 0
查看>>