WPF 自定义窗口
在WPF中,经常需要对窗口进行设置,下面讲讲常用的几个设置。
窗口样式
1、无边框窗口
无边框透明窗体 设置
WindowStyle="None"--无边框,如果需要其它按钮,如缩小、放大、收缩、关闭按钮,可以自定义
AllowsTransparency="True"--只有设置了AllowsTransparency,才有1、窗体真正的隐藏边框2、背景透明有效
Background="Transparent"
窗口阴影设置
可以用Border的CornerRadius设置窗口四周圆角
设置窗口阴影--值得一提的是,如果直接用Window.Effect,效果会影响CornerRadius设置的圆角效果。
<Window.Effect>
<DropShadowEffect BlurRadius="30" Color="Gray" ShadowDepth="0" RenderingBias="Quality" ></DropShadowEffect>
</Window.Effect>
举例:
<Window x:Class="WpfApplication4.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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" WindowStartupLocation="CenterScreen"
AllowsTransparency="True" WindowStyle="None" Background="Transparent">
<Grid>
<Border CornerRadius="5" Background="Red"></Border>
</Grid>
</Window>
2、窗口按钮
当我们设置无边窗口时,也即是需要重新设置一套窗口的操作按钮。

按钮,可以用修改Button的Background或者修改Template,往其中设置图标或者直接用Path、Border、Rectangle等基础元素绘制。
然后添加简单的动画Animation
1) 方法1.下面是自定义的按钮Style,往其中传入图标路径即可
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle x:Name="T_Rectangle" Height="15" Width="15">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding ImagesSource}"></ImageBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"></ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="T_Rectangle" Property="Height" Value="18"></Setter>
<Setter TargetName="T_Rectangle" Property="Width" Value="18"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="T_Rectangle" Property="Height" Value="20"></Setter>
<Setter TargetName="T_Rectangle" Property="Width" Value="20"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2)方法2.直接用基础元素绘制
Path,通过Path来画线。当然一般水平、竖直也是可以用Rectangle/Border之类的替代
一些简单的线条图标用Path来做,还是很方便的。
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button x:Name="BtnMinimize" ToolTip="Minimize" Style="{StaticResource TitleBtnStyle}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="T_Grid" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Path x:Name="T_Path" Data="M0,0 L8,0" Stroke="Black" StrokeThickness="1"></Path>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger SourceName="T_Grid" Property="IsMouseOver" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="#FFC1C1C1"></Setter>
<Setter TargetName="T_Path" Property="Margin" Value="0,4,0,0"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="BtnMaximize" ToolTip="Maximize" Style="{StaticResource TitleBtnStyle}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="T_Grid" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Rectangle x:Name="T_Rect" Stroke="Black" StrokeThickness="0.5" Height="8" Margin="5,0" Width="8"></Rectangle>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="#FFC1C1C1"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="BtnRestore" ToolTip="Restore" Style="{StaticResource TitleBtnStyle}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="T_Grid" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid >
<Rectangle Stroke="Black" StrokeThickness="0.5" Height="7" Width="7" Margin="2,0,0,2"></Rectangle>
<Rectangle Stroke="Black" StrokeThickness="0.5" Height="7" Width="7" Fill="White" Margin="0,2,2,0"></Rectangle>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="#FFC1C1C1"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="BtnClose" ToolTip="Close" Style="{StaticResource TitleBtnStyle}" Click="BtnClose_OnClick">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="T_Grid" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<Path Data="M0,0 L8,8" Stroke="Black" StrokeThickness="1"></Path>
<Path Data="M8,0 L0,8" Stroke="Black" StrokeThickness="1"></Path>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="LightGray"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="T_Grid" Property="Background" Value="#FFC1C1C1"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
3、窗口 resize 鼠标自由改变窗口大小 (转)
覆写一个OnSourceInitialized方法,在其中添加一个委托
//重写
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
hwndSource.AddHook(new HwndSourceHook(WndProc));
}
} private const int WM_NCHITTEST = 0x0084;
private Point mousePoint = new Point(); //鼠标坐标
private const int ResizeBorderAGWidth = ;//转角宽度
private const int ResizeBorderThickness = ;//边框宽度
/// <summary>
/// 委托方法
/// </summary>
/// <param name="hwnd"></param>
/// <param name="msg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <param name="handled"></param>
/// <returns></returns>
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_NCHITTEST:
mousePoint.X = (lParam.ToInt32() & 0xFFFF);
mousePoint.Y = (lParam.ToInt32() >> );
// 窗口左上角
if (mousePoint.Y - Top <= ResizeBorderAGWidth && mousePoint.X - Left <= ResizeBorderAGWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTTOPLEFT);
}
// 窗口左下角
else if (ActualHeight + Top - mousePoint.Y <= ResizeBorderAGWidth && mousePoint.X - Left <= ResizeBorderAGWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOMLEFT);
}
// 窗口右上角
else if (mousePoint.Y - Top <= ResizeBorderAGWidth && ActualWidth + Left - mousePoint.X <= ResizeBorderAGWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTTOPRIGHT);
}
// 窗口右下角
else if (ActualWidth + Left - mousePoint.X <= ResizeBorderAGWidth && ActualHeight + Top - mousePoint.Y <= ResizeBorderAGWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOMRIGHT);
}
// 窗口左侧
else if (mousePoint.X - Left <= ResizeBorderThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTLEFT);
}
// 窗口右侧
else if (ActualWidth + Left - mousePoint.X <= ResizeBorderThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTRIGHT);
}
// 窗口上方
else if (mousePoint.Y - Top <= ResizeBorderThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTTOP);
}
// 窗口下方
else if (ActualHeight + Top - mousePoint.Y <= ResizeBorderThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOM);
}
else // 窗口移动
{
//handled = true;
//return new IntPtr((int)HitTest.HTCAPTION);
return IntPtr.Zero;
}
} return IntPtr.Zero;
}
用到的枚举列表类:
public enum HitTest : int
{
HTERROR = -,
HTTRANSPARENT = -,
HTNOWHERE = ,
HTCLIENT = ,
HTCAPTION = ,
HTSYSMENU = ,
HTGROWBOX = ,
HTSIZE = HTGROWBOX,
HTMENU = ,
HTHSCROLL = ,
HTVSCROLL = ,
HTMINBUTTON = ,
HTMAXBUTTON = ,
HTLEFT = ,
HTRIGHT = ,
HTTOP = ,
HTTOPLEFT = ,
HTTOPRIGHT = ,
HTBOTTOM = ,
HTBOTTOMLEFT = ,
HTBOTTOMRIGHT = ,
HTBORDER = ,
HTREDUCE = HTMINBUTTON,
HTZOOM = HTMAXBUTTON,
HTSIZEFIRST = HTLEFT,
HTSIZELAST = HTBOTTOMRIGHT,
HTOBJECT = ,
HTCLOSE = ,
HTHELP = ,
}
窗口拖动
1、在界面上对布局元素如Grid,添加委托事件: MouseLeftButtonDown="UIElement_OnMouseLeftButtonDown"
2、委托方法中处理一下就行了:
private void UIElement_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState==MouseButtonState.Pressed)
{
this.DragMove();
}
}
WPF 自定义窗口的更多相关文章
- WPF自定义窗口基类
WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...
- WPF自学入门(九)WPF自定义窗口基类
今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...
- wpf 自定义窗口,最大化时覆盖任务栏解决方案
原文:wpf 自定义窗口,最大化时覆盖任务栏解决方案 相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 W ...
- WPF自定义窗口最大化显示任务栏
原文:WPF自定义窗口最大化显示任务栏 当我们要自定义WPF窗口样式时,通常是采用设计窗口的属性 WindowStyle="None" ,然后为窗口自定义放大,缩小,关闭按钮的样式 ...
- wpf 自定义窗口,最大化时不覆盖任务栏
相信很多人使用wpf时会选择自定义美观的窗口,因此会设置WindowStyle="None" 取消自带的标题栏.但这样使用 WindowState="Maximized& ...
- WPF 自定义窗口标题栏
1.建一个WPF资源词典,在其中定义窗口样式,并在App.xaml中指定其为程序资源 2.写一个继续自windows的类,并指定这个类的Style为第一步资源里的样式 3.新建窗口时,分别把xaml文 ...
- WPF自定义窗口(Windows Server 2012 Style)
先上图 新建CustomControl,名:HeaderedWindow Themes\Generic.aml文件夹下加入 笔刷,转换器 <SolidColorBrush x:Key=" ...
- WPF 自定义窗口关闭按钮
关闭图标设计主要涉及主要知识点: 1.Path,通过Path来画线.当然一般水平.竖直也是可以用Rectangle/Border之类的替代 一些简单的线条图标用Path来做,还是很方便的. 2.简单的 ...
- WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
WPF 自定义窗口样式有多种方式,不过基本核心实现都是在修改 Win32 窗口样式.然而,Windows 上的应用就应该有 Windows 应用的样子嘛,在保证自定义的同时也能与其他窗口样式保持一致当 ...
随机推荐
- salesforce 零基础学习(五十四)常见异常友好消息提示
异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_con ...
- 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)
在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...
- nginx源码分析之hash的实现
nginx实现了自己的hash数据结构,正如数据结构中讲述的那样,nginx用开放链表法解决冲突,不过不同的是一旦一个hash表被初始化后就不会被修改,即插入和删除,只进行查询操作,所以nginx通过 ...
- CSS3与页面布局学习总结(二)——Box Model、边距折叠、内联与块标签、CSSReset
一.盒子模型(Box Model) 盒子模型也有人称为框模型,HTML中的多数元素都会在浏览器中生成一个矩形的区域,每个区域包含四个组成部分,从外向内依次是:外边距(Margin).边框(Border ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(二)
马尔可夫模型与隐马尔可夫模型 作者:白宁超 2016年7月11日15:31:11 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无什么用场.直到学习自然语 ...
- Anliven - To-Do List
2016 - December Name Type Start Deadline Status Output Comments Last Review SQL必知必会(第4版) Book 2016-1 ...
- Node基础篇(文件操作)
文件操作 相关模块 Node内核提供了很多与文件操作相关的模块,每个模块都提供了一些最基本的操作API,在NPM中也有社区提供的功能包 fs: 基础的文件操作 API path: 提供和路径相关的操作 ...
- 深入学习jQuery描述文本内容的3个方法
× 目录 [1]html() [2]text() [3]val()[4]总结 前面的话 在javascript中,描述元素内容有5个属性,分别是innerHTML.outerHTML.innerTex ...
- WCF备忘录一:服务端实例的生命周期
示例代码下载地址:WCFDemo1Day 概述 客户端向WCF服务发出请求后,服务端会实例化一个Service对象(实现了契约接口的对象)用来处理请求,实例化Service对象以及维护其生命周期的方式 ...
- C语言中的结构体
用户自己建立自己的结构体类型 1. 定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...