【WPF】无边框窗体
之前写了一个支持尺寸变换的无边框窗体的一个基窗体,代码如下:
public class LBaseWindow : Window
{
/// <summary>
/// 基窗体
/// </summary>
public LBaseWindow()
{
Initialize();
}
/// <summary>
/// 是否显示任务栏,如果任务栏不显示,则窗体覆盖整个屏幕
/// </summary>
public Visibility TaskbarVisibility
{
get
{
return _taskbarVisibility;
}
set
{
if (_taskbarVisibility != value)
{
_taskbarVisibility = value;
SetTaskbarChange();
}
}
}
/// <summary>
/// 源数据初始化
/// </summary>
/// <param name="e"></param>
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
hwndSource.AddHook(new HwndSourceHook(this.WndProc));
_handle = hwndSource.Handle;
}
}
/// <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)
{
#region[窗体大小修改]
case WM_NCHITTEST:
this.mousePoint.X = (lParam.ToInt32() & 0xFFFF);
this.mousePoint.Y = (lParam.ToInt32() >> );
double left = this.WindowState == System.Windows.WindowState.Maximized ? : this.Left;
double top = this.WindowState == System.Windows.WindowState.Maximized ? : this.Top;
// 窗口左上角
if (this.mousePoint.Y - this.Top <= this.agWidth
&& this.mousePoint.X - left <= this.agWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTTOPLEFT);
}
// 窗口左下角
else if (this.ActualHeight + top - this.mousePoint.Y <= this.agWidth
&& this.mousePoint.X - left <= this.agWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOMLEFT);
}
// 窗口右上角
else if (this.mousePoint.Y - top <= this.agWidth
&& this.ActualWidth + left - this.mousePoint.X <= this.agWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTTOPRIGHT);
}
// 窗口右下角
else if (this.ActualWidth + left - this.mousePoint.X <= this.agWidth
&& this.ActualHeight + top - this.mousePoint.Y <= this.agWidth)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOMRIGHT);
}
// 窗口左侧
else if (this.mousePoint.X - left <= this.bThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTLEFT);
}
// 窗口右侧
else if (this.ActualWidth + left - this.mousePoint.X <= this.bThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTRIGHT);
}
// 窗口上方
else if (this.mousePoint.Y - top <= this.bThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTTOP);
}
// 窗口下方
else if (this.ActualHeight + top - this.mousePoint.Y <= this.bThickness)
{
handled = true;
return new IntPtr((int)HitTest.HTBOTTOM);
}
else
{
return IntPtr.Zero;
//handled = true;
//return new IntPtr((int)HitTest.HTCAPTION);
}
#endregion
#region[窗体最大化控制]
case WM_GETMINMAXINFO:
WMGetMinMaxInfo(hwnd, lParam);
handled = true;
break;
#endregion
}
return IntPtr.Zero;
}
/// <summary>
/// 控制窗体最大化
/// </summary>
/// <param name="hwnd"></param>
/// <param name="lParam"></param>
protected virtual void WMGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
// Adjust the maximized size and position to fit the work area of the correct monitor
int MONITOR_DEFAULTTONEAREST = 0x00000002;
System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor != System.IntPtr.Zero)
{
MONITORINFO monitorInfo = new MONITORINFO();
GetMonitorInfo(monitor, monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
RECT rcMonitorArea = monitorInfo.rcMonitor;
if (TaskbarVisibility == System.Windows.Visibility.Visible)
{
mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);
mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
}
else
{
mmi.ptMaxPosition.x = ;
mmi.ptMaxPosition.y = ;
mmi.ptMaxSize.x = rcMonitorArea.right;
mmi.ptMaxSize.y = rcMonitorArea.bottom;
}
}
Marshal.StructureToPtr(mmi, lParam, true);
}
/// <summary>
/// 设置修改任务栏变更
/// </summary>
private void SetTaskbarChange()
{
WindowState state = this.WindowState;
this.Opacity = ;
this.WindowState = System.Windows.WindowState.Minimized;
this.WindowState = state;
this.Opacity = ;
}
/// <summary>
/// 窗体阴影半径修改
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ShadowRadiusChanged()
{
ControlTemplate template = (ControlTemplate)this.Resources["WindowTemplate"];
if (template == null) return;
Grid grid = (Grid)template.FindName("ClientGrid", this);
if (grid == null) return;
if (this.WindowState != System.Windows.WindowState.Maximized)
grid.Margin = new Thickness();
else
grid.Margin = new Thickness();
if (this.Opacity == )
this.Opacity = ;
}
/// <summary>
/// 初始化
/// </summary>
private void Initialize()
{
this.Opacity = ;
this.Loaded += (sender, e) => InitializeEvent();
this.ContentRendered += (sender, e) => ShadowRadiusChanged();
this.SizeChanged += (sender, e) => ShadowRadiusChanged();
}
/// <summary>
/// 初始化事件
/// </summary>
private void InitializeEvent()
{
ResourceDictionary resource = new ResourceDictionary();
resource.Source = new Uri(@"pack://application:,,,/DepthView;component/View/Styles/WindowStyle.xaml", UriKind.RelativeOrAbsolute);
this.Resources.MergedDictionaries.Add(resource);
this.Style = (Style)this.Resources["WindowStyleKey"];
} private const int WM_SYSCOMMAND = 0x112;
private const int WM_GETMINMAXINFO = 0x0024;
private const int SC_CLOSE = 0xF060;
private const int SC_MINIMIZE = 0xF020;
private const int SC_MAXIMIZE = 0xF030;
private const int WM_NCHITTEST = 0x0084;
private readonly int agWidth = ; //拐角宽度
private readonly int bThickness = ; // 边框宽度
private Point mousePoint = new Point(); //鼠标坐标
private Visibility _taskbarVisibility;
private IntPtr _handle; [DllImport("user32.dll")]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("User32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
/// <summary>
/// </summary>
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
/// <summary>
/// </summary>
public RECT rcMonitor = new RECT();
/// <summary>
/// </summary>
public RECT rcWork = new RECT();
/// <summary>
/// </summary>
public int dwFlags = ;
}
/// <summary>
/// 矩形
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = )]
public struct RECT
{
/// <summary>
/// 左边界坐标
/// </summary>
public int left;
/// <summary>
/// 上边界坐标
/// </summary>
public int top;
/// <summary>
/// 右边界坐标
/// </summary>
public int right;
/// <summary>
/// 下边界坐标
/// </summary>
public int bottom;
}
/// <summary>
/// 窗体大小信息
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
};
/// <summary>
/// POINT aka POINTAPI
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
/// <summary>
/// x coordinate of point.
/// </summary>
public int x;
/// <summary>
/// y coordinate of point.
/// </summary>
public int y; /// <summary>
/// Construct a point of coordinates (x,y).
/// </summary>
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
/// <summary>
/// 鼠标点击信息
/// </summary>
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 = ,
}
}
Xaml:
<ControlTemplate x:Key="WindowTemplate" TargetType="{x:Type Window}">
<Grid x:Name="ClientGrid" Margin="10">
<Border Background="{x:Null}" BorderBrush="{TemplateBinding Background}" BorderThickness="2" CornerRadius="3">
<Border.Effect>
<DropShadowEffect x:Name="shadow" BlurRadius="10" ShadowDepth="0"/>
</Border.Effect>
</Border>
<Border Background="{x:Null}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Margin}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
CornerRadius="3">
<ContentPresenter />
</Border>
</Grid>
</ControlTemplate>
<Style x:Key="WindowStyleKey" TargetType="{x:Type Window}">
<Setter Property="Template" Value="{DynamicResource ResourceKey=WindowTemplate}"></Setter>
</Style>
有一个问题就是全屏是否显示任务栏,目前是采用最小化后最大化,来触发WndProc,这个应该可以改进,后期再看看。
【WPF】无边框窗体的更多相关文章
- wpf无边框窗体移动和大小调整
原文:wpf无边框窗体移动和大小调整 using System; using System.Windows; using System.Windows.Interop; namespace Wpf ...
- WPFの无边框窗体以及控件的移动
对于WPF,一旦隐藏了标题栏,就无法移动,这时候需要重写移动方法,下面列举常见的三种方式方式. 方式一:重写OnMouseLeftButtonDown protected override void ...
- 【转】【WPF】 WPF 调用API修改窗体风格实现真正的无边框窗体
WPF中设置无边框窗体似乎是要将WindowStyle设置为None,AllowTransparency=true,这样才能达到WinForm中无边框窗体的样式.但是AllowTransparency ...
- 01.WPF中制作无边框窗体
[引用:]http://blog.csdn.net/johnsuna/article/details/1893319 众所周知,在WinForm中,如果要制作一个无边框窗体,可以将窗体的FormB ...
- C# .net WPF无边框移动窗体
转自 http://download.csdn.net/detail/xiang348352/3095084 WPF无边框移动窗体,先在<Window>里添加 MouseLeftButto ...
- WPF中制作无边框窗体
原文:WPF中制作无边框窗体 众所周知,在WinForm中,如果要制作一个无边框窗体,可以将窗体的FormBorderStyle属性设置为None来完成.如果要制作成异形窗体,则需要使用图片或者使用G ...
- WPF 调用API修改窗体风格实现真正的无边框窗体
原文:WPF 调用API修改窗体风格实现真正的无边框窗体 WPF中设置无边框窗体似乎是要将WindowStyle设置为None,AllowTransparency=true,这样才能达到WinForm ...
- WPF无边框移动窗体
WPF无边框移动窗体,先在<Window>里添加 MouseLeftButtonDown=”Window_MouseLeftButtonDown” 然后导航到事件,在事件里添加 if (e ...
- 利用WPF创建含多种交互特性的无边框窗体
咳咳,标题一口气读下来确实有点累,让我先解释一下.另外文章底部有演示程序的下载. 本文介绍利用WPF创建一个含有以下特性的窗口: 有窗口阴影,比如QQ窗口外围只有几像素的阴影: 支持透明且无边框,为了 ...
随机推荐
- Spark GraphX学习资料
<Spark GraphX 大规模图计算和图挖掘> http://book.51cto.com/art/201408/450049.htm http://www.csdn.net/arti ...
- 2015第18本:从0到1,ZERO to ONE, Notes on startups, or how to build the future
<从0到1>中文版的副标题是”开创商业与未来的秘密“,题目大得吓人,英文副标题就谨慎了许多:Notes on startups, or how to build the future. 全 ...
- Mac 以太网连接 报无效的服务器地址 BasicIPv6ValidationError
Mac 以太网连接 报无效的服务器地址 BasicIPv6ValidationError 用Mac这么久,一直是用WiFi连接网络,没搞过以太网连接,我也是醉了 显然 Mac 不能像 Windows ...
- hadoop2.6完全分布式安装HBase1.1
本文出自:http://wuyudong.com/archives/119 对于全分布式的HBase安装,需要通过hbase-site.xml文档来配置本机的HBase特性,由于各个HBase之间通过 ...
- Fragments之间的交互(实现参数传递)
Fragments之间的交互(实现参数传递) 日常开发中,通常Fragments之间可能需要交互,比如基于用户事件改变Fragment的内容.所有Fragment之间的交互需要通过他们关联的Activ ...
- 弃用的同步get和post请求
#import "ViewController.h" #import "Header.h" @interface ViewController () <N ...
- 网络开始---多线程---NSThread-02-线程状态(了解)(三)
#import "HMViewController.h" @interface HMViewController () @property (nonatomic, strong) ...
- 更轻量的 View Controllers
iew controllers 通常是 iOS 项目中最大的文件,并且它们包含了许多不必要的代码.所以 View controllers 中的代码几乎总是复用率最低的.我们将会看到给 view con ...
- JRebel for Android 1.0发布!
什么是JRebel for Android? 一款Android studio插件——允许你修改正在运行中的应用程序,而且不必重新部署或重启.支持所有运行Android 4.0及以上版本的手机和平板. ...
- LightSpeed使用指南
LightSpeed 是一个最高性能的 .NET 领域建模和 O/R 映射框架,第一级别的 LINQ 支持.Visual Studio 2008/2010 设计器集成,是一个著名的高性能框架.[注:收 ...