DMSkin.WPF
DMSkinComplexWindow.cs
using DMSkin.Core.WIN32;
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
namespace DMSkin.WPF
{
///
/// 双层双体 - 在Windows 7上面 系统按钮区域还存在一些BUG。
///
public partial clast DMSkinComplexWindow : Window
{
#region 初始化
public DMSkinComplexWindow()
{
InitializeWindowStyle();
//绑定窗体操作函数
SourceInitialized += MainWindow_SourceInitialized;
StateChanged += MainWindow_StateChanged;
IsVisibleChanged += MainWindow_IsVisibleChanged;
MouseLeftButtonDown += MainWindow_MouseLeftButtonDown;
Closed += MainWindow_Closed;
SizeChanged += MainWindow_SizeChanged;
LocationChanged += MainWindow_LocationChanged;
}
#endregion
#region 切换单双窗口模式
///
/// 加载双层窗口的样式
///
private void InitializeWindowStyle()
{
_shadowWindow = new ShadowWindow();
Dispatcher.BeginInvoke(new Action(x =>
{
Thread.Sleep(70);
_shadowWindow.Left = this.Left - 30;
_shadowWindow.Top = this.Top - 30;
ShadowWindowVisibility(true);//初始化
Owner = _shadowWindow;//绑定阴影窗体
Activate();
}), DispatcherPriority.ApplicationIdle, this);
}
#endregion
#region 阴影窗体
///
/// 显示或者隐藏阴影
///
private void ShadowWindowVisibility(bool show)
{
if (show)
{
_shadowWindow.Show();
}
else
{
_shadowWindow.Hide();
}
}
///
/// 阴影窗体
///
ShadowWindow _shadowWindow = null;
///
/// 窗体关闭时 关闭阴影窗口
///
private void MainWindow_Closed(object sender, EventArgs e)
{
if (_shadowWindow != null)
{
_shadowWindow.Close();
}
}
///
/// 主窗体修改尺寸时 更新阴影窗口尺寸
///
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_shadowWindow != null)
{
_shadowWindow.Width = Width + 60;
_shadowWindow.Height = Height + 60;
}
}
///
/// 窗体移动坐标时 更新阴影窗口坐标
///
private void MainWindow_LocationChanged(object sender, EventArgs e)
{
if (_shadowWindow != null)
{
_shadowWindow.Left = Left - 30;
_shadowWindow.Top = Top - 30;
}
}
#endregion
#region 系统函数
IntPtr Handle = IntPtr.Zero;
void MainWindow_SourceInitialized(object sender, EventArgs e)
{
Handle = new WindowInteropHelper(this).Handle;
HwndSource source = HwndSource.FromHwnd(Handle);
if (source == null)
{ throw new Exception("Cannot get HwndSource instance."); }
source.AddHook(new HwndSourceHook(this.WndProc));
}
private void WmNCCalcSize(IntPtr LParam)
{
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowmessages/wm_nccalcsize.asp
// http://groups.google.pl/groups?selm=OnRNaGfDEHA.1600%40tk2msftngp13.phx.gbl
var r = (RECT)Marshal.PtrToStructure(LParam, typeof(RECT));
//var max = MinMaxState == FormWindowState.Maximized;
if (WindowState == WindowState.Maximized)
{
var x = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXSIZEFRAME);
var y = NativeMethods.GetSystemMetrics(NativeConstants.SM_CYSIZEFRAME);
var p = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXPADDEDBORDER);
var w = x + p;
var h = y + p;
r.left += w;
r.top += h;
r.right -= w;
r.bottom -= h;
var appBarData = new APPBARDATA();
appBarData.cbSize = Marshal.SizeOf(typeof(APPBARDATA));
var autohide = (NativeMethods.SHAppBarMessage(NativeConstants.ABM_GETSTATE, ref appBarData) & NativeConstants.ABS_AUTOHIDE) != 0;
if (autohide) r.bottom -= 1;
Marshal.StructureToPtr(r, LParam, true);
}
}
//四个坐标
POINTAPI[] poin = new POINTAPI[4];
//是否正在绘制边角
bool ReWindowState = false;
//重设主窗口裁剪区域
public void ReWindow()
{
if (ReWindowState)//已经在绘制过程
{
return;
}
ReWindowState = true;
Task.Factory.StartNew(() =>
{
//150毫秒延迟,并且150毫秒内不会重复触发多次
Thread.Sleep(150);
//让窗体不被裁剪
poin[3].x = (int)ActualWidth;
poin[1].y = (int)ActualHeight;
poin[2].x = (int)ActualWidth;
poin[2].y = (int)ActualHeight;
IntPtr hRgn = NativeMethods.CreatePolygonRgn(ref poin[0], 4, 0);
NativeMethods.SetWindowRgn(Handle, hRgn, true);
ReWindowState = false;
//("触发时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
});
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
//WM_NCCALCSIZE
case (int)WindowMessages.WM_NCCALCSIZE:
//WmNCCalcSize(lParam);
ReWindow();
handled = true;
break;
///重绘 非客户区
case (int)WindowMessages.WM_NCPAINT:
// Here should all our painting occur, but...
handled = true;
return NativeConstants.TRUE;
case (int)WindowMessages.WM_NCACTIVATE:
// ... WM_NCACTIVATE does some painting directly
// without bothering with WM_NCPAINT ...
bool active = (wParam == NativeConstants.TRUE);
if (WindowState != WindowState.Minimized)
{
handled = true;
return NativeConstants.TRUE;
}
break;
//------------------
//if (wParam == (IntPtr)Win32.WM_TRUE)
//{
// handled = true;
//}
case (int)WindowMessages.WM_NCLBUTTONDOWN:
if (wParam.ToInt32() == (int)HitTest.HTCLOSE ||
wParam.ToInt32() == (int)HitTest.HTMAXBUTTON ||
wParam.ToInt32() == (int)HitTest.HTMINBUTTON ||
wParam.ToInt32() == (int)HitTest.HTHELP)
{
NativeMethods.SendMessage(Handle, (int)WindowMessages.WM_NCPAINT, IntPtr.Zero, IntPtr.Zero);
handled = true;
}
break;
case (int)WindowMessages.WM_NCUAHDRAWCAPTION:
case (int)WindowMessages.WM_NCUAHDRAWFRAME:
handled = true;
break;
//获取窗口的最大化最小化信息
//case (int)WindowMessages.WM_GETMINMAXINFO:
// WmGetMinMaxInfo(hwnd, lParam);
// handled = true;
// break;
//窗口拉伸 还有DPI BUG
//case (int)WindowMessages.WM_NCHITTEST:
// return WmNCHitTest(lParam, ref handled);
}
return IntPtr.Zero;
}
///
/// 圆角拖动大小
///
private readonly int cornerWidth = 8;
///
/// 拉伸鼠标坐标
///
private Point mousePoint = new Point();
private IntPtr WmNCHitTest(IntPtr lParam, ref bool handled)
{
this.mousePoint.X = (int)(short)(lParam.ToInt32() & 0xFFFF);
this.mousePoint.Y = (int)(short)(lParam.ToInt32() >> 16);
if (ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip)
{
handled = true;
//if (Math.Abs(this.mousePoint.Y - this.Top)