窗体边框自绘问题,快崩溃了
想要对窗体的边框(非客户区)进行自绘制,替换系统的默认绘制,比如对标题栏和最大化最小化关闭等按钮进行自定义外观和大小
网上能查到的通常的做法都是把窗体设为无边框FormBorderStyle = FormBorderStyle.None,然后在客户区绘制模拟边框,只需重载OnPaint就可以,但这种做法有个严重的缺陷就是设成无边框后,窗体的实际客户区和窗体的大小是一致的,也就是看上去客户区在中间,但往其中放入一个控件,把控件的Dock设成Fill看看,是不是控件把整个的窗体都遮住了?这是因为在客户区重绘只是欺骗了用户的肉眼,系统本身并不认为你画的边框就真的是边框,系统认为所有的内容都是客户区的内容,而且这种解决方法没法实现系统菜单(点击窗体左上角的图标显示的菜单),所以这种解决方法是不完善的。
后来在这种方法的基础上找到第二种方法,就是重载WndProc,对WM_NCCALCSIZE消息进行处理,修改客户区的大小,告诉系统真正的客户区大小,这样处理后貌似问题都解决了,但发现这样处理后和.net本身的窗口缩放机制不能很好的兼容,比如控件的Anchor属性可以设置4个方向的锚定,一旦设置了右侧和下方的锚定,每次在设计器中把窗口关闭再打开,发现控件的位置都会向左和向上移动,原因就是系统还是把窗体的原边界作为锚定的基准,修改了客户区后导致这个锚定出现错误,最终无法在设计器中对布局进行调整,重载了SetClientSizeCore等方法后也不能解决,最终只能放弃该方法。
后来又找到第三种解决方法,不设置窗体边框为None,直接重载WndProc,对WM_NCPAINT消息进行处理,实现自己的非客户区重绘,但搞了很长时间都没办法把系统的默认绘制完全替换,表面上看上去是替换了,但只要做某些操作(比如点击窗体的最大化最小化),系统本身的按钮就又会显示出来,整个画面被破坏,也就是说虽然自己绘制过程替换了系统的绘制过程,但系统原先绘制按钮的位置系统还是认为是原来的按钮,当鼠标点击上去后,系统又把对应的按钮给显示出来了,这个问题始终没法彻底解决,网上也找不到更详细的描述。
如何完美的解决自定义的边框?要求能够在设计和运行时都和原Form的处理保持一致。