我找到了三篇文章,并且测试了一下,最佳解决因设置无边框窗体导致的动画丢失解决方案-
【1】stackoverflow-Borderless Window Using Areo Snap, Shadow, Minimize Animation, and Shake
【2】stackoverflow-FormBorderStyle.None removes the native open effect of windows 8
【3】stackoverflow-Use windows animations on borderless form
以下为伪代码
case WM_NCCALCSIZE: {
if (是否已经打开阴影---->>m_aeroEnabled) {
【return 0;】 //---->> m.Result = IntPtr.Zero
} else {
【return DefWindowProc(hwnd, msg, wparam, lparam);】 //---->> DefWndProc(m);
}
}
此方法仍需要DWMAPI来绘制阴影,其次由于窗体没有了标题栏(都属于边框),需要自己重绘一个标题栏
正好SunnyUI需要自行重绘,免去了设置 FormBorderStyle = FormBorderStyle.None;
时造成不必要动画丢失的问题
经我测试,以下VB.NET代码没有问题,可以保证 阴影开启、动画保留、无闪烁
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case Win32.User.WM_ERASEBKGND
m.Result = IntPtr.Zero
Case Win32.User.WM_NCCALCSIZE
If m_aeroEnabled Then
m.Result = IntPtr.Zero
Else
DefWndProc(m)'如需更深层定义可重写该函数
End If
Case Else
MyBase.WndProc(m)
End Select
'''------拖拽调节大小
If m.Msg = Win32.User.WM_NCHITTEST AndAlso WindowState = FormWindowState.Normal Then
Dim vPoint As Point = New Point(MousePosition.X, MousePosition.Y)
vPoint = PointToClient(vPoint)
Dim dragSize As Integer = 5
If vPoint.X <= dragSize Then
If vPoint.Y <= dragSize Then
m.Result = CType(Win32.User.HTTOPLEFT, IntPtr)
ElseIf vPoint.Y >= ClientSize.Height - dragSize Then
m.Result = CType(Win32.User.HTBOTTOMLEFT, IntPtr)
Else
m.Result = CType(Win32.User.HTLEFT, IntPtr)
End If
ElseIf vPoint.X >= ClientSize.Width - dragSize Then
If vPoint.Y <= dragSize Then
m.Result = CType(Win32.User.HTTOPRIGHT, IntPtr)
ElseIf vPoint.Y >= ClientSize.Height - dragSize Then
m.Result = CType(Win32.User.HTBOTTOMRIGHT, IntPtr)
Else
m.Result = CType(Win32.User.HTRIGHT, IntPtr)
End If
ElseIf vPoint.Y <= dragSize Then
m.Result = CType(Win32.User.HTTOP, IntPtr)
ElseIf vPoint.Y >= ClientSize.Height - dragSize Then
m.Result = CType(Win32.User.HTBOTTOM, IntPtr)
End If
current_size = Size
End If
'''------拖拽调节大小
If m.Msg = Win32.User.WM_NCPAINT AndAlso m_aeroEnabled Then
Dim v = 2
Win32.Dwm.DwmSetWindowAttribute(Handle, 2, v, 4)
Dim margins As Win32.Dwm.MARGINS = New Win32.Dwm.MARGINS() With {
.bottomHeight = 1,
.leftWidth = 1,
.rightWidth = 1,
.topHeight = 1
}
Win32.Dwm.DwmExtendFrameIntoClientArea(Handle, margins)
End If
End Sub
代码转换地址:https://converter.telerik.com/
我追求动画的初衷并不是为了多美观,而是尽量追求在视觉上不显得突兀,如QQ、微信等尚未适配原生API,而网易云音乐完美的保留了几乎所有的原生窗体特性(之前版本没有保留)
showdialog的窗体也可以通过继承主窗体来实现原生样式,而且就目前的UIstyle,个人觉得不够深度自定义(毕竟您希望如果是高度自定义请自行改源码),不过网上为了扁平化上循环draw png的都有,就是为了搞个阴影,很多人都不知道有dwmapi,且绝大多数需要自行设置标题栏,如果您能够解决,我相信任何人更愿意去nuget download,而不是clone code,sunnyUI是后来者,应该取cskin的优点而不是保留无边框
其次我在重写最大化最小化和还原上遇到了没有对应事件的问题,重写标题栏虽然没有必要,但是至少弄个图片上去吧,三个按钮可选择添加三种状态的图片,可以自定义按钮尺寸,没有就用默认的,因为在我调整完全局配色时发现右上角三个按钮底色还是蓝色,如果不愿重写,能否留出个接口以便我自行重写标题栏?非常感谢
另外CSkin的关键技术今天用de4dot反编译出来了:大量的重写wndproc,而不是gdi,说明是大量重写不是重绘,能够省下很多性能,而且重写底层更容易实现,而不是重绘了发现没变化,只能启用userpaint,然后还得写CreateParams来屏蔽闪烁。不过sunnyUI现在已经很不错了,win32的DeviceIoControl类型能写对的全网都没几个人,您类型写对了,我今天测试发现已经可以加载驱动了,希望能够改进相关功能。