1587 lines
61 KiB
C#
1587 lines
61 KiB
C#
using System;
|
|
using System.Text;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.InteropServices;
|
|
using DevComponents.DotNetBar.Rendering;
|
|
using System.Drawing.Drawing2D;
|
|
using System.ComponentModel;
|
|
|
|
namespace DevComponents.DotNetBar
|
|
{
|
|
/// <summary>
|
|
/// Represents the form in Office style with custom borders and caption.
|
|
/// </summary>
|
|
public class OfficeForm : RibbonForm
|
|
{
|
|
#region Private Variables
|
|
private int m_BorderWidth = 2;
|
|
private int m_CornerSize = 5;
|
|
private GenericItemContainer m_Caption = null;
|
|
private ColorScheme m_ColorScheme = null;
|
|
private LabelItem m_TitleLabel = null;
|
|
private SystemCaptionItem m_SystemIcon = null;
|
|
private SystemCaptionItem m_SystemButtons = null;
|
|
private Timer m_MouseTimer = null;
|
|
private Font m_CaptionFont = null;
|
|
private string m_TitleText = "";
|
|
#endregion
|
|
|
|
#region Constructor
|
|
public OfficeForm()
|
|
: base()
|
|
{
|
|
// This forces the initialization out of paint loop which speeds up how fast components show up
|
|
BaseRenderer renderer = Rendering.GlobalManager.Renderer;
|
|
|
|
m_BorderWidth = SystemInformation.Border3DSize.Width + NativeFunctions.BorderMultiplierFactor;
|
|
this.DockPadding.All = 0;
|
|
|
|
m_Caption = new GenericItemContainer();
|
|
m_Caption.GlobalItem = false;
|
|
m_Caption.ContainerControl = this;
|
|
m_Caption.WrapItems = false;
|
|
m_Caption.EventHeight = false;
|
|
m_Caption.UseMoreItemsButton = false;
|
|
m_Caption.Stretch = true;
|
|
m_Caption.Displayed = true;
|
|
m_Caption.SystemContainer = true;
|
|
m_Caption.PaddingTop = 0;
|
|
m_Caption.PaddingBottom = 0;
|
|
m_Caption.PaddingLeft = 2;
|
|
m_Caption.ItemSpacing = 1;
|
|
m_Caption.SetOwner(this);
|
|
m_Caption.Style = eDotNetBarStyle.StyleManagerControlled;
|
|
m_Caption.ToolbarItemsAlign = eContainerVerticalAlignment.Top;
|
|
|
|
m_SystemIcon = new SystemCaptionItem();
|
|
m_SystemIcon.GlobalItem = false;
|
|
m_SystemIcon.Enabled = false;
|
|
m_Caption.SubItems.Add(m_SystemIcon);
|
|
m_SystemIcon.IsSystemIcon = true;
|
|
m_SystemIcon.Icon = this.Icon;
|
|
|
|
m_TitleLabel = CreateTitleLabel();
|
|
m_Caption.SubItems.Add(m_TitleLabel);
|
|
|
|
CreateAdditionalCaptionItems(m_Caption);
|
|
|
|
m_SystemButtons = new SystemCaptionItem();
|
|
m_SystemButtons.GlobalItem = false;
|
|
//m_SystemButtons.ItemAlignment = eItemAlignment.Far;
|
|
m_SystemButtons.Click += new EventHandler(SystemButtons_Click);
|
|
m_SystemButtons.MouseEnter += new EventHandler(SystemButtons_MouseEnter);
|
|
m_Caption.SubItems.Add(m_SystemButtons);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
CleanupMdiClientHandler();
|
|
StopCaptionNCMouseTimer();
|
|
m_SystemButtons.Click -= new EventHandler(SystemButtons_Click);
|
|
m_SystemButtons.MouseEnter -= new EventHandler(SystemButtons_MouseEnter);
|
|
m_TitleLabel.MarkupLinkClick -= TitleLabelMarkupLinkClick;
|
|
m_Caption.Dispose();
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected virtual void CreateAdditionalCaptionItems(GenericItemContainer captionContainer)
|
|
{
|
|
}
|
|
|
|
protected virtual LabelItem CreateTitleLabel()
|
|
{
|
|
LabelItem label = new LabelItem();
|
|
label.GlobalItem = false;
|
|
label.Font = SystemFonts.CaptionFont;
|
|
label.Stretch = true;
|
|
label.TextLineAlignment = StringAlignment.Center;
|
|
label.Text = this.Text;
|
|
label.PaddingLeft = 3;
|
|
label.PaddingRight = 3;
|
|
label.MarkupLinkClick += TitleLabelMarkupLinkClick;
|
|
return label;
|
|
}
|
|
private void TitleLabelMarkupLinkClick(object sender, MarkupLinkClickEventArgs e)
|
|
{
|
|
OnTitleTextMarkupLinkClick(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by StyleManager to notify control that style on manager has changed and that control should refresh its appearance if
|
|
/// its style is controlled by StyleManager.
|
|
/// </summary>
|
|
/// <param name="newStyle">New active style.</param>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public override void StyleManagerStyleChanged(eDotNetBarStyle newStyle)
|
|
{
|
|
base.StyleManagerStyleChanged(newStyle);
|
|
this.RecalcSize();
|
|
InvalidateNonClient(true);
|
|
}
|
|
#endregion
|
|
|
|
#region Internal Implementation
|
|
protected override bool SetClientSizeCoreCustom(int x, int y)
|
|
{
|
|
TrackSetBoundsCore = true;
|
|
AdjustBounds(ref x, ref y);
|
|
return true; // Make sure base call is made
|
|
}
|
|
/// <summary>
|
|
/// Gets or sets the rich text displayed in form caption instead of the Form.Text property. This property supports text-markup.
|
|
/// You can use <font color="SysCaptionTextExtra"> markup to instruct the markup renderer to use Office 2007 system caption extra text color which
|
|
/// changes depending on the currently selected color table. Note that when using this property you should manage also the Form.Text property since
|
|
/// that is the text that will be displayed in Windows task-bar and elsewhere where system Form.Text property is used.
|
|
/// You can also use the hyperlinks as part of the text markup and handle the TitleTextMarkupLinkClick event to be notified when they are clicked.
|
|
/// Setting this property to an empty string (default value) indicates that Form.Text property will be used for form caption.
|
|
/// </summary>
|
|
[Browsable(true), DefaultValue(""), Editor("DevComponents.DotNetBar.Design.TextMarkupUIEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor)), EditorBrowsable(EditorBrowsableState.Always), Category("Appearance"), Description("Indicates text displayed in form caption instead of the Form.Text property.")]
|
|
public string TitleText
|
|
{
|
|
get { return m_TitleText; }
|
|
set
|
|
{
|
|
if (value == null) value = "";
|
|
|
|
m_TitleText = value;
|
|
if (value == "")
|
|
m_TitleLabel.Text = this.Text;
|
|
else
|
|
m_TitleLabel.Text = value;
|
|
if (this.IsHandleCreated) this.RecalcSize();
|
|
this.InvalidateNonClient(false);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Occurs when text-markup link in TitleText is clicked.
|
|
/// </summary>
|
|
public event MarkupLinkClickEventHandler TitleTextMarkupLinkClick;
|
|
/// <summary>
|
|
/// Raises TitleTextMarkupLinkClick event.
|
|
/// </summary>
|
|
/// <param name="e">Provides event arguments.</param>
|
|
protected virtual void OnTitleTextMarkupLinkClick(MarkupLinkClickEventArgs e)
|
|
{
|
|
MarkupLinkClickEventHandler handler = TitleTextMarkupLinkClick;
|
|
if (handler != null)
|
|
handler(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether custom form styling is enabled.
|
|
/// </summary>
|
|
/// <returns>true if custom styling is enabled otherwise false.</returns>
|
|
protected override bool IsCustomFormStyleEnabled()
|
|
{
|
|
return base.IsCustomFormStyleEnabled() && (!(WinApi.IsGlassEnabled && EnableGlass && !DesignMode) || this.IsMdiChild);
|
|
}
|
|
private bool _WasMdiChild = false, _UpdateFromGlassStateOnHandleCreated = false;
|
|
protected override void OnParentChanged(EventArgs e)
|
|
{
|
|
if (this.EnableGlass && WinApi.IsGlassEnabled)
|
|
{
|
|
if (this.IsHandleCreated)
|
|
UpdateFormGlassState();
|
|
else if (_WasMdiChild)
|
|
_UpdateFromGlassStateOnHandleCreated = true;
|
|
|
|
}
|
|
_WasMdiChild = IsMdiChild;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the font for the form caption text when CaptionVisible=true. Default value is NULL which means that system font is used.
|
|
/// </summary>
|
|
[Browsable(true), DefaultValue(null), Category("Caption"), Description("Indicates font for the form caption text when CaptionVisible=true.")]
|
|
public Font CaptionFont
|
|
{
|
|
get { return m_CaptionFont; }
|
|
set
|
|
{
|
|
m_CaptionFont = value;
|
|
OnCaptionFontChanged();
|
|
}
|
|
}
|
|
|
|
private void OnCaptionFontChanged()
|
|
{
|
|
if (m_TitleLabel != null)
|
|
{
|
|
if (m_CaptionFont != null)
|
|
m_TitleLabel.Font = m_CaptionFont;
|
|
else
|
|
{
|
|
#if FRAMEWORK20
|
|
m_TitleLabel.Font = SystemFonts.CaptionFont;
|
|
#else
|
|
m_TitleLabel.Font = SystemInformation.MenuFont;
|
|
#endif
|
|
}
|
|
this.Invalidate(m_Caption.DisplayRectangle);
|
|
}
|
|
InvalidateNonClient(false);
|
|
}
|
|
|
|
protected override void OnFontChanged(EventArgs e)
|
|
{
|
|
base.OnFontChanged(e);
|
|
InvalidateNonClient(false);
|
|
}
|
|
|
|
protected override bool WindowsMessageSetIcon(ref Message m)
|
|
{
|
|
UpdateSystemButton();
|
|
return base.WindowsMessageSetIcon(ref m);
|
|
}
|
|
#endregion
|
|
|
|
#region Non-client area handling
|
|
/// <summary>
|
|
/// Invalidates non client area of the form.
|
|
/// </summary>
|
|
/// <param name="invalidateForm">Indicates whether complete form is invalidated.</param>
|
|
public void InvalidateNonClient(bool invalidateForm)
|
|
{
|
|
if (!BarFunctions.IsHandleValid(this)) return;
|
|
const int RDW_INVALIDATE = 0x0001;
|
|
const int RDW_FRAME = 0x0400;
|
|
NativeFunctions.RECT r = new NativeFunctions.RECT(0, 0, this.Width, m_Caption.HeightInternal);
|
|
if(invalidateForm)
|
|
r = new NativeFunctions.RECT(0, 0, this.Width, this.Height);
|
|
NativeFunctions.RedrawWindow(this.Handle, ref r, IntPtr.Zero, RDW_INVALIDATE | RDW_FRAME);
|
|
}
|
|
|
|
protected override Rectangle ReduceDisplayRectangle(Rectangle r)
|
|
{
|
|
return r;
|
|
}
|
|
protected override void AdjustBounds(ref int width, ref int height, BoundsSpecified specified)
|
|
{
|
|
return;
|
|
//if(System.Environment.OSVersion.Version.Major == 6 && !IsCustomFormStyleEnabled())
|
|
// return;
|
|
|
|
//WinApi.RECT rect = new WinApi.RECT(0, 0, width, height);
|
|
//CreateParams params1 = this.CreateParams;
|
|
//WinApi.AdjustWindowRectEx(ref rect, params1.Style, false, params1.ExStyle);
|
|
|
|
//if ((specified & BoundsSpecified.Height) == BoundsSpecified.Height)
|
|
//{
|
|
// if (System.Environment.OSVersion.Version.Major == 6 && this.FormBorderStyle != FormBorderStyle.Sizable && !this.DesignMode)
|
|
// height -= (rect.Height - height - m_BorderWidth * 2 - (SystemInformation.CaptionHeight + 9));
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.FixedDialog && !this.DesignMode)
|
|
// height -= (rect.Height - height - m_BorderWidth * 2 - 1);
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.Fixed3D && !this.DesignMode)
|
|
// height -= (rect.Height - height - m_BorderWidth * 2) + 2;
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.FixedSingle && !this.DesignMode)
|
|
// height -= (rect.Height - height - m_BorderWidth * 2) + 2;
|
|
// else
|
|
// height -= (rect.Height - height - m_BorderWidth * 2 - (SystemInformation.CaptionHeight + 1) /*- (System.Environment.OSVersion.Version.Major == 6 ? SystemInformation.Border3DSize.Height : 0)*/);
|
|
//}
|
|
|
|
//if ((specified & BoundsSpecified.Width) == BoundsSpecified.Width)
|
|
//{
|
|
// if (System.Environment.OSVersion.Version.Major == 6 && FormBorderStyle != FormBorderStyle.Sizable && !this.DesignMode)
|
|
// width -= (rect.Width - width - m_BorderWidth * 2 - 9);
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.FixedDialog && !this.DesignMode)
|
|
// width -= (rect.Width - width - m_BorderWidth * 2 - 2) ;
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.Fixed3D && !this.DesignMode)
|
|
// width -= (rect.Width - width - m_BorderWidth * 2)+2;
|
|
// else if (!this.ControlBox && this.FormBorderStyle == FormBorderStyle.FixedSingle && !this.DesignMode)
|
|
// width -= (rect.Width - width - m_BorderWidth * 2) + 2;
|
|
// else
|
|
// width -= (rect.Width - width - m_BorderWidth * 2 /*- (System.Environment.OSVersion.Version.Major == 6 ? SystemInformation.Border3DSize.Width * 2 : 0)*/);
|
|
//}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether Vista glass effect extension over the ribbon control caption is enabled.
|
|
/// </summary>
|
|
protected override bool EnableGlassExtend
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
protected override bool WindowsMessageDwmCompositionChanged(ref Message m)
|
|
{
|
|
bool ret = base.WindowsMessageDwmCompositionChanged(ref m);
|
|
UpdateFormControlStyle();
|
|
return ret;
|
|
}
|
|
|
|
protected override bool WindowsMessageNCCalcSize(ref Message m)
|
|
{
|
|
if (m_SystemButtons != null)
|
|
m_SystemButtons.ToolWindowButtons =
|
|
(this.FormBorderStyle == System.Windows.Forms.FormBorderStyle.FixedToolWindow ||
|
|
this.FormBorderStyle == System.Windows.Forms.FormBorderStyle.SizableToolWindow);
|
|
return true; // There should be no need to do custom sizing since in designer any changes to non-client area size result in form size change
|
|
// Default implementation of ribbon form does not have non-client area at all...
|
|
//if (m.WParam == IntPtr.Zero)
|
|
//{
|
|
// WinApi.RECT r = (WinApi.RECT)Marshal.PtrToStructure(m.LParam, typeof(WinApi.RECT));
|
|
|
|
// WinApi.RECT newClientRect = WinApi.RECT.FromRectangle(GetClientRectangle(r.ToRectangle()));
|
|
|
|
// Marshal.StructureToPtr(newClientRect, m.LParam, false);
|
|
// m.Result = IntPtr.Zero;
|
|
//}
|
|
//else
|
|
//{
|
|
// WinApi.NCCALCSIZE_PARAMS csp;
|
|
// csp = (WinApi.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(WinApi.NCCALCSIZE_PARAMS));
|
|
|
|
// WinApi.WINDOWPOS pos = (WinApi.WINDOWPOS)Marshal.PtrToStructure(csp.lppos, typeof(WinApi.WINDOWPOS));
|
|
|
|
// WinApi.RECT newClientRect = WinApi.RECT.FromRectangle(GetClientRectangle(new Rectangle(pos.x, pos.y, pos.cx, pos.cy)));
|
|
// csp.rgrc0 = newClientRect;
|
|
// csp.rgrc1 = newClientRect;
|
|
// Marshal.StructureToPtr(csp, m.LParam, false);
|
|
// m.Result = new IntPtr((int)WinApi.WindowsMessages.WVR_VALIDRECTS);
|
|
//}
|
|
|
|
//return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when WM_NCACTIVATE message is received.
|
|
/// </summary>
|
|
/// <param name="m">Reference to message data.</param>
|
|
/// <returns>Return true to call base form implementation otherwise return false.</returns>
|
|
protected override bool WindowsMessageNCActivate(ref Message m)
|
|
{
|
|
if (m.WParam != IntPtr.Zero)
|
|
this.NonClientActive = true;
|
|
else
|
|
{
|
|
this.NonClientActive = false;
|
|
_LastNCMouseMove = DateTime.MinValue;
|
|
}
|
|
CreateCashedCaptionBitmap();
|
|
BaseWndProc(ref m);
|
|
DrawCashedCaptionBitmap();
|
|
//m.Result = new IntPtr(1);
|
|
//bool ret = base.WindowsMessageNCActivate(ref m);
|
|
if (NonClientPaintEnabled)
|
|
{
|
|
PaintNonClientAreaBuffered();
|
|
Redraw();
|
|
}
|
|
//if (this.IsMdiContainer)
|
|
//{
|
|
// this.Invalidate(new Rectangle(0, 0, this.Width, 32), true);
|
|
//}
|
|
//else
|
|
//{
|
|
// this.Invalidate(new Rectangle(0, 0, this.Width, 2), true);
|
|
//}
|
|
//this.Update();
|
|
return false;
|
|
}
|
|
|
|
#region Cashed Drawing of caption
|
|
private BufferedBitmap m_CashedCaptionBitmap = null;
|
|
private Point m_CashedCaptionBitmapLocation = Point.Empty;
|
|
private void CreateCashedCaptionBitmap()
|
|
{
|
|
if (m_CashedCaptionBitmap != null)
|
|
{
|
|
m_CashedCaptionBitmap.Dispose();
|
|
m_CashedCaptionBitmap = null;
|
|
}
|
|
if (m_Caption.DisplayRectangle.Width <= 0 || m_Caption.DisplayRectangle.Height <= 0 || !this.IsHandleCreated || this.IsDisposed)
|
|
return;
|
|
|
|
IntPtr dc = WinApi.GetWindowDC(this.Handle);
|
|
try
|
|
{
|
|
m_CashedCaptionBitmap = new BufferedBitmap(dc, new Rectangle(m_CashedCaptionBitmapLocation.X, m_CashedCaptionBitmapLocation.Y,
|
|
m_Caption.DisplayRectangle.Width, m_Caption.DisplayRectangle.Height));
|
|
}
|
|
finally
|
|
{
|
|
WinApi.ReleaseDC(this.Handle, dc);
|
|
}
|
|
|
|
PaintFormCaptionTo(m_CashedCaptionBitmap.Graphics);
|
|
}
|
|
private void DrawCashedCaptionBitmap()
|
|
{
|
|
if (m_CashedCaptionBitmap == null)
|
|
return;
|
|
IntPtr dc = WinApi.GetWindowDC(this.Handle);
|
|
using (Graphics g = Graphics.FromHdc(dc))
|
|
{
|
|
m_CashedCaptionBitmap.Render(g);
|
|
}
|
|
WinApi.ReleaseDC(this.Handle, dc);
|
|
|
|
m_CashedCaptionBitmap.Dispose();
|
|
m_CashedCaptionBitmap = null;
|
|
}
|
|
#endregion
|
|
|
|
protected override Rectangle GetClientRectangle(Rectangle rect)
|
|
{
|
|
NonClientInfo nci = GetNonClientInfo();
|
|
if (this.WindowState == FormWindowState.Minimized && this.IsMdiChild)
|
|
{
|
|
return new Rectangle(rect.X + nci.LeftBorder, rect.Y + nci.CaptionTotalHeight, rect.Width - (nci.LeftBorder + nci.RightBorder), 0);
|
|
}
|
|
return new Rectangle(rect.X + nci.LeftBorder, rect.Y + nci.CaptionTotalHeight,
|
|
rect.Width - (nci.LeftBorder + nci.RightBorder), rect.Height - (nci.CaptionTotalHeight + nci.BottomBorder));
|
|
|
|
//WinApi.RECT r = new WinApi.RECT(0, 0, rect.Width, rect.Height);
|
|
//CreateParams params1 = this.CreateParams;
|
|
//WinApi.AdjustWindowRectEx(ref r, params1.Style, false, params1.ExStyle);
|
|
|
|
//return new Rectangle(Math.Abs(r.Left), Math.Abs(r.Top), rect.Width - (r.Width - rect.Width), rect.Height - (r.Height - rect.Height));
|
|
|
|
|
|
//if (this.WindowState == FormWindowState.Maximized && this.IsMdiChild && System.Environment.OSVersion.Version.Major == 6)
|
|
//{
|
|
// rect.Inflate(-(m_BorderWidth + SystemInformation.Border3DSize.Width + 3), -(m_BorderWidth + SystemInformation.Border3DSize.Height + 2));
|
|
// rect.Y += SystemInformation.CaptionHeight + 1;
|
|
// rect.Height -= SystemInformation.CaptionHeight + 1;
|
|
//}
|
|
//else
|
|
//{
|
|
// rect.Inflate(-m_BorderWidth, -m_BorderWidth);
|
|
// rect.Y += SystemInformation.CaptionHeight + 1;
|
|
// rect.Height -= SystemInformation.CaptionHeight + 1;
|
|
//}
|
|
//return rect;
|
|
}
|
|
protected virtual bool UseCornerSize
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets the form path for the give input bounds.
|
|
/// </summary>
|
|
/// <param name="bounds">Represents the form bounds.</param>
|
|
/// <returns></returns>
|
|
protected override GraphicsPath GetFormPath(Rectangle bounds)
|
|
{
|
|
GraphicsPath path = new GraphicsPath();
|
|
Rectangle r = bounds;
|
|
|
|
if (!UseCornerSize || this.TopLeftCornerSize == 0 && TopRightCornerSize == 0)
|
|
{
|
|
path.AddRectangle(r);
|
|
return path;
|
|
}
|
|
ArcData arc = ElementStyleDisplay.GetCornerArc(r, m_CornerSize, eCornerArc.TopLeft);
|
|
path.AddArc(arc.X, arc.Y, arc.Width, arc.Height, arc.StartAngle, arc.SweepAngle);
|
|
|
|
arc = ElementStyleDisplay.GetCornerArc(r, m_CornerSize, eCornerArc.TopRight);
|
|
path.AddArc(arc.X, arc.Y, arc.Width, arc.Height, arc.StartAngle, arc.SweepAngle);
|
|
|
|
path.AddLine(r.Right, r.Bottom - 3, r.Right, r.Bottom);
|
|
path.AddLine(r.Right, r.Bottom, r.Right-3, r.Bottom);
|
|
|
|
path.AddLine(r.X + 3, r.Bottom, r.X, r.Bottom);
|
|
path.AddLine(r.X, r.Bottom, r.X, r.Bottom - 3);
|
|
|
|
path.CloseAllFigures();
|
|
|
|
return path;
|
|
}
|
|
|
|
private Point GetMousePosition()
|
|
{
|
|
if (this.IsDisposed)
|
|
return Point.Empty;
|
|
Point p = this.PointToClient(Control.MousePosition);
|
|
if (WindowState != FormWindowState.Minimized)
|
|
{
|
|
p.X += m_Caption.PaddingLeft; //m_BorderWidth;
|
|
p.Y += m_Caption.HeightInternal;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
private Timer _CaptionNCMouseTimer = null;
|
|
private bool CaptionNCMouseInside
|
|
{
|
|
get
|
|
{
|
|
return _CaptionNCMouseInside;
|
|
}
|
|
set
|
|
{
|
|
if (_CaptionNCMouseInside != value)
|
|
{
|
|
_CaptionNCMouseInside = value;
|
|
if (!_CaptionNCMouseInside)
|
|
{
|
|
StopCaptionNCMouseTimer();
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
else
|
|
StartCaptionNCMouseTimer();
|
|
}
|
|
}
|
|
}
|
|
private void StartCaptionNCMouseTimer()
|
|
{
|
|
if (_CaptionNCMouseTimer != null) return;
|
|
_CaptionNCMouseTimer = new Timer();
|
|
_CaptionNCMouseTimer.Interval = 300;
|
|
_CaptionNCMouseTimer.Tick += new EventHandler(NCMouseTimerTick);
|
|
_CaptionNCMouseTimer.Start();
|
|
}
|
|
private void NCMouseTimerTick(object sender, EventArgs e)
|
|
{
|
|
Point p = GetMousePosition();
|
|
if (!m_Caption.Bounds.Contains(p))
|
|
{
|
|
CaptionNCMouseInside = false;
|
|
}
|
|
}
|
|
private void StopCaptionNCMouseTimer()
|
|
{
|
|
Timer timer = _CaptionNCMouseTimer;
|
|
_CaptionNCMouseTimer = null;
|
|
if (timer == null) return;
|
|
timer.Stop();
|
|
timer.Tick -= NCMouseTimerTick;
|
|
timer.Dispose();
|
|
}
|
|
|
|
private DateTime _LastNCMouseMove = DateTime.MinValue;
|
|
private bool _CaptionNCMouseInside = false;
|
|
protected override bool WindowsMessageNCMouseMove(ref Message m)
|
|
{
|
|
Point p = GetMousePosition();
|
|
|
|
m_Caption.InternalMouseMove(new MouseEventArgs(Control.MouseButtons, 0, p.X, p.Y, 0));
|
|
CaptionNCMouseInside = true;
|
|
if (m_SystemIcon.Tooltip != "" && m_Caption.HotSubItem == m_SystemIcon)
|
|
{
|
|
SetupHoverTimer();
|
|
}
|
|
|
|
if (Control.MouseButtons == MouseButtons.Left)
|
|
{
|
|
BaseItem item = m_Caption.ItemAtLocation(p.X, p.Y);
|
|
if (item == m_TitleLabel && m_Caption.ItemAtLocation(_NcMouseDownPoint.X, _NcMouseDownPoint.Y)==item)
|
|
{
|
|
if (this.WindowState == FormWindowState.Normal || this.WindowState == FormWindowState.Minimized && this.IsMdiChild)
|
|
{
|
|
const int HTCAPTION = 2;
|
|
byte[] bx = BitConverter.GetBytes(p.X);
|
|
byte[] by = BitConverter.GetBytes(p.Y);
|
|
byte[] blp = new byte[] { bx[0], bx[1], by[0], by[1] };
|
|
int lParam = BitConverter.ToInt32(blp, 0);
|
|
this.Capture = false;
|
|
PopupManager.CloseAllPopups();
|
|
NativeFunctions.SendMessage(this.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MOVE + HTCAPTION, lParam);
|
|
return false;
|
|
}
|
|
else if (this.WindowState == FormWindowState.Maximized && BarFunctions.IsWindows7 && _IsActive)
|
|
{
|
|
if (_LastNCMouseMove != DateTime.MinValue)
|
|
{
|
|
if (DateTime.Now.Subtract(_LastNCMouseMove).TotalSeconds > 0)
|
|
{
|
|
this.WindowState = FormWindowState.Normal;
|
|
_LastNCMouseMove = DateTime.MinValue;
|
|
}
|
|
}
|
|
else
|
|
_LastNCMouseMove = DateTime.Now;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool _IsActive = false;
|
|
protected override void OnActivated(EventArgs e)
|
|
{
|
|
_IsActive = true;
|
|
base.OnActivated(e);
|
|
}
|
|
|
|
protected override bool WindowsMessageNCMouseLeave(ref Message m)
|
|
{
|
|
StopHoverTimer();
|
|
m_Caption.InternalMouseLeave();
|
|
CaptionNCMouseInside = false;
|
|
return true;
|
|
}
|
|
|
|
private Timer m_HoverTimer = null;
|
|
private void SetupHoverTimer()
|
|
{
|
|
if (m_HoverTimer != null)
|
|
{
|
|
m_HoverTimer.Stop();
|
|
m_HoverTimer.Start();
|
|
return;
|
|
}
|
|
m_HoverTimer = new Timer();
|
|
#if FRAMEWORK20
|
|
m_HoverTimer.Interval = Math.Max(500, SystemInformation.MouseHoverTime);
|
|
#else
|
|
m_HoverTimer.Interval = 600;
|
|
#endif
|
|
m_HoverTimer.Tick += new EventHandler(HoverTimer_Tick);
|
|
m_HoverTimer.Start();
|
|
}
|
|
|
|
private void HoverTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
m_HoverTimer.Stop();
|
|
if (m_SystemIcon != null && m_SystemIcon.Tooltip != "" && m_Caption != null && m_Caption.HotSubItem == m_SystemIcon)
|
|
{
|
|
m_Caption.InternalMouseHover();
|
|
}
|
|
StopHoverTimer();
|
|
}
|
|
|
|
private void StopHoverTimer()
|
|
{
|
|
Timer t = m_HoverTimer;
|
|
if (m_HoverTimer != null)
|
|
{
|
|
m_HoverTimer = null;
|
|
t.Stop();
|
|
t.Tick -= new EventHandler(HoverTimer_Tick);
|
|
}
|
|
}
|
|
|
|
protected override bool WindowsMessageNCHitTest(ref Message m)
|
|
{
|
|
// Get position being tested...
|
|
int x = WinApi.LOWORD(m.LParam);
|
|
int y = WinApi.HIWORD(m.LParam);
|
|
|
|
Point p = PointToClient(new Point(x, y));
|
|
if (this.WindowState != FormWindowState.Minimized)
|
|
{
|
|
p.X += m_BorderWidth;
|
|
p.Y += m_BorderWidth + SystemInformation.CaptionHeight;
|
|
}
|
|
|
|
int borderSize = m_BorderWidth;
|
|
int cornerPadding = 2;
|
|
|
|
if (IsSizable)
|
|
{
|
|
#if FRAMEWORK20
|
|
if (this.RightToLeftLayout && this.RightToLeft == RightToLeft.Yes)
|
|
#else
|
|
if (this.RightToLeft == RightToLeft.Yes)
|
|
#endif
|
|
{
|
|
// Top-left corner
|
|
Rectangle r = new Rectangle(this.Width - (m_CornerSize + cornerPadding), 0, (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding));
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopLeftSizeableCorner);
|
|
return false;
|
|
}
|
|
// Top Right
|
|
r = new Rectangle(0, 0, (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding));
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopRightSizeableCorner);
|
|
return false;
|
|
}
|
|
// Bottom Left
|
|
r = new Rectangle(this.Width - (m_CornerSize + cornerPadding), this.Height - (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding));
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomLeftSizeableCorner);
|
|
return false;
|
|
}
|
|
// Bottom Right
|
|
r = new Rectangle(0, this.Height - (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding), (m_CornerSize + cornerPadding));
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomRightSizeableCorner);
|
|
return false;
|
|
}
|
|
|
|
// Left border
|
|
r = new Rectangle(this.Width - borderSize, 0, borderSize, this.Height);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.LeftSizeableBorder);
|
|
return false;
|
|
}
|
|
// Right border
|
|
r = new Rectangle(0, 0, borderSize, this.Height);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.RightSizeableBorder);
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Top-left corner
|
|
Rectangle r = new Rectangle(0, 0, m_CornerSize + cornerPadding, m_CornerSize + cornerPadding);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopLeftSizeableCorner);
|
|
return false;
|
|
}
|
|
// Top Right
|
|
r = new Rectangle(this.Width - (m_CornerSize + cornerPadding), 0, m_CornerSize + cornerPadding, m_CornerSize + cornerPadding);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopRightSizeableCorner);
|
|
return false;
|
|
}
|
|
// Bottom Left
|
|
r = new Rectangle(0, this.Height - m_CornerSize, m_CornerSize + cornerPadding, m_CornerSize + cornerPadding);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomLeftSizeableCorner);
|
|
return false;
|
|
}
|
|
// Bottom Right
|
|
r = new Rectangle(this.Width - m_CornerSize, this.Height - m_CornerSize, m_CornerSize + cornerPadding, m_CornerSize + cornerPadding);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomRightSizeableCorner);
|
|
return false;
|
|
}
|
|
|
|
// Top border
|
|
r = new Rectangle(0, 0, this.Width, borderSize);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TopSizeableBorder);
|
|
return false;
|
|
}
|
|
// Bottom border
|
|
r = new Rectangle(0, this.Height - borderSize, this.Width, borderSize);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.BottomSizeableBorder);
|
|
return false;
|
|
}
|
|
// Left border
|
|
r = new Rectangle(0, 0, borderSize, this.Height);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.LeftSizeableBorder);
|
|
return false;
|
|
}
|
|
// Right border
|
|
r = new Rectangle(this.Width - borderSize, 0, borderSize, this.Height);
|
|
if (r.Contains(p))
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.RightSizeableBorder);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
BaseItem item=m_Caption.ItemAtLocation(p.X, p.Y);
|
|
if (item == m_TitleLabel)
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.TitleBar);
|
|
return false;
|
|
}
|
|
else if (item == m_SystemIcon)
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.Menu);
|
|
return false;
|
|
}
|
|
else if (item == m_SystemButtons)
|
|
{
|
|
SystemButton btn = m_SystemButtons.GetButton(p.X, p.Y);
|
|
if (btn == SystemButton.Minimize)
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.MinimizeButton);
|
|
else if (btn == SystemButton.Maximize)
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.MaximizeButton);
|
|
else if (btn == SystemButton.Close)
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.CloseButton);
|
|
else if (btn == SystemButton.Restore)
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.ReduceButton);
|
|
else if (btn == SystemButton.Help)
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.HelpButton);
|
|
|
|
return false;
|
|
}
|
|
else if (item is ButtonItem)
|
|
{
|
|
m.Result = new IntPtr((int)WinApi.WindowHitTestRegions.Object);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
private Point _NcMouseDownPoint = Point.Empty;
|
|
protected override bool WindowsMessageNCLButtonDown(ref Message m)
|
|
{
|
|
int wParamInt = WinApi.ToInt(m.WParam);
|
|
if (wParamInt == (int)WinApi.WindowHitTestRegions.TopSizeableBorder ||
|
|
wParamInt == (int)WinApi.WindowHitTestRegions.TopRightSizeableCorner) return true;
|
|
Point p = GetMousePosition();
|
|
_NcMouseDownPoint = p;
|
|
m_Caption.InternalMouseDown(new MouseEventArgs(MouseButtons.Left, 0, p.X, p.Y, 0));
|
|
|
|
BaseItem item = m_Caption.ItemAtLocation(p.X, p.Y);
|
|
if (item != null && (item == m_SystemButtons || item == m_TitleLabel || p.X >= m_SystemButtons.DisplayRectangle.X && p.X <= m_SystemButtons.DisplayRectangle.Right))
|
|
{
|
|
if (!this.NonClientActive)
|
|
this.Activate();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected override bool WindowsMessageNCLButtonUp(ref Message m)
|
|
{
|
|
Point p = GetMousePosition();
|
|
BaseItem item = m_Caption.ItemAtLocation(p.X, p.Y);
|
|
|
|
m_Caption.InternalMouseUp(new MouseEventArgs(MouseButtons.Left, 0, p.X, p.Y, 0));
|
|
|
|
if (p == _NcMouseDownPoint && !string.IsNullOrEmpty(this.TitleText))
|
|
m_Caption.InternalClick(MouseButtons.Left, p);
|
|
|
|
if (item == m_SystemButtons)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private void SystemButtons_Click(object sender, EventArgs e)
|
|
{
|
|
SystemCaptionItem sci = sender as SystemCaptionItem;
|
|
Form frm = this;
|
|
|
|
if (sci.MouseDownButton == SystemButton.Minimize)
|
|
{
|
|
NativeFunctions.PostMessage(frm.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MINIMIZE, 0);
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
else if (sci.MouseDownButton == SystemButton.Maximize)
|
|
{
|
|
NativeFunctions.PostMessage(frm.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_MAXIMIZE, 0);
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
else if (sci.MouseDownButton == SystemButton.Restore)
|
|
{
|
|
NativeFunctions.PostMessage(frm.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_RESTORE, 0);
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
else if (sci.MouseDownButton == SystemButton.Close)
|
|
{
|
|
NativeFunctions.PostMessage(frm.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_CLOSE, 0);
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
else if (sci.MouseDownButton == SystemButton.Help)
|
|
{
|
|
NativeFunctions.PostMessage(frm.Handle, NativeFunctions.WM_SYSCOMMAND, NativeFunctions.SC_CONTEXTHELP, 0);
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
}
|
|
|
|
private void SystemButtons_MouseEnter(object sender, EventArgs e)
|
|
{
|
|
if (m_MouseTimer == null)
|
|
SetupMouseTimer();
|
|
}
|
|
|
|
private void SetupMouseTimer()
|
|
{
|
|
m_MouseTimer = new Timer();
|
|
m_MouseTimer.Interval = 200;
|
|
m_MouseTimer.Tick += new EventHandler(MouseTimer_Tick);
|
|
m_MouseTimer.Start();
|
|
}
|
|
|
|
private void MouseTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
Point p = GetMousePosition();
|
|
if (m_SystemButtons != null && !m_SystemButtons.DisplayRectangle.Contains(p))
|
|
{
|
|
m_MouseTimer.Enabled = false;
|
|
StopMouseTimer();
|
|
|
|
m_SystemButtons.InternalMouseLeave();
|
|
}
|
|
}
|
|
|
|
private void StopMouseTimer()
|
|
{
|
|
if (m_MouseTimer != null)
|
|
{
|
|
m_MouseTimer.Enabled = false;
|
|
m_MouseTimer.Tick -= new EventHandler(MouseTimer_Tick);
|
|
m_MouseTimer.Dispose();
|
|
m_MouseTimer = null;
|
|
}
|
|
}
|
|
|
|
protected override void OnVisibleChanged(EventArgs e)
|
|
{
|
|
if (!this.Visible)
|
|
{
|
|
StopMouseTimer();
|
|
StopCaptionNCMouseTimer();
|
|
}
|
|
base.OnVisibleChanged(e);
|
|
}
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
{
|
|
this.StopMouseTimer();
|
|
base.OnClosed(e);
|
|
}
|
|
|
|
protected override void OnResize(EventArgs e)
|
|
{
|
|
RecalcSize();
|
|
|
|
base.OnResize(e);
|
|
}
|
|
|
|
internal void RecalcSize()
|
|
{
|
|
if (!this.IsHandleCreated) return;
|
|
if (m_Caption != null)
|
|
{
|
|
NonClientInfo nci = GetNonClientInfo();
|
|
m_Caption.LeftInternal = 1;
|
|
m_Caption.TopInternal = 0;
|
|
m_Caption.PaddingLeft = Dpi.DescaleWidth(nci.LeftBorder) - 1;
|
|
m_Caption.PaddingRight = Dpi.DescaleWidth(nci.RightBorder);
|
|
m_Caption.PaddingTop = Dpi.DescaleHeight(nci.BottomBorder)/2 + 1;
|
|
m_Caption.WidthInternal = this.Width - 1;
|
|
m_Caption.HeightInternal = nci.CaptionTotalHeight - nci.BottomBorder / 2;
|
|
m_Caption.IsRightToLeft = (this.RightToLeft == RightToLeft.Yes);
|
|
m_Caption.OverflowEnabled = false;
|
|
if (m_TitleLabel != null)
|
|
{
|
|
m_TitleLabel.Height = Dpi.DescaleHeight(m_Caption.HeightInternal - nci.BottomBorder-2);
|
|
if (m_TitleText != "")
|
|
m_TitleLabel.Width = 0;
|
|
else
|
|
m_TitleLabel.Width = 16;
|
|
m_TitleLabel.TextLineAlignment = StringAlignment.Center;
|
|
}
|
|
|
|
m_Caption.RecalcSize();
|
|
m_Caption.HeightInternal = nci.CaptionTotalHeight;
|
|
if (m_SystemIcon != null)
|
|
m_SystemIcon.TopInternal += (m_Caption.HeightInternal - m_SystemIcon.HeightInternal - nci.BottomBorder * 2) / 2 + 1;
|
|
m_TitleLabel.TopInternal+=Dpi.Height1;
|
|
|
|
if (this.WindowState == FormWindowState.Maximized)
|
|
{
|
|
if (m_SystemIcon != null)
|
|
m_SystemIcon.TopInternal += Dpi.Height2;
|
|
m_TitleLabel.TopInternal += Dpi.Height2;
|
|
}
|
|
|
|
if (FormBorderStyle != FormBorderStyle.FixedSingle)
|
|
{
|
|
m_SystemButtons.TopInternal -= Dpi.Height1;
|
|
}
|
|
}
|
|
|
|
if (this.WindowState == FormWindowState.Maximized || this.WindowState == FormWindowState.Minimized)
|
|
m_SystemButtons.RestoreEnabled = true;
|
|
else
|
|
m_SystemButtons.RestoreEnabled = false;
|
|
}
|
|
|
|
protected override void OnMouseLeave(EventArgs e)
|
|
{
|
|
m_Caption.InternalMouseLeave();
|
|
base.OnMouseLeave(e);
|
|
}
|
|
|
|
protected override void OnDeactivate(EventArgs e)
|
|
{
|
|
_IsActive = false;
|
|
base.OnDeactivate(e);
|
|
StopMouseTimer();
|
|
m_Caption.InternalMouseLeave();
|
|
}
|
|
|
|
protected override void OnTextChanged(EventArgs e)
|
|
{
|
|
base.OnTextChanged(e);
|
|
UpdateFormText();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the form title bar text. Usually calling this method is not necessary but under certain conditions when form is used as MDI parent form
|
|
/// calling it to update combined text is necessary.
|
|
/// </summary>
|
|
public void UpdateFormText()
|
|
{
|
|
bool changed = false;
|
|
if (m_TitleLabel != null && m_TitleText == "")
|
|
{
|
|
changed = m_TitleLabel.Text != this.Text;
|
|
m_TitleLabel.Text = this.Text;
|
|
}
|
|
if (changed)
|
|
{
|
|
if (this.IsMdiChild && this.MdiParent is RibbonForm)
|
|
{
|
|
((RibbonForm)this.MdiParent).InvalidateRibbonCaption();
|
|
}
|
|
InvalidateNonClient(false);
|
|
}
|
|
}
|
|
protected override void OnControlRemoved(ControlEventArgs e)
|
|
{
|
|
if (e.Control is MdiClient)
|
|
{
|
|
e.Control.ControlRemoved -= MdiClientControlRemoved;
|
|
e.Control.ControlAdded -= MdiClientControlAdded;
|
|
e.Control.HandleCreated -= MdiClientHandleCreated;
|
|
CleanupMdiClientHandler();
|
|
}
|
|
base.OnControlRemoved(e);
|
|
}
|
|
protected override void OnControlAdded(ControlEventArgs e)
|
|
{
|
|
if (e.Control is MdiClient)
|
|
{
|
|
e.Control.ControlRemoved += MdiClientControlRemoved;
|
|
e.Control.ControlAdded += MdiClientControlAdded;
|
|
e.Control.HandleCreated += MdiClientHandleCreated;
|
|
SetupMdiClientHandler((MdiClient)e.Control);
|
|
}
|
|
base.OnControlAdded(e);
|
|
}
|
|
|
|
private void CleanupMdiClientHandler()
|
|
{
|
|
if (_MdiHandler != null)
|
|
{
|
|
_MdiHandler.MdiSetMenu -= this.OnMdiSetMenu;
|
|
_MdiHandler.ReleaseHandle();
|
|
_MdiHandler = null;
|
|
}
|
|
}
|
|
private void SetupMdiClientHandler(MdiClient mdiClient)
|
|
{
|
|
if (mdiClient.IsHandleCreated)
|
|
SubclassMdiClient(mdiClient);
|
|
}
|
|
private bool _HideMdiSystemMenu = true;
|
|
[DefaultValue(true), Browsable(false)]
|
|
public bool HideMdiSystemMenu
|
|
{
|
|
get { return _HideMdiSystemMenu; }
|
|
set
|
|
{
|
|
_HideMdiSystemMenu = value;
|
|
}
|
|
}
|
|
|
|
private void OnMdiSetMenu(object sender, System.EventArgs e)
|
|
{
|
|
MDIClientMsgHandler m = sender as MDIClientMsgHandler;
|
|
if (_HideMdiSystemMenu)
|
|
m.EatMessage = true;
|
|
}
|
|
private MDIClientMsgHandler _MdiHandler = null;
|
|
private void SubclassMdiClient(MdiClient client)
|
|
{
|
|
CleanupMdiClientHandler();
|
|
_MdiHandler = new MDIClientMsgHandler();
|
|
_MdiHandler.MdiSetMenu += new EventHandler(this.OnMdiSetMenu);
|
|
_MdiHandler.AssignHandle(client.Handle);
|
|
}
|
|
private void MdiClientHandleCreated(object sender, EventArgs e)
|
|
{
|
|
SubclassMdiClient((MdiClient)sender);
|
|
}
|
|
|
|
private void MdiClientControlRemoved(object sender, ControlEventArgs e)
|
|
{
|
|
e.Control.Resize -= new EventHandler(MdiChildResize);
|
|
}
|
|
private void MdiClientControlAdded(object sender, ControlEventArgs e)
|
|
{
|
|
e.Control.Resize += new EventHandler(MdiChildResize);
|
|
}
|
|
|
|
protected override void OnMdiChildActivate(EventArgs e)
|
|
{
|
|
UpdateFormText();
|
|
base.OnMdiChildActivate(e);
|
|
}
|
|
|
|
private void MdiChildResize(object sender, EventArgs e)
|
|
{
|
|
InvokeDelayed(new MethodInvoker(delegate { UpdateFormText(); }));
|
|
}
|
|
|
|
protected override void OnStyleChanged(EventArgs e)
|
|
{
|
|
UpdateSystemButton();
|
|
InvalidateNonClient(false);
|
|
base.OnStyleChanged(e);
|
|
}
|
|
|
|
protected override void OnSystemColorsChanged(EventArgs e)
|
|
{
|
|
OnCaptionFontChanged();
|
|
base.OnSystemColorsChanged(e);
|
|
}
|
|
|
|
protected override void OnHandleCreated(EventArgs e)
|
|
{
|
|
UpdateSystemButton();
|
|
if (_UpdateFromGlassStateOnHandleCreated)
|
|
{
|
|
_UpdateFromGlassStateOnHandleCreated = false;
|
|
UpdateFormGlassState();
|
|
}
|
|
base.OnHandleCreated(e);
|
|
}
|
|
protected override void OnRenderFormIconChanged(bool oldValue, bool newValue)
|
|
{
|
|
UpdateSystemButton();
|
|
base.OnRenderFormIconChanged(oldValue, newValue);
|
|
}
|
|
protected override void OnRenderFormTextChanged(bool oldValue, bool newValue)
|
|
{
|
|
UpdateSystemButton();
|
|
base.OnRenderFormTextChanged(oldValue, newValue);
|
|
}
|
|
private void UpdateSystemButton()
|
|
{
|
|
if (m_SystemButtons != null)
|
|
{
|
|
m_SystemButtons.MinimizeVisible = this.MinimizeBox;
|
|
m_SystemButtons.RestoreMaximizeVisible = this.MaximizeBox;
|
|
|
|
m_SystemButtons.Visible = this.ControlBox;
|
|
m_SystemIcon.Visible = this.ControlBox;
|
|
|
|
m_SystemButtons.HelpVisible = this.HelpButton;
|
|
}
|
|
|
|
#if FRAMEWORK20
|
|
if (m_SystemIcon != null)
|
|
{
|
|
m_SystemIcon.Visible = this.ShowIcon && this.RenderFormIcon;
|
|
}
|
|
#endif
|
|
if (this.FormBorderStyle == FormBorderStyle.FixedDialog)
|
|
m_SystemIcon.Visible = false;
|
|
|
|
if (m_TitleLabel != null)
|
|
m_TitleLabel.IsRendered = this.RenderFormText;
|
|
|
|
if (this.IsHandleCreated)
|
|
RecalcSize();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the icon for the form.
|
|
/// </summary>
|
|
[Browsable(true)]
|
|
public new Icon Icon
|
|
{
|
|
get { return base.Icon; }
|
|
set
|
|
{
|
|
base.Icon = value;
|
|
m_SystemIcon.Icon = value;
|
|
UpdateSystemButton();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether the form enables auto scrolling.
|
|
/// </summary>
|
|
[Browsable(false), DefaultValue(false)]
|
|
public override bool AutoScroll
|
|
{
|
|
get { return base.AutoScroll; }
|
|
set { base.AutoScroll = value; }
|
|
}
|
|
|
|
protected internal bool CloseEnabled
|
|
{
|
|
get
|
|
{
|
|
return m_SystemButtons.CloseEnabled;
|
|
}
|
|
set
|
|
{
|
|
if (m_SystemButtons.CloseEnabled != value)
|
|
{
|
|
m_SystemButtons.CloseEnabled = value;
|
|
OnCloseEnabledChanged();
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when CloseEnabled property value has changed.
|
|
/// </summary>
|
|
protected virtual void OnCloseEnabledChanged()
|
|
{
|
|
if (!BarFunctions.IsHandleValid(this)) return;
|
|
|
|
IntPtr handle = this.Handle;
|
|
IntPtr menuHandle = NativeFunctions.GetSystemMenu(handle, false);
|
|
uint flags = 0;
|
|
const uint MF_BYCOMMAND = 0x0;
|
|
const uint MF_GRAYED = 0x1;
|
|
if (CloseEnabled)
|
|
{
|
|
flags = MF_BYCOMMAND | ~MF_GRAYED;
|
|
}
|
|
else
|
|
{
|
|
flags = MF_BYCOMMAND | MF_GRAYED;
|
|
}
|
|
WinApi.EnableMenuItem(menuHandle, NativeFunctions.SC_CLOSE, flags);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Office 2007 Renderer global Color Table. Setting this property will affect all controls in application that are using Office 2007 global renderer.
|
|
/// </summary>
|
|
[Browsable(false), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Description("Indicates the Office 2007 Renderer global Color Table.")]
|
|
public Rendering.eOffice2007ColorScheme Office2007ColorTable
|
|
{
|
|
get
|
|
{
|
|
Rendering.Office2007Renderer r = this.GetRenderer() as Rendering.Office2007Renderer;
|
|
if (r != null)
|
|
return r.ColorTable.InitialColorScheme;
|
|
return Rendering.eOffice2007ColorScheme.Blue;
|
|
}
|
|
set
|
|
{
|
|
#if (FRAMEWORK20)
|
|
RibbonPredefinedColorSchemes.ChangeOffice2007ColorTable(value);
|
|
#else
|
|
RibbonPredefinedColorSchemes.ChangeOffice2007ColorTable(this, value);
|
|
#endif
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Non-client area painting
|
|
/// <summary>
|
|
/// Gets whether client border is painted in OnPaint method.
|
|
/// </summary>
|
|
protected override bool PaintClientBorder
|
|
{
|
|
get { return false; }
|
|
}
|
|
/// <summary>
|
|
/// Gets whether ribbon control caption is painted
|
|
/// </summary>
|
|
protected override bool PaintRibbonCaption
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Paints the non-client area of the form.
|
|
/// </summary>
|
|
protected override bool WindowsMessageNCPaint(ref Message m)
|
|
{
|
|
m.Result = IntPtr.Zero;
|
|
|
|
if (this.IsHandleCreated && !this.IsDisposed && this.Handle != IntPtr.Zero && this.EnableCustomStyle && NonClientPaintEnabled)
|
|
{
|
|
PaintNonClientAreaBuffered();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected virtual void PaintNonClientAreaBuffered()
|
|
{
|
|
IntPtr dc = WinApi.GetWindowDC(this.Handle);
|
|
try
|
|
{
|
|
using (Graphics g = Graphics.FromHdc(dc))
|
|
{
|
|
PaintNonClientAreaBuffered(g);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
WinApi.ReleaseDC(this.Handle, dc);
|
|
}
|
|
}
|
|
|
|
protected virtual void PaintNonClientAreaBuffered(Graphics targetGraphics)
|
|
{
|
|
BufferedBitmap bmp = new BufferedBitmap(targetGraphics, new Rectangle(0,0,this.Width, this.Height));
|
|
try
|
|
{
|
|
bmp.Graphics.SetClip(this.GetClientRectangle(new Rectangle(0, 0, this.Width, this.Height)), CombineMode.Exclude);
|
|
PaintNonClientArea(bmp.Graphics);
|
|
|
|
bmp.Render(targetGraphics, this.GetClientRectangle(new Rectangle(0, 0, this.Width, this.Height)));
|
|
}
|
|
finally
|
|
{
|
|
bmp.Dispose();
|
|
}
|
|
}
|
|
|
|
protected virtual Rectangle GetInnerFormBounds()
|
|
{
|
|
//NonClientInfo nci = GetNonClientInfo();
|
|
//return new Rectangle(nci.LeftBorder, nci.BottomBorder, this.Width - (nci.LeftBorder + nci.RightBorder + 1), this.Height - nci.BottomBorder * 2);
|
|
|
|
Rectangle r = new Rectangle(1, 1, this.Width - 3, this.Height - 1);
|
|
|
|
#if FRAMEWORK20
|
|
if (this.RightToLeftLayout) r = new Rectangle(1, 1, this.Width - 2, this.Height - 1);
|
|
#endif
|
|
|
|
return r;
|
|
}
|
|
|
|
protected virtual void PaintNonClientArea(Graphics g)
|
|
{
|
|
NonClientInfo nci = GetNonClientInfo();
|
|
PaintFormBorder(g, nci.LeftBorder, false);
|
|
//PaintFormCaptionTo(g);
|
|
Rectangle r = GetInnerFormBounds();
|
|
if (m_CornerSize > 1 && UseCornerSize)
|
|
m_CornerSize--;
|
|
using (GraphicsPath path = GetFormPath(r))
|
|
{
|
|
if (m_CornerSize > 0 && UseCornerSize)
|
|
m_CornerSize++;
|
|
Region reg = new Region();
|
|
reg.MakeEmpty();
|
|
reg.Union(path);
|
|
// Widen path for the border...
|
|
path.Widen(SystemPens.Control);
|
|
Region r2 = new Region(path);
|
|
reg.Union(path);
|
|
g.SetClip(reg, CombineMode.Replace);
|
|
|
|
PaintFormCaptionTo(g);
|
|
}
|
|
g.ResetClip();
|
|
}
|
|
|
|
private bool m_AntiAlias = true;
|
|
/// <summary>
|
|
/// Gets or sets whether anti-alias smoothing is used while painting form caption. Default value is true.
|
|
/// </summary>
|
|
[DefaultValue(true), Browsable(true), Category("Appearance"), Description("Gets or sets whether anti-aliasing is used while painting form caption.")]
|
|
public bool CaptionAntiAlias
|
|
{
|
|
get { return m_AntiAlias; }
|
|
set
|
|
{
|
|
if (m_AntiAlias != value)
|
|
{
|
|
m_AntiAlias = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PaintFormCaptionTo(Graphics g)
|
|
{
|
|
ItemPaintArgs p = GetItemPaintArgs(g);
|
|
|
|
SmoothingMode sm = g.SmoothingMode;
|
|
System.Drawing.Text.TextRenderingHint th = g.TextRenderingHint;
|
|
|
|
if (m_AntiAlias)
|
|
{
|
|
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
// Setting this disables the Clear-Type rendering on other controls on form. Do not do it.
|
|
//g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint;
|
|
}
|
|
|
|
if (p.Renderer != null)
|
|
{
|
|
if (p.Renderer is Office2007Renderer)
|
|
{
|
|
if (NonClientActive)
|
|
m_TitleLabel.ForeColor = ((Office2007Renderer)p.Renderer).ColorTable.Form.Active.CaptionText;
|
|
else
|
|
m_TitleLabel.ForeColor = ((Office2007Renderer)p.Renderer).ColorTable.Form.Inactive.CaptionText;
|
|
}
|
|
|
|
p.Renderer.DrawFormCaptionBackground(new FormCaptionRendererEventArgs(g, m_Caption.DisplayRectangle, this));
|
|
}
|
|
|
|
int nciLeftBorder = 0;
|
|
if (this.BackgroundImage != null && this.BackgroundImageUnderCaption ||
|
|
StyleManager.IsMetro(StyleManager.Style))
|
|
{
|
|
NonClientInfo nci = GetNonClientInfo();
|
|
nciLeftBorder = nci.LeftBorder;
|
|
}
|
|
|
|
PaintNonClientBackgroundImage(g, this.ClientRectangle);
|
|
|
|
if (this.BackgroundImage != null && this.BackgroundImageUnderCaption || StyleManager.IsMetro(StyleManager.Style))
|
|
{
|
|
PaintFormBorder(g, nciLeftBorder, true);
|
|
}
|
|
|
|
m_Caption.Paint(p);
|
|
|
|
//if (m_AntiAlias)
|
|
{
|
|
g.SmoothingMode = sm;
|
|
//g.TextRenderingHint = th;
|
|
}
|
|
}
|
|
|
|
private ItemPaintArgs GetItemPaintArgs(Graphics g)
|
|
{
|
|
ItemPaintArgs pa = new ItemPaintArgs(null, this, g, GetColorScheme());
|
|
pa.Renderer = this.GetRenderer();
|
|
return pa;
|
|
}
|
|
|
|
protected virtual ColorScheme GetColorScheme()
|
|
{
|
|
if (m_ColorScheme == null)
|
|
{
|
|
if (GlobalManager.Renderer is Office2007Renderer)
|
|
return ((Office2007Renderer)GlobalManager.Renderer).ColorTable.LegacyColors;
|
|
return new ColorScheme(eDotNetBarStyle.Office2007);
|
|
}
|
|
else
|
|
return m_ColorScheme;
|
|
}
|
|
|
|
private Rendering.BaseRenderer m_DefaultRenderer = null;
|
|
private Rendering.BaseRenderer m_Renderer = null;
|
|
private eRenderMode m_RenderMode = eRenderMode.Global;
|
|
/// <summary>
|
|
/// Returns the renderer control will be rendered with.
|
|
/// </summary>
|
|
/// <returns>The current renderer.</returns>
|
|
public virtual Rendering.BaseRenderer GetRenderer()
|
|
{
|
|
if (m_RenderMode == eRenderMode.Global && Rendering.GlobalManager.Renderer != null)
|
|
return Rendering.GlobalManager.Renderer;
|
|
else if (m_RenderMode == eRenderMode.Custom && m_Renderer != null)
|
|
return m_Renderer;
|
|
|
|
if (m_DefaultRenderer == null)
|
|
m_DefaultRenderer = new Rendering.Office2007Renderer();
|
|
|
|
return m_Renderer;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the redering mode used by control. Default value is eRenderMode.Global which means that static GlobalManager.Renderer is used. If set to Custom then Renderer property must
|
|
/// also be set to the custom renderer that will be used.
|
|
/// </summary>
|
|
[Browsable(false), DefaultValue(eRenderMode.Global)]
|
|
public eRenderMode RenderMode
|
|
{
|
|
get { return m_RenderMode; }
|
|
set
|
|
{
|
|
if (m_RenderMode != value)
|
|
{
|
|
m_RenderMode = value;
|
|
this.Invalidate(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the custom renderer used by the items on this control. RenderMode property must also be set to eRenderMode.Custom in order renderer
|
|
/// specified here to be used.
|
|
/// </summary>
|
|
[Browsable(false), DefaultValue(null)]
|
|
public DevComponents.DotNetBar.Rendering.BaseRenderer Renderer
|
|
{
|
|
get
|
|
{
|
|
return m_Renderer;
|
|
}
|
|
set { m_Renderer = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the tooltip for the form system icon.
|
|
/// </summary>
|
|
[Browsable(true), DefaultValue(""), Description("Indicates tooltip for the form system icon."), Localizable(true)]
|
|
public string IconTooltip
|
|
{
|
|
get { return m_SystemIcon.Tooltip; }
|
|
set { m_SystemIcon.Tooltip = value; }
|
|
}
|
|
|
|
///// <summary>
|
|
///// Gets the array of LinearGradientColorTable objects that describe the border colors. The colors with index 0 is used as the outer most
|
|
///// border.
|
|
///// </summary>
|
|
///// <returns>Array of LinearGradientColorTable</returns>
|
|
//protected override LinearGradientColorTable[] GetBorderColors()
|
|
//{
|
|
// LinearGradientColorTable[] colors = base.GetBorderColors();
|
|
|
|
// RECT rect = new RECT(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
|
|
// CreateParams params1 = this.CreateParams;
|
|
// AdjustWindowRectEx(ref rect, params1.Style, false, params1.ExStyle);
|
|
|
|
// int borderWidth = Math.Abs(rect.Left);
|
|
// if (colors.Length < borderWidth)
|
|
// {
|
|
// LinearGradientColorTable[] cn = new LinearGradientColorTable[borderWidth];
|
|
// LinearGradientColorTable innerColor = colors[colors.Length-1];
|
|
// colors.CopyTo(cn, 0);
|
|
// for (int i = colors.Length; i < borderWidth; i++)
|
|
// cn[i] = new LinearGradientColorTable(innerColor.Start, innerColor.End, innerColor.GradientAngle);
|
|
// colors = cn;
|
|
// }
|
|
|
|
// return colors;
|
|
//}
|
|
#endregion
|
|
|
|
#region Windows API
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class Office2007Form : OfficeForm
|
|
{
|
|
}
|
|
|
|
internal class NonClientInfo
|
|
{
|
|
public int CaptionTotalHeight = 0;
|
|
public int BottomBorder = 0;
|
|
public int LeftBorder = 0;
|
|
public int RightBorder = 0;
|
|
}
|
|
}
|