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

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. IO流-输入输出

    java的I/O技术可以将数据保存到文本.二进制.ZIP压缩文件中,下面来说说一些基本的常识(今天只讲理论).先来说说流,何为流?“流就是一组有序的数据序列,根据操作的类型,可以分为输入(Input) ...

  2. 浅谈RSA加密算法

    一.什么是非对称加密 1.加密的密钥与加密的密钥不相同,这样的加密算法称之为非对称加密 2.密钥分为:公钥,私钥  公钥:可以对外给任何人的加密和解密的密码,是公开的 私钥:通过私钥可以生成公钥,但从 ...

  3. Spring(四)Bean注入方试

    一.构造方法注入 定义:通过构造函数来完成依赖关系的设定 优缺点: 在构造对象的同时,完成依赖关系的建立 如果关联的对象很多,那和不得不在构造方法上加入过多的参数 基中有index:如果指定索引从0开 ...

  4. Android源码分析之Message

    准备开始写点东西,算是对自己阅读源码的一个记录/笔记,也希望能对同样感兴趣的人有所帮助,希望能坚持下去,加油. 在Android的开发中,我们经常用到Handler.postXXX方法,或者View. ...

  5. win8下出现安装sql2012 正在启动操作系统功能"NetFx3"

    今天上午装win8系统,发现在装sql server 2012的时候,一直停在"正在启动操作系统功能"NetFx3""不动了,在网上找了下相关的资料,发现原来N ...

  6. Eclipse 一直提示 loading descriptor for 的解决方法

    启动eclipse之后,进行相关操作时,弹出界面,提示:loading descriptor for xxx 解决方法: 在Eclipse左侧的Project Explorer 最右上角有一个小钮,鼠 ...

  7. PHP模拟发送POST请求之三、用Telnet和fsockopen()模拟发送POST信息

    了解完了HTTP头信息和URL信息的具体内容,我们开始尝试自己动手写一段头信息发送到服务器.Windows内置命令Telnet可以帮助我们发送简单的HTTP请求. 并且TELNET是一个特别灵活的工具 ...

  8. PHP中IP地址与整型数字互相转换详解

    这篇文章主要介绍了PHP中IP地址与整型数字互相转换详解,本文介绍了使用PHP函数ip2long与long2ip的使用,以及它们的BUG介绍,最后给出自己写的两个算法,需要的朋友可以参考下 IP转换成 ...

  9. Android 滑动效果入门篇(一)—— ViewFlipper

    ViewFilpper 是Android官方提供的一个View容器类,继承于ViewAnimator类,用于实现页面切换,也可以设定时间间隔,让它自动播放.又ViewAnimator继承至于Frame ...

  10. codeforces C. Triangle

    C. Triangle time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...