1680 lines
51 KiB
C#
1680 lines
51 KiB
C#
|
/*
|
|||
|
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
|
|||
|
* 自由使用与修改代码;欲将代码用于商业用途的,请先与作者联系。
|
|||
|
* 使用本代码请保留此处信息。作者联系方式:ping3108@163.com, 欢迎进行技术交流
|
|||
|
*/
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Drawing;
|
|||
|
using System.Drawing.Drawing2D;
|
|||
|
using System.Windows.Forms;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
|
|||
|
using MGdu.WinFormUI;
|
|||
|
using MGdu.WinFormUI.MyGraphics;
|
|||
|
using System.Security.Permissions;
|
|||
|
|
|||
|
namespace MGdu.WinFormUI
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// a form that supports custom theme
|
|||
|
/// </summary>
|
|||
|
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
|
|||
|
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
|
|||
|
public partial class GMForm : Form
|
|||
|
{
|
|||
|
|
|||
|
#region private variable
|
|||
|
|
|||
|
ControlBoxManager controlBoxManager;
|
|||
|
GMShadow _shawdowForm;
|
|||
|
Form _lastClosedMdiChild;
|
|||
|
List<Form> _listClosedMdiChild;
|
|||
|
MdiBarController _mdiBarController;
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region mdi event support
|
|||
|
|
|||
|
EventHandler _mdiNewTabButtonClick;
|
|||
|
EventHandler _mdiTabCloseButtonClick;
|
|||
|
EventHandler _mdiBarCreated;
|
|||
|
/// <summary>
|
|||
|
/// 标签新建按钮事件
|
|||
|
/// </summary>
|
|||
|
[Description("标签新建按钮事件")]
|
|||
|
|
|||
|
public event EventHandler MdiNewTabButtonClick
|
|||
|
{
|
|||
|
add
|
|||
|
{
|
|||
|
_mdiNewTabButtonClick = value;
|
|||
|
}
|
|||
|
remove
|
|||
|
{
|
|||
|
_mdiNewTabButtonClick = null;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标签关闭按钮事件
|
|||
|
/// </summary>
|
|||
|
[Description("标签关闭按钮事件")]
|
|||
|
|
|||
|
public event EventHandler MdiTabCloseButtonClick
|
|||
|
{
|
|||
|
add
|
|||
|
{
|
|||
|
_mdiTabCloseButtonClick = value;
|
|||
|
}
|
|||
|
remove
|
|||
|
{
|
|||
|
_mdiTabCloseButtonClick = null;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
///标签创建时事件
|
|||
|
/// </summary>
|
|||
|
[Description("标签创建时事件")]
|
|||
|
|
|||
|
public event EventHandler MdiBarCreated
|
|||
|
{
|
|||
|
add { _mdiBarCreated = value; }
|
|||
|
remove { _mdiBarCreated = null; }
|
|||
|
}
|
|||
|
|
|||
|
private void OnMdiNewTabButtonClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_mdiNewTabButtonClick?.Invoke(sender, e);
|
|||
|
}
|
|||
|
|
|||
|
private void OnMdiTabCloseButtonClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_mdiTabCloseButtonClick?.Invoke(sender, e);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在标签栏创建时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected virtual void OnMdiBarCreated(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_mdiBarCreated?.Invoke(sender, e);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region property
|
|||
|
|
|||
|
#region property private var
|
|||
|
|
|||
|
bool _resizable = true; // not with theme
|
|||
|
Padding _padding = new Padding(0); // not with theme
|
|||
|
|
|||
|
ThemeFormBase _myTheme;
|
|||
|
|
|||
|
#endregion
|
|||
|
/// <summary>
|
|||
|
/// 内边距
|
|||
|
/// </summary>
|
|||
|
|
|||
|
[DefaultValue(typeof(Padding), "0")]
|
|||
|
public new Padding Padding
|
|||
|
{
|
|||
|
get { return _padding; }
|
|||
|
set
|
|||
|
{
|
|||
|
_padding = value;
|
|||
|
base.Padding = new Padding(
|
|||
|
BorderWidth + _padding.Left,
|
|||
|
CaptionHeight + BorderWidth + _padding.Top,
|
|||
|
BorderWidth + _padding.Right,
|
|||
|
BorderWidth + _padding.Bottom);
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 默认内边距
|
|||
|
/// </summary>
|
|||
|
protected override Padding DefaultPadding
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Padding(
|
|||
|
BorderWidth,
|
|||
|
BorderWidth + CaptionHeight,
|
|||
|
BorderWidth,
|
|||
|
BorderWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标题
|
|||
|
/// </summary>
|
|||
|
public override string Text
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return base.Text;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
base.Text = value;
|
|||
|
Invalidate(TextRect);
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 皮肤/主题
|
|||
|
/// </summary>
|
|||
|
[Browsable(false)]
|
|||
|
public ThemeFormBase XTheme
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (_myTheme == null)
|
|||
|
_myTheme = new ThemeFormBase();
|
|||
|
return _myTheme;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
_myTheme = value;
|
|||
|
PrepareForNewTheme();
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region editable gmform properties
|
|||
|
/// <summary>
|
|||
|
/// 是否可拖动改变窗体大小
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("是否可拖动改变窗体大小")]
|
|||
|
[DefaultValue(true)]
|
|||
|
public bool Resizable
|
|||
|
{
|
|||
|
get { return _resizable; }
|
|||
|
set
|
|||
|
{
|
|||
|
_resizable = value;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体边界大小,鼠标移动到该边界将变成指针形状,拖动可改变窗体大小
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("窗体边界大小,鼠标移动到该边界将变成指针形状,拖动可改变窗体大小")]
|
|||
|
[DefaultValue(6)]
|
|||
|
public int SideResizeWidth
|
|||
|
{
|
|||
|
get { return XTheme.SideResizeWidth; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.SideResizeWidth)
|
|||
|
{
|
|||
|
XTheme.SideResizeWidth = value;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体边框大小
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("窗体边框大小")]
|
|||
|
[DefaultValue(6)]
|
|||
|
public int BorderWidth
|
|||
|
{
|
|||
|
get { return XTheme.BorderWidth; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.BorderWidth)
|
|||
|
{
|
|||
|
XTheme.BorderWidth = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标题栏高度
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("标题栏高度")]
|
|||
|
[DefaultValue(30)]
|
|||
|
public int CaptionHeight
|
|||
|
{
|
|||
|
get { return XTheme.CaptionHeight; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.CaptionHeight)
|
|||
|
{
|
|||
|
XTheme.CaptionHeight = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
///窗体圆角程度
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[DefaultValue(8)]
|
|||
|
[Description("窗体圆角程度")]
|
|||
|
public int Radius
|
|||
|
{
|
|||
|
get { return XTheme.Radius; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.Radius)
|
|||
|
{
|
|||
|
XTheme.Radius = (value < 0 ? 0 : value);
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体圆角样式
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[DefaultValue(typeof(RoundStyle), "2")]
|
|||
|
[Description("窗体圆角样式")]
|
|||
|
public RoundStyle Round
|
|||
|
{
|
|||
|
get { return XTheme.RoundedStyle; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.RoundedStyle)
|
|||
|
{
|
|||
|
XTheme.RoundedStyle = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 控制按钮相对于右上角的偏移量
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("控制按钮相对于右上角的偏移量")]
|
|||
|
[DefaultValue(typeof(Point), "8, 8")]
|
|||
|
public Point ControlBoxOffset
|
|||
|
{
|
|||
|
get { return XTheme.ControlBoxOffset; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ControlBoxOffset = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 关闭/最大化/最小化按钮之间的距离,可以设置成负值使它们重叠
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("关闭/最大化/最小化按钮之间的距离,可以设置成负值使它们重叠")]
|
|||
|
[DefaultValue(0)]
|
|||
|
public int ControlBoxSpace
|
|||
|
{
|
|||
|
get { return XTheme.ControlBoxSpace; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ControlBoxSpace = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标题栏图标尺寸
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("标题栏图标尺寸")]
|
|||
|
[DefaultValue(typeof(Size), "16,16")]
|
|||
|
public Size IconSize
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (ShowIcon)
|
|||
|
return XTheme.IconSize;
|
|||
|
else
|
|||
|
return System.Drawing.Size.Empty;
|
|||
|
}
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.IconSize = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标题栏图标与窗体左边框的距离
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("标题栏图标与窗体左边框的距离")]
|
|||
|
[DefaultValue(2)]
|
|||
|
public int IconLeftMargin
|
|||
|
{
|
|||
|
get { return (this.ShowIcon ? XTheme.IconLeftMargin : 0); }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.IconLeftMargin = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标题距离左边的距离
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[DefaultValue(2), Description("标题距离左边的距离")]
|
|||
|
public int TextLeftMargin
|
|||
|
{
|
|||
|
get { return XTheme.TextLeftMargin; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.TextLeftMargin = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体关闭按钮的尺寸
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[Description("窗体关闭按钮的尺寸")]
|
|||
|
[DefaultValue(typeof(Size), "37, 17")]
|
|||
|
public Size CloseBoxSize
|
|||
|
{
|
|||
|
get { return XTheme.CloseBoxSize; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.CloseBoxSize = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体最大化/还原按钮的大小
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[DefaultValue(typeof(Size), "25, 17")]
|
|||
|
[Description("窗体最大化/还原按钮的大小")]
|
|||
|
public Size MaxBoxSize
|
|||
|
{
|
|||
|
get { return XTheme.MaxBoxSize; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.MaxBoxSize = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体最小化按钮的大小
|
|||
|
/// </summary>
|
|||
|
[Category("GMForm")]
|
|||
|
[DefaultValue(typeof(Size), "25, 17")]
|
|||
|
[Description("窗体最小化按钮的大小")]
|
|||
|
public Size MinBoxSize
|
|||
|
{
|
|||
|
get { return XTheme.MinBoxSize; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.MinBoxSize = value;
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region form shadow about
|
|||
|
/// <summary>
|
|||
|
/// 是否显示阴影
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow"), Description("是否显示阴影")]
|
|||
|
public bool ShowShadow
|
|||
|
{
|
|||
|
get { return XTheme.ShowShadow; }
|
|||
|
set
|
|||
|
{
|
|||
|
if (value != XTheme.ShowShadow)
|
|||
|
{
|
|||
|
XTheme.ShowShadow = value;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体阴影宽度
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow"), Description("窗体阴影宽度")]
|
|||
|
public int ShadowWidth
|
|||
|
{
|
|||
|
get { return XTheme.ShadowWidth; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ShadowWidth = value;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 使用阴影来缩放
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow"), Description("使用阴影来缩放")]
|
|||
|
public bool UseShadowToResize
|
|||
|
{
|
|||
|
get { return XTheme.UseShadowToResize; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.UseShadowToResize = value;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体阴影颜色
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow")]
|
|||
|
[Description("窗体阴影颜色")]
|
|||
|
public Color ShadowColor
|
|||
|
{
|
|||
|
get { return XTheme.ShadowColor; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ShadowColor = value;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 阴影从里到外是逐渐变浅的,这个值设置深色部分的透明度,ARGB中的A值
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow")]
|
|||
|
[Description("阴影从里到外是逐渐变浅的,这个值设置深色部分的透明度,ARGB中的A值")]
|
|||
|
public int ShadowAValueDark
|
|||
|
{
|
|||
|
get { return XTheme.ShadowAValueDark; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ShadowAValueDark = value;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 阴影从里到外是逐渐变浅的,这个值设置浅色部分的透明度,ARGB中的A值
|
|||
|
/// </summary>
|
|||
|
[Category("Form Shadow")]
|
|||
|
[Description("阴影从里到外是逐渐变浅的,这个值设置浅色部分的透明度,ARGB中的A值")]
|
|||
|
public int ShadowAValueLight
|
|||
|
{
|
|||
|
get { return XTheme.ShadowAValueLight; }
|
|||
|
set
|
|||
|
{
|
|||
|
XTheme.ShadowAValueLight = value;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region form resize region, internal readonly
|
|||
|
|
|||
|
internal Rectangle TopLeftRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(0, 0, SideResizeWidth, SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle TopRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
SideResizeWidth,
|
|||
|
0,
|
|||
|
this.Size.Width - SideResizeWidth * 2,
|
|||
|
SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle TopRightRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
this.Size.Width - SideResizeWidth,
|
|||
|
0,
|
|||
|
SideResizeWidth,
|
|||
|
SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle LeftRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
0,
|
|||
|
SideResizeWidth,
|
|||
|
SideResizeWidth,
|
|||
|
this.Size.Height - SideResizeWidth * 2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle RightRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
this.Size.Width - SideResizeWidth,
|
|||
|
SideResizeWidth,
|
|||
|
SideResizeWidth,
|
|||
|
this.Size.Height - SideResizeWidth * 2);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle BottomLeftRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
0,
|
|||
|
this.Size.Height - SideResizeWidth,
|
|||
|
SideResizeWidth,
|
|||
|
SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle BottomRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
SideResizeWidth,
|
|||
|
this.Size.Height - SideResizeWidth,
|
|||
|
this.Size.Width - SideResizeWidth * 2,
|
|||
|
SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle BottomRightRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
this.Size.Width - SideResizeWidth,
|
|||
|
this.Size.Height - SideResizeWidth,
|
|||
|
SideResizeWidth,
|
|||
|
SideResizeWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
#region calculated rect
|
|||
|
|
|||
|
internal Rectangle CaptionRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
BorderWidth,
|
|||
|
BorderWidth,
|
|||
|
this.ClientSize.Width - BorderWidth * 2,
|
|||
|
CaptionHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle CaptionRectToDraw
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
0,
|
|||
|
0,
|
|||
|
this.ClientSize.Width,
|
|||
|
CaptionHeight + BorderWidth);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle CloseBoxRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (ControlBox)
|
|||
|
{
|
|||
|
int x = ClientSize.Width - ControlBoxOffset.X - CloseBoxSize.Width;
|
|||
|
return new Rectangle(
|
|||
|
new Point(x, ControlBoxOffset.Y),
|
|||
|
CloseBoxSize);
|
|||
|
}
|
|||
|
else
|
|||
|
return Rectangle.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle MaxBoxRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (ControlBox && MaximizeBox)
|
|||
|
{
|
|||
|
int x = CloseBoxRect.Left - ControlBoxSpace - MaxBoxSize.Width;
|
|||
|
return new Rectangle(
|
|||
|
new Point(x, ControlBoxOffset.Y),
|
|||
|
MaxBoxSize);
|
|||
|
}
|
|||
|
else
|
|||
|
return Rectangle.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle MinBoxRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (ControlBox && MinimizeBox)
|
|||
|
{
|
|||
|
int x;
|
|||
|
if (MaximizeBox)
|
|||
|
x = MaxBoxRect.Left - ControlBoxSpace - MinBoxSize.Width;
|
|||
|
else
|
|||
|
x = CloseBoxRect.Left - ControlBoxSpace - MinBoxSize.Width;
|
|||
|
return new Rectangle(
|
|||
|
new Point(x, ControlBoxOffset.Y),
|
|||
|
MinBoxSize);
|
|||
|
}
|
|||
|
else
|
|||
|
return Rectangle.Empty;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle IconRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (ControlBox && ShowIcon)
|
|||
|
{
|
|||
|
int x = BorderWidth + IconLeftMargin;
|
|||
|
int y = BorderWidth + (CaptionHeight - IconSize.Height) / 2;
|
|||
|
return new Rectangle(new Point(x, y), IconSize);
|
|||
|
}
|
|||
|
else
|
|||
|
return new Rectangle(BorderWidth, BorderWidth, 0, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal Rectangle TextRect
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
int x = IconRect.Right + TextLeftMargin;
|
|||
|
int y = BorderWidth;
|
|||
|
int height = CaptionHeight;
|
|||
|
int right = this.ClientSize.Width - x;
|
|||
|
if (ControlBox)
|
|||
|
{
|
|||
|
right = CloseBoxRect.Left;
|
|||
|
if (MinimizeBox)
|
|||
|
{
|
|||
|
right = MinBoxRect.Left;
|
|||
|
}
|
|||
|
else if (MaximizeBox)
|
|||
|
{
|
|||
|
right = MaxBoxRect.Left;
|
|||
|
}
|
|||
|
}
|
|||
|
int width = right - x;
|
|||
|
return new Rectangle(x, y, width, height);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 表示去掉自画的边框及标题栏后,剩下的可用的客户区区域,坐标相对于窗体左上角
|
|||
|
/// </summary>
|
|||
|
[Browsable(false)]
|
|||
|
public Rectangle UserClientBounds
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Rectangle(
|
|||
|
BorderWidth,
|
|||
|
BorderWidth + CaptionHeight,
|
|||
|
ClientSize.Width - BorderWidth * 2,
|
|||
|
ClientSize.Height - BorderWidth * 2 - CaptionHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 表示去掉自画的边框及标题栏后,剩下的可用的客户区大小
|
|||
|
/// </summary>
|
|||
|
[Browsable(false)]
|
|||
|
public Size UserClientSize
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return new Size(
|
|||
|
ClientSize.Width - BorderWidth * 2,
|
|||
|
ClientSize.Height - BorderWidth * 2 - CaptionHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 表示MDI标签栏的区域,包括bottom-region
|
|||
|
/// </summary>
|
|||
|
[Browsable(false)]
|
|||
|
public Rectangle MdiBarBounds
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
if (!IsMdiContainer || _mdiBarController == null)
|
|||
|
return Rectangle.Empty;
|
|||
|
return _mdiBarController.Bounds;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region constructor & initialize
|
|||
|
/// <summary>
|
|||
|
/// MGdUI皮肤
|
|||
|
/// </summary>
|
|||
|
public GMForm()
|
|||
|
: base()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
FormIni();
|
|||
|
//if (!DesignMode)
|
|||
|
//{
|
|||
|
// base.ShowInTaskbar = ShowInTaskbar;
|
|||
|
//}
|
|||
|
// 下面这个条件是永远不为true的,如果不把此类直接设置成mdicontainer
|
|||
|
//if (this.IsMdiContainer)
|
|||
|
// SetMdiClient();
|
|||
|
}
|
|||
|
|
|||
|
private void FormIni()
|
|||
|
{
|
|||
|
this.SetStyle(
|
|||
|
ControlStyles.AllPaintingInWmPaint |
|
|||
|
ControlStyles.UserPaint |
|
|||
|
ControlStyles.OptimizedDoubleBuffer |
|
|||
|
ControlStyles.ResizeRedraw, true);
|
|||
|
this.DoubleBuffered = true;
|
|||
|
this.UpdateStyles();
|
|||
|
base.Padding = DefaultPadding;
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager = new ControlBoxManager(this);
|
|||
|
}
|
|||
|
|
|||
|
#region MDI-Support
|
|||
|
/// <summary>
|
|||
|
/// 获取子窗体
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public MdiClient GetMdiClient()
|
|||
|
{
|
|||
|
MdiClient mdiclient = null;
|
|||
|
foreach (Control ctl in Controls)
|
|||
|
{
|
|||
|
if ((mdiclient = ctl as MdiClient) != null)
|
|||
|
break;
|
|||
|
}
|
|||
|
return mdiclient;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 通过sendmessage方式激活子窗体以避免闪烁
|
|||
|
/// </summary>
|
|||
|
/// <param name="childToActivate"></param>
|
|||
|
public void ActivateMdiChildForm(Form childToActivate)
|
|||
|
{
|
|||
|
MdiClient mdi = GetMdiClient();
|
|||
|
if (mdi == null)
|
|||
|
return;
|
|||
|
if (base.ActiveMdiChild == childToActivate)
|
|||
|
return;
|
|||
|
if (base.MdiChildren.Length < 2)
|
|||
|
return;
|
|||
|
Control form = null;
|
|||
|
bool isNext = false;
|
|||
|
int pos = mdi.Controls.IndexOf(childToActivate);
|
|||
|
if (pos < 0)
|
|||
|
return;
|
|||
|
if (pos == 0)
|
|||
|
{
|
|||
|
form = mdi.Controls[pos + 1];
|
|||
|
isNext = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
form = mdi.Controls[pos - 1];
|
|||
|
isNext = false;
|
|||
|
}
|
|||
|
IntPtr next = (isNext ? Win32.WinAPI.TRUE : Win32.WinAPI.FALSE);
|
|||
|
Win32.WinAPI.SendMessage(mdi.Handle,
|
|||
|
(int)Win32.WinAPI.WindowMessages.WM_MDINEXT, form.Handle, next);
|
|||
|
}
|
|||
|
|
|||
|
private void SetMdiClient()
|
|||
|
{
|
|||
|
if (!IsMdiContainer)
|
|||
|
return;
|
|||
|
|
|||
|
MdiClient mdi = GetMdiClient();
|
|||
|
if (mdi != null)
|
|||
|
{
|
|||
|
SetMdiStyles(mdi);
|
|||
|
UpdateMdiStyles(mdi);
|
|||
|
SetMdiClientLocation(mdi);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void SetMdiStyles(MdiClient mdi)
|
|||
|
{
|
|||
|
// remove the border
|
|||
|
|
|||
|
int style = Win32.WinAPI.GetWindowLong(mdi.Handle, (int)Win32.WinAPI.GWLPara.GWL_STYLE);
|
|||
|
int exStyle = Win32.WinAPI.GetWindowLong(mdi.Handle, (int)Win32.WinAPI.GWLPara.GWL_EXSTYLE);
|
|||
|
|
|||
|
style &= ~(int)Win32.WinAPI.WindowStyle.WS_BORDER;
|
|||
|
exStyle &= ~(int)Win32.WinAPI.WindowStyleEx.WS_EX_CLIENTEDGE;
|
|||
|
|
|||
|
Win32.WinAPI.SetWindowLong(mdi.Handle, (int)Win32.WinAPI.GWLPara.GWL_STYLE, style);
|
|||
|
Win32.WinAPI.SetWindowLong(mdi.Handle, (int)Win32.WinAPI.GWLPara.GWL_EXSTYLE, exStyle);
|
|||
|
|
|||
|
Win32.WinAPI.ShowScrollBar(mdi.Handle, (int)Win32.WinAPI.ScrollBar.SB_BOTH, 0 /*false*/);
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateMdiStyles(MdiClient mdi)
|
|||
|
{
|
|||
|
// To show style changes, the non-client area must be repainted. Using the
|
|||
|
// control's Invalidate method does not affect the non-client area.
|
|||
|
// Instead use a Win32 call to signal the style has changed.
|
|||
|
|
|||
|
Win32.WinAPI.SetWindowPos(mdi.Handle, IntPtr.Zero, 0, 0, 0, 0,
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_NOACTIVATE |
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_NOMOVE |
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_NOSIZE |
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_NOZORDER |
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_NOOWNERZORDER |
|
|||
|
(uint)Win32.WinAPI.SWPPara.SWP_FRAMECHANGED);
|
|||
|
}
|
|||
|
|
|||
|
private void SetMdiClientLocation(MdiClient mdi)
|
|||
|
{
|
|||
|
mdi.BackColor = Color.White;
|
|||
|
//mdi.Margin = new Padding(10);
|
|||
|
//mdi.Dock = DockStyle.None;
|
|||
|
|
|||
|
//mdi.Location = new Point(30, 40);
|
|||
|
//mdi.Size = new Size(400, 260);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// used for child mdi form to notify its parent form that it's closed
|
|||
|
/// <summary>
|
|||
|
/// 当子窗体关闭时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected void MdiChildClosed(object sender, FormClosedEventArgs e)
|
|||
|
{
|
|||
|
Form child = sender as Form;
|
|||
|
if (child != null)
|
|||
|
{
|
|||
|
_lastClosedMdiChild = child;
|
|||
|
_listClosedMdiChild.Add(child);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// for mdi child form
|
|||
|
/// <summary>
|
|||
|
/// 子窗体可视化变化
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected void MdiChildVisibleChange(object sender, EventArgs e)
|
|||
|
{
|
|||
|
base.Invalidate();
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 获取当前的子窗体列表
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public List<Form> GetCurrentMdiChildren()
|
|||
|
{
|
|||
|
List<Form> list = new List<Form>();
|
|||
|
if (_listClosedMdiChild != null)
|
|||
|
{
|
|||
|
foreach (Form f in MdiChildren)
|
|||
|
{
|
|||
|
if (!_listClosedMdiChild.Contains(f) && f.Visible)
|
|||
|
list.Add(f);
|
|||
|
}
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region private method
|
|||
|
|
|||
|
private void SetFormMinimizeSize()
|
|||
|
{
|
|||
|
int minW = 160;
|
|||
|
int minH = 60;
|
|||
|
|
|||
|
int w = BorderWidth * 2 + IconLeftMargin + IconSize.Width
|
|||
|
+ TextLeftMargin + MinBoxSize.Width + MaxBoxSize.Width
|
|||
|
+ CloseBoxSize.Width + ControlBoxSpace * 2
|
|||
|
+ ControlBoxOffset.X + 12;
|
|||
|
if (w < minW)
|
|||
|
w = minW;
|
|||
|
int h = BorderWidth * 2 + CaptionHeight + 8;
|
|||
|
if (h < minH)
|
|||
|
h = minH;
|
|||
|
base.MinimumSize = new Size(w, h);
|
|||
|
}
|
|||
|
|
|||
|
private void SetShadowFormSize()
|
|||
|
{
|
|||
|
if (_shawdowForm == null || _shawdowForm.IsDisposed)
|
|||
|
return;
|
|||
|
if (base.WindowState == FormWindowState.Normal)
|
|||
|
{
|
|||
|
var size = base.Size;
|
|||
|
size.Width += XTheme.ShadowWidth * 2;
|
|||
|
size.Height += XTheme.ShadowWidth * 2;
|
|||
|
if (_shawdowForm.Size != size)
|
|||
|
{
|
|||
|
_shawdowForm.Size = size;
|
|||
|
// update size -- api: movewindow....
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void SetShadowFormLocation()
|
|||
|
{
|
|||
|
if (_shawdowForm == null || _shawdowForm.IsDisposed)
|
|||
|
return;
|
|||
|
if (base.WindowState == FormWindowState.Normal)
|
|||
|
{
|
|||
|
Point p = base.Location;
|
|||
|
p.Offset(-XTheme.ShadowWidth, -XTheme.ShadowWidth);
|
|||
|
if (_shawdowForm.Location != p)
|
|||
|
{
|
|||
|
_shawdowForm.Location = p;
|
|||
|
// update location -- api: movewindow....
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void PrepareForNewTheme()
|
|||
|
{
|
|||
|
if (base.Region != null)
|
|||
|
base.Region.Dispose();
|
|||
|
base.Region = null;
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
{
|
|||
|
controlBoxManager.ResetBoxColor();
|
|||
|
controlBoxManager.FormResize();
|
|||
|
}
|
|||
|
SetFormRegion();
|
|||
|
//Padding = new Padding(0);
|
|||
|
base.BackColor = XTheme.FormBackColor;
|
|||
|
base.OnSizeChanged(EventArgs.Empty);
|
|||
|
SetFormMinimizeSize();
|
|||
|
if (XTheme.ShowShadow)
|
|||
|
{
|
|||
|
if (_shawdowForm == null || _shawdowForm.IsDisposed)
|
|||
|
{
|
|||
|
OnActivated(EventArgs.Empty);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (_shawdowForm != null)
|
|||
|
{
|
|||
|
_shawdowForm.Close();
|
|||
|
_shawdowForm = null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void SetFormRegion()
|
|||
|
{
|
|||
|
if (base.Region != null)
|
|||
|
base.Region.Dispose();
|
|||
|
|
|||
|
Rectangle rect = new Rectangle(Point.Empty, base.Size);
|
|||
|
GraphicsPath path;
|
|||
|
|
|||
|
if (XTheme.UseDefaultTopRoundingFormRegion)
|
|||
|
path = GraphicsPathHelper.CreateTopRoundedPathForFormRegion(rect);
|
|||
|
else
|
|||
|
path = GraphicsPathHelper.CreateRoundedRect(rect, Radius, Round, false);
|
|||
|
|
|||
|
this.Region = new Region(path);
|
|||
|
}
|
|||
|
|
|||
|
//private GraphicsPath CreateRoundedFormRect(bool correction)
|
|||
|
//{
|
|||
|
// Rectangle rect = new Rectangle(Point.Empty, this.Size);
|
|||
|
// return GraphicsPathHelper.CreateRoundedRect(rect, Radius, Round, correction);
|
|||
|
//}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 判断所接收到的 wm_nc-calc-size 消息是否指示窗体即将最小化
|
|||
|
/// </summary>
|
|||
|
private bool IsAboutToMinimize(Win32.WinAPI.RECT rect)
|
|||
|
{
|
|||
|
if (rect.Left == -32000 && rect.Top == -32000)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 判断所接收到的 wm_nc-calc-size 消息是否指示窗体即将最大化
|
|||
|
/// </summary>
|
|||
|
private bool IsAboutToMaximize(Win32.WinAPI.RECT rect)
|
|||
|
{
|
|||
|
/*
|
|||
|
* 判断的方法是,只要窗体的左右、上下都延伸到了屏幕工作区之外,
|
|||
|
* 并且左和右、上和下都延伸相同的量,就认为窗体是要进行最大化
|
|||
|
*/
|
|||
|
|
|||
|
int left = rect.Left;
|
|||
|
int top = rect.Top;
|
|||
|
int width = rect.Right - rect.Left;
|
|||
|
int height = rect.Bottom - rect.Top;
|
|||
|
|
|||
|
if (left < 0 && top < 0)
|
|||
|
{
|
|||
|
Rectangle workingArea = Screen.GetWorkingArea(this);
|
|||
|
if (width == (workingArea.Width + (-left) * 2)
|
|||
|
&& height == (workingArea.Height + (-top) * 2))
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
private void DrawFormBackground(Graphics g)
|
|||
|
{
|
|||
|
SmoothingMode oldMode = g.SmoothingMode;
|
|||
|
if (Round != RoundStyle.None)
|
|||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|||
|
|
|||
|
using (SolidBrush sb = new SolidBrush(XTheme.FormBackColor))
|
|||
|
{
|
|||
|
using (GraphicsPath path = GraphicsPathHelper.CreateRoundedRect(
|
|||
|
ClientRectangle, Radius, Round, false))
|
|||
|
{
|
|||
|
g.FillPath(sb, path);
|
|||
|
}
|
|||
|
}
|
|||
|
g.SmoothingMode = oldMode;
|
|||
|
}
|
|||
|
|
|||
|
private void DrawCaptionBackground(Graphics g)
|
|||
|
{
|
|||
|
using (LinearGradientBrush lb = new LinearGradientBrush(
|
|||
|
CaptionRectToDraw,
|
|||
|
XTheme.CaptionBackColorTop,
|
|||
|
XTheme.CaptionBackColorBottom,
|
|||
|
LinearGradientMode.Vertical))
|
|||
|
{
|
|||
|
g.FillRectangle(lb, CaptionRectToDraw);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void DrawFormIconAndText(Graphics g)
|
|||
|
{
|
|||
|
if (ShowIcon && Icon != null && XTheme.DrawCaptionIcon)
|
|||
|
{
|
|||
|
g.DrawIcon(this.Icon, IconRect);
|
|||
|
}
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(Text) && XTheme.DrawCaptionText)
|
|||
|
{
|
|||
|
TextRenderer.DrawText(
|
|||
|
g,
|
|||
|
this.Text,
|
|||
|
SystemFonts.CaptionFont,
|
|||
|
TextRect,
|
|||
|
XTheme.CaptionTextColor,
|
|||
|
(XTheme.CaptionTextCenter ? TextFormatFlags.HorizontalCenter : TextFormatFlags.Left) |
|
|||
|
TextFormatFlags.VerticalCenter |
|
|||
|
TextFormatFlags.EndEllipsis);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void DrawFormBorder(Graphics g)
|
|||
|
{
|
|||
|
int width = BorderWidth;
|
|||
|
Rectangle rect = ClientRectangle;
|
|||
|
|
|||
|
SmoothingMode oldMode = g.SmoothingMode;
|
|||
|
if (Round != RoundStyle.None)
|
|||
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|||
|
|
|||
|
// outter border
|
|||
|
if (width > 0)
|
|||
|
{
|
|||
|
using (Pen p = new Pen(XTheme.FormBorderOutterColor))
|
|||
|
{
|
|||
|
using (GraphicsPath path = GraphicsPathHelper.CreateRoundedRect(
|
|||
|
rect, Radius, Round, true))
|
|||
|
{
|
|||
|
g.DrawPath(p, path);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
width--;
|
|||
|
|
|||
|
// inner border
|
|||
|
if (width > 0)
|
|||
|
{
|
|||
|
using (Pen p = new Pen(XTheme.FormBorderInnerColor))
|
|||
|
{
|
|||
|
rect.Inflate(-1, -1);
|
|||
|
using (GraphicsPath path = GraphicsPathHelper.CreateRoundedRect(
|
|||
|
rect, Radius, Round, true))
|
|||
|
{
|
|||
|
g.DrawPath(p, path);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
width--;
|
|||
|
|
|||
|
g.SmoothingMode = oldMode;
|
|||
|
|
|||
|
// other inside border
|
|||
|
using (Pen p = new Pen(XTheme.FormBorderInmostColor))
|
|||
|
{
|
|||
|
while (width > 0)
|
|||
|
{
|
|||
|
rect.Inflate(-1, -1);
|
|||
|
g.DrawRectangle(p, rect);
|
|||
|
width--;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// to make the client area to have 3D view
|
|||
|
/// </summary>
|
|||
|
private void DrawInsetClientRect(Graphics g)
|
|||
|
{
|
|||
|
int x = BorderWidth;
|
|||
|
int y = BorderWidth + CaptionHeight;
|
|||
|
int w = ClientSize.Width - BorderWidth * 2;
|
|||
|
int h = ClientSize.Height - BorderWidth * 2 - CaptionHeight;
|
|||
|
Rectangle clientRect = new Rectangle(x, y, w, h);
|
|||
|
clientRect.Width--;
|
|||
|
clientRect.Height--;
|
|||
|
|
|||
|
Color inner = ColorHelper.GetDarkerColor(this.BackColor, 20);
|
|||
|
clientRect.Inflate(1, 1);
|
|||
|
using (Pen p1 = new Pen(inner))
|
|||
|
{
|
|||
|
g.DrawRectangle(p1, clientRect);
|
|||
|
}
|
|||
|
|
|||
|
Color outter = Color.FromArgb(80, 255, 255, 255);
|
|||
|
clientRect.Inflate(1, 1);
|
|||
|
using (Pen p2 = new Pen(outter))
|
|||
|
{
|
|||
|
g.DrawRectangle(p2, clientRect);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region your Win-Message handler method
|
|||
|
|
|||
|
private bool WmNcActivate(ref Message m)
|
|||
|
{
|
|||
|
// something here
|
|||
|
m.Result = Win32.WinAPI.TRUE;
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private bool WmNcCalcSize(ref Message m)
|
|||
|
{
|
|||
|
if (m.WParam == new IntPtr(1))
|
|||
|
{
|
|||
|
Win32.WinAPI.NCCALCSIZE_PARAMS info = (Win32.WinAPI.NCCALCSIZE_PARAMS)
|
|||
|
Marshal.PtrToStructure(m.LParam, typeof(Win32.WinAPI.NCCALCSIZE_PARAMS));
|
|||
|
if (IsAboutToMaximize(info.rectNewForm))
|
|||
|
{
|
|||
|
Rectangle workingRect = Screen.GetWorkingArea(this);
|
|||
|
info.rectNewForm.Left = workingRect.Left - BorderWidth;
|
|||
|
info.rectNewForm.Top = workingRect.Top - BorderWidth;
|
|||
|
info.rectNewForm.Right = workingRect.Right + BorderWidth;
|
|||
|
info.rectNewForm.Bottom = workingRect.Bottom + BorderWidth;
|
|||
|
Marshal.StructureToPtr(info, m.LParam, false);
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private bool WmNcHitTest(ref Message m)
|
|||
|
{
|
|||
|
int para = m.LParam.ToInt32();
|
|||
|
//var point = MousePosition;
|
|||
|
//int x0 = Win32.WinAPI.LOWORD(para);
|
|||
|
//int y0 = Win32.WinAPI.HIWORD(para);
|
|||
|
Point p = PointToClient(MousePosition);
|
|||
|
|
|||
|
if (Resizable)
|
|||
|
{
|
|||
|
if (TopLeftRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOPLEFT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (TopRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOP);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (TopRightRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTTOPRIGHT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (LeftRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTLEFT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (RightRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTRIGHT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (BottomLeftRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOMLEFT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (BottomRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOM);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (BottomRightRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTBOTTOMRIGHT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (IconRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTSYSMENU);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (CloseBoxRect.Contains(p) || MaxBoxRect.Contains(p) || MinBoxRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTCLIENT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
{
|
|||
|
if (_mdiBarController.HitTestBounds.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTCLIENT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (CaptionRect.Contains(p))
|
|||
|
{
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTCAPTION);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
m.Result = new IntPtr((int)Win32.WinAPI.NCHITTEST.HTCLIENT);
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region override method
|
|||
|
/// <summary>
|
|||
|
/// 消息
|
|||
|
/// </summary>
|
|||
|
/// <param name="m"></param>
|
|||
|
protected override void WndProc(ref Message m)
|
|||
|
{
|
|||
|
bool alreadyHandled = false;
|
|||
|
|
|||
|
switch (m.Msg)
|
|||
|
{
|
|||
|
case (int)Win32.WinAPI.WindowMessages.WM_NCCALCSIZE:
|
|||
|
alreadyHandled = WmNcCalcSize(ref m);
|
|||
|
break;
|
|||
|
case (int)Win32.WinAPI.WindowMessages.WM_NCHITTEST:
|
|||
|
alreadyHandled = WmNcHitTest(ref m);
|
|||
|
break;
|
|||
|
|
|||
|
case (int)Win32.WinAPI.WindowMessages.WM_NCACTIVATE:
|
|||
|
alreadyHandled = WmNcActivate(ref m);
|
|||
|
break;
|
|||
|
|
|||
|
case (int)Win32.WinAPI.WindowMessages.WM_NCPAINT:
|
|||
|
alreadyHandled = true;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!alreadyHandled)
|
|||
|
base.WndProc(ref m);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 画UI
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnPaint(PaintEventArgs e)
|
|||
|
{
|
|||
|
base.OnPaint(e);
|
|||
|
|
|||
|
DrawFormBackground(e.Graphics);
|
|||
|
DrawCaptionBackground(e.Graphics);
|
|||
|
DrawFormBorder(e.Graphics);
|
|||
|
DrawFormIconAndText(e.Graphics);
|
|||
|
|
|||
|
if (XTheme.SetClientInset)
|
|||
|
DrawInsetClientRect(e.Graphics);
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.DrawBoxes(e.Graphics);
|
|||
|
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
_mdiBarController.RenderTheBar(e.Graphics);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在画背景时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnPaintBackground(PaintEventArgs e)
|
|||
|
{
|
|||
|
//base.OnPaintBackground(e);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 重写该方法解决窗体每次还原都会变大的问题
|
|||
|
/// </summary>
|
|||
|
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
|
|||
|
{
|
|||
|
if (base.WindowState == FormWindowState.Normal)
|
|||
|
{
|
|||
|
if (this.Size == this.ClientSize)
|
|||
|
{
|
|||
|
//if (width == (this.Size.Width + SystemInformation.FrameBorderSize.Width * 2))
|
|||
|
if (width == (this.Size.Width + 4 * 2) || width == (this.Size.Width + 8 * 2))
|
|||
|
{
|
|||
|
width = this.Size.Width;
|
|||
|
height = this.Size.Height;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
base.SetBoundsCore(x, y, width, height, specified);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 重写该方法解决在VS设计器中,每次保存一个新的尺寸,再打开尺寸会变大的问题
|
|||
|
/// </summary>
|
|||
|
protected override void SetClientSizeCore(int x, int y)
|
|||
|
{
|
|||
|
//MessageBox.Show("before SetClientSizeCore,size:" +
|
|||
|
// base.Size.ToString() + ", clisize:" + base.ClientSize.ToString()
|
|||
|
// + ", x:" + x.ToString() + ", y:" + y.ToString());
|
|||
|
|
|||
|
//if (base.WindowState == FormWindowState.Normal && DesignMode)
|
|||
|
//{
|
|||
|
// if (base.Size != base.ClientSize)
|
|||
|
// {
|
|||
|
// int diffx = Size.Width - ClientSize.Width;
|
|||
|
// int diffy = Size.Height - ClientSize.Height;
|
|||
|
// if (diffx == 4 * 2 || diffx == 8 * 2)
|
|||
|
// {
|
|||
|
// x -= diffx;
|
|||
|
// y -= diffy;
|
|||
|
// }
|
|||
|
// }
|
|||
|
//}
|
|||
|
base.SetClientSizeCore(x, y);
|
|||
|
|
|||
|
//MessageBox.Show(base.SizeFromClientSize(new Size(x,y)).ToString());
|
|||
|
|
|||
|
//MessageBox.Show("after SetClientSizeCore,size:" +
|
|||
|
// base.Size.ToString() + ", clisize:" + base.ClientSize.ToString()
|
|||
|
// + ", x:" + x.ToString() + ", y:" + y.ToString());
|
|||
|
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 创建控件时激发
|
|||
|
/// </summary>
|
|||
|
protected override void OnCreateControl()
|
|||
|
{
|
|||
|
base.OnCreateControl();
|
|||
|
SetFormRegion();
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体可见变化时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnVisibleChanged(EventArgs e)
|
|||
|
{
|
|||
|
base.OnVisibleChanged(e);
|
|||
|
if (_shawdowForm != null)
|
|||
|
_shawdowForm.Visible = base.Visible;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 大小改变时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnSizeChanged(EventArgs e)
|
|||
|
{
|
|||
|
base.OnSizeChanged(e);
|
|||
|
SetFormRegion();
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.FormResize();
|
|||
|
|
|||
|
if (XTheme.ShowShadow && _shawdowForm != null
|
|||
|
&& !_shawdowForm.IsDisposed)
|
|||
|
{
|
|||
|
if (base.WindowState == FormWindowState.Normal)
|
|||
|
{
|
|||
|
_shawdowForm.Visible = true;
|
|||
|
SetShadowFormSize();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_shawdowForm.Visible = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在位置变化时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnLocationChanged(EventArgs e)
|
|||
|
{
|
|||
|
base.OnLocationChanged(e);
|
|||
|
|
|||
|
if (XTheme.ShowShadow && _shawdowForm != null
|
|||
|
&& !_shawdowForm.IsDisposed && _shawdowForm.Visible)
|
|||
|
SetShadowFormLocation();
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体激活
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnActivated(EventArgs e)
|
|||
|
{
|
|||
|
base.OnActivated(e);
|
|||
|
if (XTheme.ShowShadow && !base.IsMdiChild)
|
|||
|
{
|
|||
|
if (_shawdowForm == null)
|
|||
|
{
|
|||
|
_shawdowForm = new GMShadow(this);
|
|||
|
SetShadowFormSize();
|
|||
|
SetShadowFormLocation();
|
|||
|
_shawdowForm.Show(this);
|
|||
|
SetShadowFormSize();
|
|||
|
SetShadowFormLocation();
|
|||
|
|
|||
|
_shawdowForm.TopMost = base.TopMost;
|
|||
|
|
|||
|
var size = base.MinimumSize;
|
|||
|
size.Width += ShadowWidth * 2;
|
|||
|
size.Height += ShadowWidth * 2;
|
|||
|
_shawdowForm.MinimumSize = size;
|
|||
|
|
|||
|
if (XTheme.UseShadowToResize)
|
|||
|
_shawdowForm.BeginToResizeOwner();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 窗体关闭后激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnFormClosed(FormClosedEventArgs e)
|
|||
|
{
|
|||
|
if (_shawdowForm != null && !_shawdowForm.IsDisposed)
|
|||
|
_shawdowForm.Close();
|
|||
|
|
|||
|
base.OnFormClosed(e);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 加载时
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnLoad(EventArgs e)
|
|||
|
{
|
|||
|
base.OnLoad(e);
|
|||
|
|
|||
|
if (base.IsMdiContainer)
|
|||
|
{
|
|||
|
SetMdiClient();
|
|||
|
_listClosedMdiChild = new List<Form>();
|
|||
|
_mdiBarController = new MdiBarController(this);
|
|||
|
_mdiBarController.TabCloseButtonClick += new EventHandler(OnMdiTabCloseButtonClick);
|
|||
|
_mdiBarController.NewTabButtonClick +=new EventHandler(OnMdiNewTabButtonClick);
|
|||
|
OnMdiBarCreated(this, EventArgs.Empty);
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在子窗体激活时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnMdiChildActivate(EventArgs e)
|
|||
|
{
|
|||
|
base.OnMdiChildActivate(e);
|
|||
|
Invalidate();
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 标签菜单
|
|||
|
/// </summary>
|
|||
|
public ContextMenuStrip TabContextMenuStrip { get; set; } = null;
|
|||
|
/// <summary>
|
|||
|
/// 窗体上移动鼠标时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnMouseMove(MouseEventArgs e)
|
|||
|
{
|
|||
|
base.OnMouseMove(e);
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.MouseOperation(e.Location, MouseOperationType.Move);
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
_mdiBarController.MouseOperation(e.Location, MouseOperationType.Move);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 获取当前点击的标签项
|
|||
|
/// </summary>
|
|||
|
public Form ClickTab { get; set; } = null;
|
|||
|
/// <summary>
|
|||
|
/// 在窗体上按下鼠标时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnMouseDown(MouseEventArgs e)
|
|||
|
{
|
|||
|
base.OnMouseDown(e);
|
|||
|
|
|||
|
if (e.Button != System.Windows.Forms.MouseButtons.Left)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.MouseOperation(e.Location, MouseOperationType.Down);
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
_mdiBarController.MouseOperation(e.Location, MouseOperationType.Down);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在窗体上放开鼠标时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnMouseUp(MouseEventArgs e)
|
|||
|
{
|
|||
|
base.OnMouseUp(e);
|
|||
|
|
|||
|
if (e.Button != System.Windows.Forms.MouseButtons.Left)
|
|||
|
{
|
|||
|
if (e.Button == System.Windows.Forms.MouseButtons.Right)
|
|||
|
{
|
|||
|
if (TabContextMenuStrip != null)
|
|||
|
{
|
|||
|
foreach (MdiGMTabItem tab in _mdiBarController._listTabItems)
|
|||
|
{
|
|||
|
if (!tab.IsHidden)
|
|||
|
{
|
|||
|
if (tab.Bounds.Contains(e.Location) && !tab.CloseBtnRect.Contains(e.Location))
|
|||
|
{
|
|||
|
ClickTab = tab.Form;
|
|||
|
TabContextMenuStrip.Show(PointToScreen(e.Location));
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (e.Clicks > 1)
|
|||
|
return;
|
|||
|
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.MouseOperation(e.Location, MouseOperationType.Up);
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
_mdiBarController.MouseOperation(e.Location, MouseOperationType.Up);
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 在鼠标离开窗体时激发
|
|||
|
/// </summary>
|
|||
|
/// <param name="e"></param>
|
|||
|
protected override void OnMouseLeave(EventArgs e)
|
|||
|
{
|
|||
|
base.OnMouseLeave(e);
|
|||
|
if (ControlBox)
|
|||
|
controlBoxManager.MouseOperation(Point.Empty, MouseOperationType.Leave);
|
|||
|
if (IsMdiContainer && _mdiBarController != null)
|
|||
|
_mdiBarController.MouseOperation(Point.Empty, MouseOperationType.Leave);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
}
|
|||
|
}
|