using System;
using System.Drawing;
+using System.Runtime.InteropServices;
+
namespace System.Windows.Forms {
private static Color titlebar_color;
- private int BorderWidth = 3;
private Size MinTitleBarSize = new Size (115, 25);
internal Form form;
- private TitleButton close_button;
- private TitleButton maximize_button;
- private TitleButton minimize_button;
-
+ internal TitleButton close_button;
+ internal TitleButton maximize_button;
+ internal TitleButton minimize_button;
+ protected Rectangle icon_rect;
+
private TitleButton [] title_buttons = new TitleButton [3];
// moving windows
internal Point start;
- private State state;
+ internal State state;
private FormPos sizing_edge;
internal Rectangle virtual_position;
- private Rectangle prev_virtual_position;
- private Rectangle prev_bounds;
- private bool maximized;
- private class TitleButton {
+ public class TitleButton {
public Rectangle Rectangle;
public ButtonState State;
public CaptionButton Caption;
public EventHandler Clicked;
-
+
public TitleButton (CaptionButton caption, EventHandler clicked)
{
Caption = caption;
}
}
- private enum State {
+ public enum State {
Idle,
Moving,
Sizing,
}
[Flags]
- private enum FormPos {
+ public enum FormPos {
None,
TitleBar = 1,
titlebar_color = Color.FromArgb (255, 0, 0, 255);
this.form = form;
+ form.SizeChanged += new EventHandler (FormSizeChangedHandler);
+
CreateButtons ();
}
get { return form; }
}
- public bool Maximized {
- get { return maximized; }
+ public Rectangle CloseButtonRect {
+ get { return close_button.Rectangle; }
+ set { close_button.Rectangle = value; }
+ }
+
+ public Rectangle MinimizeButtonRect {
+ get { return minimize_button.Rectangle; }
+ set { minimize_button.Rectangle = value; }
+ }
+
+ public Rectangle MaximizeButtonRect {
+ get { return maximize_button.Rectangle; }
+ set { maximize_button.Rectangle = value; }
+ }
+
+ public Rectangle IconRect {
+ get { return icon_rect; }
+ set { value = icon_rect; }
+ }
+
+ public int IconWidth {
+ get { return TitleBarHeight - 5; }
}
public bool HandleMessage (ref Message m)
case Msg.WM_LBUTTONDOWN:
return HandleButtonDown (ref m);
- case Msg.WM_NCMOUSEMOVE:
- return HandleNCMouseMove (form, ref m);
+ case Msg.WM_NCHITTEST:
+ int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
+ int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
+
+ NCPointToClient (ref x, ref y);
+
+ FormPos pos = FormPosForCoords (x, y);
+
+ if (pos == FormPos.TitleBar) {
+ m.Result = new IntPtr ((int) HitTest.HTCAPTION);
+ return true;
+ }
+
+ if (!IsSizable)
+ return false;
+
+ switch (pos) {
+ case FormPos.Top:
+ m.Result = new IntPtr ((int) HitTest.HTTOP);
+ break;
+ case FormPos.Left:
+ m.Result = new IntPtr ((int) HitTest.HTLEFT);
+ break;
+ case FormPos.Right:
+ m.Result = new IntPtr ((int) HitTest.HTRIGHT);
+ break;
+ case FormPos.Bottom:
+ m.Result = new IntPtr ((int) HitTest.HTBOTTOM);
+ break;
+ case FormPos.TopLeft:
+ m.Result = new IntPtr ((int) HitTest.HTTOPLEFT);
+ break;
+ case FormPos.TopRight:
+ m.Result = new IntPtr ((int) HitTest.HTTOPRIGHT);
+ break;
+ case FormPos.BottomLeft:
+ m.Result = new IntPtr ((int) HitTest.HTBOTTOMLEFT);
+ break;
+ case FormPos.BottomRight:
+ m.Result = new IntPtr ((int) HitTest.HTBOTTOMRIGHT);
+ break;
+ default:
+ // We return false so that DefWndProc handles things
+ return false;
+ }
+ return true;
+ // Return true from these guys, otherwise win32 will mess up z-order
case Msg.WM_NCLBUTTONUP:
- return HandleNCLButtonUp (ref m);
+ HandleNCLButtonUp (ref m);
+ return true;
case Msg.WM_NCLBUTTONDOWN:
- return HandleNCLButtonDown (ref m);
+ HandleNCLButtonDown (ref m);
+ return true;
+
+ case Msg.WM_NCLBUTTONDBLCLK:
+ HandleNCLButtonDblClick (ref m);
+ break;
case Msg.WM_MOUSE_LEAVE:
FormMouseLeave (ref m);
break;
- case Msg.WM_NCPAINT:
- PaintWindowDecorations ();
+ case Msg.WM_NCCALCSIZE:
+ XplatUIWin32.NCCALCSIZE_PARAMS ncp;
+
+ if (m.WParam == (IntPtr) 1) {
+ ncp = (XplatUIWin32.NCCALCSIZE_PARAMS) Marshal.PtrToStructure (m.LParam,
+ typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
+
+ int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
+
+ if (HasBorders) {
+ ncp.rgrc1.top += TitleBarHeight + bw;
+ ncp.rgrc1.bottom -= bw;
+ ncp.rgrc1.left += bw;
+ ncp.rgrc1.right -= bw;
+ }
+
+ Marshal.StructureToPtr(ncp, m.LParam, true);
+ }
+
break;
+
+ case Msg.WM_NCPAINT:
+ PaintEventArgs pe = XplatUI.PaintEventStart (form.Handle, false);
+
+ Rectangle clip;
+ // clip region is not correct on win32.
+ // if (m.WParam.ToInt32 () > 1) {
+ // Region r = Region.FromHrgn (m.WParam);
+ // RectangleF rf = r.GetBounds (pe.Graphics);
+ // clip = new Rectangle ((int) rf.X, (int) rf.Y, (int) rf.Width, (int) rf.Height);
+ //} else {
+ clip = new Rectangle (0, 0, form.Width, form.Height);
+ //}
+
+ ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
+ XplatUI.PaintEventEnd (form.Handle, false);
+ return true;
}
+
return false;
}
CreateButtons ();
}
+ public void HandleMenuMouseDown (MainMenu menu, int x, int y)
+ {
+ Point pt = MenuTracker.ScreenToMenu (menu, new Point (x, y));
+
+ foreach (TitleButton button in title_buttons) {
+ if (button != null && button.Rectangle.Contains (pt)) {
+ button.Clicked (this, EventArgs.Empty);
+ button.State = ButtonState.Pushed;
+ return;
+ }
+ }
+ }
+
+ public virtual void SetWindowState (FormWindowState old_state, FormWindowState window_state)
+ {
+ }
+
+ public virtual FormWindowState GetWindowState ()
+ {
+ return form.window_state;
+ }
+
public virtual void PointToClient (ref int x, ref int y)
{
- // toolwindows stay in screencoords
+ // toolwindows stay in screencoords we just have to make sure
+ // they obey the working area
+ Rectangle working = SystemInformation.WorkingArea;
+
+ if (x > working.Right)
+ x = working.Right;
+ if (x < working.Left)
+ x = working.Left;
+
+ if (y < working.Top)
+ y = working.Top;
+ if (y > working.Bottom)
+ y = working.Bottom;
}
public virtual void PointToScreen (ref int x, ref int y)
return style != FormBorderStyle.FixedToolWindow && style != FormBorderStyle.SizableToolWindow;
}
- private void CreateButtons ()
+ protected virtual void Activate ()
+ {
+ // Hack to get a paint
+ //NativeWindow.WndProc (form.Handle, Msg.WM_NCPAINT, IntPtr.Zero, IntPtr.Zero);
+ form.Refresh ();
+ }
+
+ public virtual bool IsActive ()
+ {
+ return true;
+ }
+
+
+ private void FormSizeChangedHandler (object sender, EventArgs e)
+ {
+ ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
+ Message m = new Message ();
+ m.Msg = (int) Msg.WM_NCPAINT;
+ m.HWnd = form.Handle;
+ m.LParam = IntPtr.Zero;
+ m.WParam = new IntPtr (1);
+ XplatUI.SendMessage (ref m);
+ }
+
+ protected void CreateButtons ()
{
switch (form.FormBorderStyle) {
case FormBorderStyle.None:
close_button = null;
minimize_button = null;
maximize_button = null;
+ if (IsMaximized || IsMinimized)
+ goto case FormBorderStyle.Sizable;
+ break;
+ case FormBorderStyle.FixedToolWindow:
+ case FormBorderStyle.SizableToolWindow:
+ close_button = new TitleButton (CaptionButton.Close, new EventHandler (CloseClicked));
+ if (IsMaximized || IsMinimized)
+ goto case FormBorderStyle.Sizable;
break;
case FormBorderStyle.FixedSingle:
case FormBorderStyle.Fixed3D:
minimize_button = new TitleButton (CaptionButton.Minimize, new EventHandler (MinimizeClicked));
maximize_button = new TitleButton (CaptionButton.Maximize, new EventHandler (MaximizeClicked));
break;
- case FormBorderStyle.FixedToolWindow:
- case FormBorderStyle.SizableToolWindow:
- close_button = new TitleButton (CaptionButton.Close, new EventHandler (CloseClicked));
- break;
}
title_buttons [0] = close_button;
title_buttons [1] = minimize_button;
title_buttons [2] = maximize_button;
+
+ ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
}
protected virtual bool HandleButtonDown (ref Message m)
{
- form.BringToFront ();
+ Activate ();
return false;
}
protected virtual bool HandleNCLButtonDown (ref Message m)
{
- form.BringToFront ();
-
- int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
- int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
+ Activate ();
start = Cursor.Position;
virtual_position = form.Bounds;
- form.PointToClient (ref x, ref y);
+ int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
+ int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
+
// Need to adjust because we are in NC land
- y += TitleBarHeight;
+ NCPointToClient (ref x, ref y);
FormPos pos = FormPosForCoords (x, y);
-
+
if (pos == FormPos.TitleBar) {
HandleTitleBarDown (x, y);
return true;
}
if (IsSizable) {
- SetCursorForPos (pos);
-
if ((pos & FormPos.AnyEdge) == 0)
return false;
+ virtual_position = form.Bounds;
state = State.Sizing;
sizing_edge = pos;
form.Capture = true;
return false;
}
- private void HandleTitleBarDown (int x, int y)
+ protected virtual void HandleNCLButtonDblClick (ref Message m)
+ {
+ }
+
+ protected virtual void HandleTitleBarDown (int x, int y)
{
foreach (TitleButton button in title_buttons) {
if (button != null && button.Rectangle.Contains (x, y)) {
}
}
- if (maximized)
+ if (IsMaximized)
return;
- state = State.Moving;
+ state = State.Moving;
form.Capture = true;
}
return false;
}
- private bool HandleNCMouseMove (Form form, ref Message m)
- {
- if (IsSizable) {
- int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
- int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
- FormPos pos = FormPosForCoords (x, y);
-
- SetCursorForPos (pos);
-
- ClearVirtualPosition ();
- state = State.Idle;
- }
-
- return false;
- }
-
private void FormMouseLeave (ref Message m)
{
form.ResetCursor ();
}
-
- private void SetCursorForPos (FormPos pos)
- {
- switch (pos) {
- case FormPos.TopLeft:
- case FormPos.BottomRight:
- form.Cursor = Cursors.SizeNWSE;
- break;
- case FormPos.TopRight:
- case FormPos.BottomLeft:
- form.Cursor = Cursors.SizeNESW;
- break;
- case FormPos.Top:
- case FormPos.Bottom:
- form.Cursor = Cursors.SizeNS;
- break;
- case FormPos.Left:
- case FormPos.Right:
- form.Cursor = Cursors.SizeWE;
- break;
- default:
- form.ResetCursor ();
- break;
- }
- }
protected virtual void HandleWindowMove (Message m)
{
private void HandleSizing (Message m)
{
- Point move = MouseMove (m);
Rectangle pos = virtual_position;
- int mw = MinTitleBarSize.Width + (BorderWidth * 2);
- int mh = MinTitleBarSize.Height + (BorderWidth * 2);
-
+ int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
+ int mw = MinTitleBarSize.Width + (bw * 2);
+ int mh = MinTitleBarSize.Height + (bw * 2);
+ int x = Cursor.Position.X;
+ int y = Cursor.Position.Y;
+
+ PointToClient (ref x, ref y);
+
if ((sizing_edge & FormPos.Top) != 0) {
- int height = form.Height - move.Y;
- if (height <= mh) {
- move.Y += height - mh;
- height = mh;
- }
- pos.Y = form.Top + move.Y;
- pos.Height = height;
+ if (pos.Bottom - y < mh)
+ y = pos.Bottom - mh;
+ pos.Height = pos.Bottom - y;
+ pos.Y = y;
} else if ((sizing_edge & FormPos.Bottom) != 0) {
- int height = form.Height + move.Y;
+ int height = y - pos.Top;
if (height <= mh)
- move.Y -= height - mh;
- pos.Height = form.Height + move.Y;
+ height = mh;
+ pos.Height = height;
}
if ((sizing_edge & FormPos.Left) != 0) {
- int width = form.Width - move.X;
- if (width <= mw) {
- move.X += width - mw;
- width = mw;
- }
- pos.X = form.Left + move.X;
- pos.Width = width;
+ if (pos.Right - x < mw)
+ x = pos.Right - mw;
+ pos.Width = pos.Right - x;
+ pos.X = x;
} else if ((sizing_edge & FormPos.Right) != 0) {
- int width = form.Width + move.X;
+ int width = x - form.Left;
if (width <= mw)
- move.X -= width - mw;
- pos.Width = form.Width + move.X;
+ width = mw;
+ pos.Width = width;
}
UpdateVP (pos);
}
- private bool IsSizable {
+ public bool IsMaximized {
+ get { return GetWindowState () == FormWindowState.Maximized; }
+ }
+
+ public bool IsMinimized {
+ get { return GetWindowState () == FormWindowState.Minimized; }
+ }
+
+ public bool IsSizable {
get {
switch (form.FormBorderStyle) {
case FormBorderStyle.Sizable:
}
}
- private bool HasBorders {
+ public bool HasBorders {
get {
return form.FormBorderStyle != FormBorderStyle.None;
}
}
- private bool IsToolWindow {
+ public bool IsToolWindow {
get {
if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
form.FormBorderStyle == FormBorderStyle.FixedToolWindow)
}
}
- private int TitleBarHeight {
+ public int TitleBarHeight {
get {
- if (IsToolWindow)
- return 19;
- if (form.FormBorderStyle == FormBorderStyle.None)
- return 0;
- return 26;
+ return ThemeEngine.Current.ManagedWindowTitleBarHeight (this);
}
}
form.Capture = false;
form.Bounds = virtual_position;
state = State.Idle;
+
+ OnWindowFinishedMoving ();
}
private bool HandleNCLButtonUp (ref Message m)
{
+ if (form.Capture) {
+ ClearVirtualPosition ();
+
+ form.Capture = false;
+ state = State.Idle;
+ if (form.MdiContainer != null)
+ form.MdiContainer.SizeScrollBars();
+ }
+
int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
- form.PointToClient (ref x, ref y);
-
- // Need to adjust because we are in NC land
- y += TitleBarHeight;
+ NCPointToClient (ref x, ref y);
foreach (TitleButton button in title_buttons) {
if (button != null && button.Rectangle.Contains (x, y)) {
return true;
}
-
- private void PaintWindowDecorations ()
- {
- Graphics dc = XplatUI.GetMenuDC (form.Handle, IntPtr.Zero);
-
- if (HasBorders) {
- Rectangle borders = new Rectangle (0, 0, form.Width, form.Height);
-
- ControlPaint.DrawBorder3D (dc, borders, Border3DStyle.Raised);
-
- if (IsSizable) {
- borders.Inflate (-1, -1);
- ControlPaint.DrawFocusRectangle (dc, borders);
- }
- }
-
- Color color = ThemeEngine.Current.ColorControlDark;
-
- if (form.Focused && !maximized)
- color = titlebar_color;
-
- Rectangle tb = new Rectangle (BorderWidth, BorderWidth,
- form.Width - (BorderWidth * 2), TitleBarHeight - 1);
-
- dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (color), tb);
-
- dc.DrawLine (new Pen (Color.White, 1), BorderWidth,
- TitleBarHeight + BorderWidth, form.Width - BorderWidth,
- TitleBarHeight + BorderWidth);
-
- if (!IsToolWindow) {
- tb.X += 18; // Room for the icon and the buttons
- tb.Width = (form.Width - 62) - tb.X;
- }
-
- if (form.Text != null) {
- StringFormat format = new StringFormat ();
- format.FormatFlags = StringFormatFlags.NoWrap;
- format.Trimming = StringTrimming.EllipsisCharacter;
- format.LineAlignment = StringAlignment.Center;
- dc.DrawString (form.Text, form.Font,
- ThemeEngine.Current.ResPool.GetSolidBrush (Color.White),
- tb, format);
- }
-
- if (!IsToolWindow && HasBorders) {
- if (form.Icon != null) {
- dc.DrawIcon (form.Icon, new Rectangle (BorderWidth + 3,
- BorderWidth + 3, 16, 16));
- }
-
- minimize_button.Rectangle = new Rectangle (form.Width - 62,
- BorderWidth + 2, 18, 22);
-
- maximize_button.Rectangle = new Rectangle (form.Width - 44,
- BorderWidth + 2, 18, 22);
-
- close_button.Rectangle = new Rectangle (form.Width - 24,
- BorderWidth + 2, 18, 22);
-
- DrawTitleButton (dc, minimize_button);
- DrawTitleButton (dc, maximize_button);
- DrawTitleButton (dc, close_button);
- } else if (IsToolWindow) {
- close_button.Rectangle = new Rectangle (form.Width - BorderWidth - 2 - 13,
- BorderWidth + 2, 13, 13);
- DrawTitleButton (dc, close_button);
- }
- }
- private void DrawTitleButton (Graphics dc, TitleButton button)
+ protected void DrawTitleButton (Graphics dc, TitleButton button, Rectangle clip)
{
+ if (!button.Rectangle.IntersectsWith (clip))
+ return;
+
dc.FillRectangle (SystemBrushes.Control, button.Rectangle);
ControlPaint.DrawCaptionButton (dc, button.Rectangle,
button.Caption, ButtonState.Normal);
}
- private void CloseClicked (object sender, EventArgs e)
+ public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
+ {
+ }
+
+ protected virtual void CloseClicked (object sender, EventArgs e)
{
form.Close ();
- // form.Close should set visibility to false somewhere
- // in it's closing chain but currently does not.
- form.Visible = false;
}
private void MinimizeClicked (object sender, EventArgs e)
{
- form.SuspendLayout ();
- form.Width = MinTitleBarSize.Width + (BorderWidth * 2);
- form.Height = MinTitleBarSize.Height + (BorderWidth * 2);
- form.ResumeLayout ();
+ if (GetWindowState () != FormWindowState.Minimized) {
+ form.WindowState = FormWindowState.Minimized;
+ } else {
+ form.WindowState = FormWindowState.Normal;
+ }
}
private void MaximizeClicked (object sender, EventArgs e)
{
- if (maximized) {
- form.Bounds = prev_bounds;
- maximized = false;
+ if (GetWindowState () != FormWindowState.Maximized) {
+ form.WindowState = FormWindowState.Maximized;
} else {
- prev_bounds = form.Bounds;
- form.Bounds = form.Parent.Bounds;
- maximized = true;
+ form.WindowState = FormWindowState.Normal;
}
}
protected virtual void DrawVirtualPosition (Rectangle virtual_position)
{
- form.Location = virtual_position.Location;
+ form.Bounds = virtual_position;
start = Cursor.Position;
}
}
- private FormPos FormPosForCoords (int x, int y)
+ protected virtual void OnWindowFinishedMoving ()
{
- if (y < TitleBarHeight + BorderWidth) {
+ }
- if (y > BorderWidth && x > BorderWidth &&
- x < form.Width - BorderWidth)
+ protected virtual void NCPointToClient(ref int x, ref int y) {
+ form.PointToClient(ref x, ref y);
+ y += TitleBarHeight;
+ y += ThemeEngine.Current.ManagedWindowBorderWidth (this);
+ }
+
+ protected FormPos FormPosForCoords (int x, int y)
+ {
+ int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
+ if (y < TitleBarHeight + bw) {
+ // Console.WriteLine ("A");
+ if (y > bw && x > bw &&
+ x < form.Width - bw)
return FormPos.TitleBar;
- if (x < BorderWidth || (x < 20 && y < BorderWidth))
+ if (x < bw || (x < 20 && y < bw))
return FormPos.TopLeft;
- if (x > form.Width - BorderWidth ||
- (x > form.Width - 20 && y < BorderWidth))
+ if (x > form.Width - bw ||
+ (x > form.Width - 20 && y < bw))
return FormPos.TopRight;
- if (y < BorderWidth)
+ if (y < bw)
return FormPos.Top;
} else if (y > form.Height - 20) {
-
- if (x < BorderWidth ||
- (x < 20 && y > form.Height - BorderWidth))
+ // Console.WriteLine ("B");
+ if (x < bw ||
+ (x < 20 && y > form.Height - bw))
return FormPos.BottomLeft;
- if (x > form.Width - BorderWidth ||
+ if (x > form.Width - (bw * 2) ||
(x > form.Width - 20 &&
- y > form.Height - BorderWidth))
+ y > form.Height - bw))
return FormPos.BottomRight;
- if (y > form.Height - BorderWidth)
+ if (y > form.Height - (bw * 2))
return FormPos.Bottom;
- } else if (x < BorderWidth) {
+ } else if (x < bw) {
+ // Console.WriteLine ("C");
return FormPos.Left;
- } else if (x > form.Width - BorderWidth) {
+ } else if (x > form.Width - (bw * 2)) {
+// Console.WriteLine ("D");
return FormPos.Right;
+ } else {
+ // Console.WriteLine ("E {0}", form.Width - bw);
}
return FormPos.None;