之前写了一个支持尺寸变换的无边框窗体的一个基窗体,代码如下:

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】无边框窗体的更多相关文章

  1. wpf无边框窗体移动和大小调整

    原文:wpf无边框窗体移动和大小调整   using System; using System.Windows; using System.Windows.Interop; namespace Wpf ...

  2. WPFの无边框窗体以及控件的移动

    对于WPF,一旦隐藏了标题栏,就无法移动,这时候需要重写移动方法,下面列举常见的三种方式方式. 方式一:重写OnMouseLeftButtonDown protected override void ...

  3. 【转】【WPF】 WPF 调用API修改窗体风格实现真正的无边框窗体

    WPF中设置无边框窗体似乎是要将WindowStyle设置为None,AllowTransparency=true,这样才能达到WinForm中无边框窗体的样式.但是AllowTransparency ...

  4. 01.WPF中制作无边框窗体

    [引用:]http://blog.csdn.net/johnsuna/article/details/1893319   众所周知,在WinForm中,如果要制作一个无边框窗体,可以将窗体的FormB ...

  5. C# .net WPF无边框移动窗体

    转自 http://download.csdn.net/detail/xiang348352/3095084 WPF无边框移动窗体,先在<Window>里添加 MouseLeftButto ...

  6. WPF中制作无边框窗体

    原文:WPF中制作无边框窗体 众所周知,在WinForm中,如果要制作一个无边框窗体,可以将窗体的FormBorderStyle属性设置为None来完成.如果要制作成异形窗体,则需要使用图片或者使用G ...

  7. WPF 调用API修改窗体风格实现真正的无边框窗体

    原文:WPF 调用API修改窗体风格实现真正的无边框窗体 WPF中设置无边框窗体似乎是要将WindowStyle设置为None,AllowTransparency=true,这样才能达到WinForm ...

  8. WPF无边框移动窗体

    WPF无边框移动窗体,先在<Window>里添加 MouseLeftButtonDown=”Window_MouseLeftButtonDown” 然后导航到事件,在事件里添加 if (e ...

  9. 利用WPF创建含多种交互特性的无边框窗体

    咳咳,标题一口气读下来确实有点累,让我先解释一下.另外文章底部有演示程序的下载. 本文介绍利用WPF创建一个含有以下特性的窗口: 有窗口阴影,比如QQ窗口外围只有几像素的阴影: 支持透明且无边框,为了 ...

随机推荐

  1. Office 365 - SharePoint Tips & Tricks

    1. Recycle Bin 地址: //管理员 /_layouts/15/AdminRecycleBin.aspx //普通用户 /_layouts/15/RecycleBin.aspx 2.

  2. 地理数据可视化:Simple,Not Easy

    如果要给2015年的地理信息行业打一个标签,地理大数据一定是其中之一.在信息技术飞速发展的今天,“大数据”作为一种潮流铺天盖地的席卷了各行各业,从央视的春运迁徙图到旅游热点预测,从大数据工程师奇货可居 ...

  3. android ButterKnife 解决重复findViewById

    简介: 程序员都是懒惰的,不想写一大堆像下面这样的代码 class ExampleActivity extends Activity { TextView title; TextView subtit ...

  4. android学习笔记 对话框合集

    package com.zhangbz.dialog; import android.app.Activity; import android.app.AlertDialog; import andr ...

  5. 傅里叶:有关FFT,DFT与蝴蝶操作(转 重要!!!!重要!!!!真的很重要!!!!)

    转载地址:http://blog.renren.com/share/408963653/15068964503(作者 :  徐可扬) 有没有!!! 其实我感觉这个学期算法最难最搞不懂的绝对不是动态规划 ...

  6. 邮件群发工具(C#版)

    引言 经常会参与组织一些社区活动,涉及到和不同的人进行交流,微信当然是必须的,同样邮件也是一种不可或缺的方式. 一般群发的邮件不是很友好,如果是一对一的,收到邮件的人是不是会比较重视,而且还有他的名字 ...

  7. Python 虚拟环境:Virtualenv

    安装sudo yum install python-virtualenv 使用方法 virtualenv [虚拟环境名称] 如,创建**ENV**的虚拟环境 virtualenv ENV 默认情况下, ...

  8. GDI学习之俄罗斯方块

    做个玩玩 public Form1() { InitializeComponent(); } #region 定义砖块int[i,j,y,x] Tricks:i为那块砖,j为状态,y为列,x为行 pr ...

  9. 无法将匿名方法转换为System.Delegate

    在WinForm中,不允许非UI线程访问UI,如果非UI线程需要跨线程调用UI控件,通常的解决办法是使用Control类中的Invoke方法,传递给该方法一个委托和委托调用的参数列表(params [ ...

  10. c# 进程间通信 IPC

    最近在调试一个算法,想通过改变算法的参数看看结果有什么变化. 碰到一个麻烦的事情是,从磁盘加载.构建数据需要15分钟.这就比较讨厌了,也就是说我每次调一个参数前都要等15分钟启动时间? 于是我就想,能 ...