4 using System.Drawing.Drawing2D;
6 namespace System.Windows.Forms {
8 internal class MdiChildContext {
10 private static readonly int MdiBorderStyle = 0xFFFF;
11 private static Color titlebar_color;
13 private int BorderWidth = 3;
14 // private int TitleBarHeight = 26;
15 // private int ToolTitleBarHeight = 19;
16 private Size MinTitleBarSize = new Size (115, 25);
19 private MdiClient mdi_container;
20 private Button close_button;
21 private Button maximize_button;
22 private Button minimize_button;
27 private FormPos sizing_edge;
28 private Rectangle virtual_position;
29 private Rectangle prev_virtual_position;
30 private Rectangle prev_bounds;
31 private bool maximized;
40 private enum FormPos {
51 TopRight = Top | Right,
53 BottomLeft = Bottom | Left,
54 BottomRight = Bottom | Right,
56 AnyEdge = Top | Left | Right | Bottom,
59 public MdiChildContext (Form form, MdiClient mdi_container)
61 titlebar_color = Color.FromArgb (255, 0, 0, 255);
63 this.mdi_container = mdi_container;
65 if (form.FormBorderStyle != FormBorderStyle.None)
66 form.InternalBorderStyle = (BorderStyle) MdiBorderStyle;
68 form.InternalBorderStyle = BorderStyle.None;
71 minimize_button = new Button ();
72 minimize_button.Bounds = new Rectangle (form.Width - 62,
74 minimize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
75 minimize_button.Paint += new PaintEventHandler (PaintButtonHandler);
76 minimize_button.Click += new EventHandler (OnMinimizeHandler);
78 maximize_button = new Button ();
79 maximize_button.Bounds = new Rectangle (form.Width - 44,
80 BorderWidth + 2, 18, 22);
81 maximize_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
82 maximize_button.Paint += new PaintEventHandler (PaintButtonHandler);
83 maximize_button.Click += new EventHandler (OnMaximizeHandler);
85 close_button = new Button ();
86 close_button.Bounds = new Rectangle (form.Width - 24,
87 BorderWidth + 2, 18, 22);
88 close_button.Anchor = AnchorStyles.Top | AnchorStyles.Right;
89 close_button.Paint += new PaintEventHandler (PaintButtonHandler);
90 close_button.Click += new EventHandler (CloseButtonClicked);
93 form.Controls.AddImplicit (close_button);
94 form.Controls.AddImplicit (maximize_button);
95 form.Controls.AddImplicit (minimize_button);
99 public bool HandleMessage (ref Message m)
101 switch ((Msg)m.Msg) {
104 // The mouse handling messages are actually
105 // not WM_NC* messages except for the first button and NCMOVEs
106 // down because we capture on the form
108 case Msg.WM_MOUSEMOVE:
109 return HandleMouseMove (form, ref m);
111 case Msg.WM_LBUTTONUP:
112 HandleLButtonUp (ref m);
115 case Msg.WM_RBUTTONDOWN:
116 case Msg.WM_LBUTTONDOWN:
117 return HandleButtonDown (ref m);
119 case Msg.WM_NCMOUSEMOVE:
120 return HandleNCMouseMove (form, ref m);
122 case Msg.WM_NCLBUTTONDOWN:
123 return HandleNCLButtonDown (ref m);
126 // form.UpdateStyles ();
127 PaintWindowDecorations ();
128 // Graphics g = XplatUI.GetMenuDC (form.Handle, IntPtr.Zero);
129 // g.Clear (Color.Red);
135 public void UpdateBorderStyle (FormBorderStyle border_style)
137 if (border_style != FormBorderStyle.None)
138 XplatUI.SetBorderStyle (form.Handle, (FormBorderStyle) MdiBorderStyle);
140 XplatUI.SetBorderStyle (form.Handle, FormBorderStyle.None);
143 private bool HandleButtonDown (ref Message m)
145 form.BringToFront ();
146 mdi_container.ActiveMdiChild = form;
150 private bool HandleNCLButtonDown (ref Message m)
152 form.BringToFront ();
153 mdi_container.ActiveMdiChild = form;
155 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
156 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
158 form.PointToClient (ref x, ref y);
160 // Need to adjust because we are in NC land
162 FormPos pos = FormPosForCoords (x, y);
164 start = new Point (x, y);
165 virtual_position = form.Bounds;
167 if (pos == FormPos.TitleBar) {
168 HandleTitleBarDown (x, y);
174 SetCursorForPos (pos);
176 if ((pos & FormPos.AnyEdge) == 0)
179 state = State.Sizing;
189 private void HandleTitleBarDown (int x, int y)
191 state = State.Moving;
195 private bool HandleMouseMove (Form form, ref Message m)
199 HandleWindowMove (m);
208 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
209 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
210 FormPos pos = FormPosForCoords (x, y);
211 Console.WriteLine ("position: " + pos);
212 SetCursorForPos (pos);
214 ClearVirtualPosition ();
222 private bool HandleNCMouseMove (Form form, ref Message m)
225 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
226 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
227 FormPos pos = FormPosForCoords (x, y);
228 Console.WriteLine ("position: " + pos);
229 SetCursorForPos (pos);
231 ClearVirtualPosition ();
238 private void SetCursorForPos (FormPos pos)
241 case FormPos.TopLeft:
242 case FormPos.BottomRight:
243 form.Cursor = Cursors.SizeNWSE;
245 case FormPos.TopRight:
246 case FormPos.BottomLeft:
247 form.Cursor = Cursors.SizeNESW;
251 form.Cursor = Cursors.SizeNS;
255 form.Cursor = Cursors.SizeWE;
258 form.Cursor = Cursors.Default;
263 private void HandleWindowMove (Message m)
265 Point move = MouseMove (m);
267 virtual_position.X = form.Left + move.X;
268 virtual_position.Y = form.Top + move.Y;
269 virtual_position.Width = form.Width;
270 virtual_position.Height = form.Height;
272 mdi_container.EnsureScrollBars (virtual_position.Right, virtual_position.Bottom);
274 DrawVirtualPosition ();
277 private void HandleSizing (Message m)
279 Point move = MouseMove (m);
280 Rectangle pos = virtual_position;
281 int mw = MinTitleBarSize.Width + (BorderWidth * 2);
282 int mh = MinTitleBarSize.Height + (BorderWidth * 2);
284 if ((sizing_edge & FormPos.Top) != 0) {
285 int height = form.Height - move.Y;
287 move.Y += height - mh;
290 pos.Y = form.Top + move.Y;
292 } else if ((sizing_edge & FormPos.Bottom) != 0) {
293 int height = form.Height + move.Y;
295 move.Y -= height - mh;
296 pos.Height = form.Height + move.Y;
299 if ((sizing_edge & FormPos.Left) != 0) {
300 int width = form.Width - move.X;
302 move.X += width - mw;
305 pos.X = form.Left + move.X;
307 } else if ((sizing_edge & FormPos.Right) != 0) {
308 int width = form.Width + move.X;
310 move.X -= width - mw;
311 pos.Width = form.Width + move.X;
317 private bool IsSizable {
319 switch (form.FormBorderStyle) {
320 case FormBorderStyle.Sizable:
321 case FormBorderStyle.SizableToolWindow:
329 private bool HasBorders {
331 return form.FormBorderStyle != FormBorderStyle.None;
335 private bool IsToolWindow {
337 if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
338 form.FormBorderStyle == FormBorderStyle.FixedToolWindow)
344 private int TitleBarHeight {
348 if (form.FormBorderStyle == FormBorderStyle.None)
354 private void UpdateVP (Rectangle r)
356 UpdateVP (r.X, r.Y, r.Width, r.Height);
359 private void UpdateVP (Point loc, int w, int h)
361 UpdateVP (loc.X, loc.Y, w, h);
364 private void UpdateVP (int x, int y, int w, int h)
366 virtual_position.X = x;
367 virtual_position.Y = y;
368 virtual_position.Width = w;
369 virtual_position.Height = h;
371 DrawVirtualPosition ();
374 private void HandleLButtonUp (ref Message m)
376 if (state == State.Idle)
379 ClearVirtualPosition ();
381 form.Capture = false;
382 form.Bounds = virtual_position;
386 private void PaintWindowDecorations ()
388 Graphics dc = XplatUI.GetMenuDC (form.Handle, IntPtr.Zero);
391 Rectangle borders = new Rectangle (0, 0, form.Width, form.Height);
392 // dc.FillRectangle (new SolidBrush (Color.Black), borders);
395 dc.DrawRectangle (new Pen (SystemColors.ControlLight, 1), borders);
396 borders.Inflate (-2, -2);
397 dc.DrawRectangle (new Pen (SystemColors.ControlDark, 1), borders);
400 dc.DrawRectangle (new Pen (SystemColors.ControlLight, 1), borders);
403 ControlPaint.DrawBorder3D (dc, borders, Border3DStyle.Raised);
406 borders.Inflate (-1, -1);
407 ControlPaint.DrawFocusRectangle (dc, borders);
411 Color color = ThemeEngine.Current.ColorControlDark;
412 if (form == mdi_container.ActiveMdiChild && !maximized)
413 color = titlebar_color;
415 Rectangle tb = new Rectangle (BorderWidth, BorderWidth,
416 form.Width - (BorderWidth * 2), TitleBarHeight - 1);
418 dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (color), tb);
420 dc.DrawLine (new Pen (Color.White, 1), BorderWidth,
421 TitleBarHeight + BorderWidth, form.Width - BorderWidth,
422 TitleBarHeight + BorderWidth);
425 tb.X += 18; // Room for the icon and the buttons
426 tb.Width = (form.Width - 62) - tb.X;
429 if (form.Text != null) {
430 StringFormat format = new StringFormat ();
431 format.FormatFlags = StringFormatFlags.NoWrap;
432 format.Trimming = StringTrimming.EllipsisCharacter;
433 format.LineAlignment = StringAlignment.Center;
434 dc.DrawString (form.Text, form.Font,
435 ThemeEngine.Current.ResPool.GetSolidBrush (Color.White),
440 if (form.Icon != null) {
441 dc.DrawIcon (form.Icon, new Rectangle (BorderWidth + 3,
442 BorderWidth + 3, 16, 16));
445 Rectangle r = new Rectangle (form.Width - 62, BorderWidth + 2, 18, 22);
446 dc.FillRectangle (SystemBrushes.Control, r);
447 ControlPaint.DrawCaptionButton (dc, r, CaptionButton.Minimize, ButtonState.Normal);
449 r = new Rectangle (form.Width - 44, BorderWidth + 2, 18, 22);
450 dc.FillRectangle (SystemBrushes.Control, r);
451 ControlPaint.DrawCaptionButton (dc, r, CaptionButton.Maximize, ButtonState.Normal);
453 r = new Rectangle (form.Width - 24, BorderWidth + 2, 18, 22);
454 dc.FillRectangle (SystemBrushes.Control, r);
455 ControlPaint.DrawCaptionButton (dc, r, CaptionButton.Close, ButtonState.Normal);
457 Rectangle r = new Rectangle (form.Width - BorderWidth - 2 - 13,
458 BorderWidth + 2, 13, 13);
459 dc.FillRectangle (SystemBrushes.Control, r);
460 ControlPaint.DrawCaptionButton (dc, r, CaptionButton.Close, ButtonState.Normal);
465 private void PaintButtonHandler (object sender, PaintEventArgs pe)
467 if (sender == close_button) {
468 ControlPaint.DrawCaptionButton (pe.Graphics,
469 close_button.ClientRectangle,
471 close_button.ButtonState);
472 } else if (sender == maximize_button) {
473 ControlPaint.DrawCaptionButton (pe.Graphics,
474 maximize_button.ClientRectangle,
475 CaptionButton.Maximize,
476 maximize_button.ButtonState);
477 } else if (sender == minimize_button) {
478 ControlPaint.DrawCaptionButton (pe.Graphics,
479 minimize_button.ClientRectangle,
480 CaptionButton.Minimize,
481 minimize_button.ButtonState);
485 private void CloseButtonClicked (object sender, EventArgs e)
488 // form.Close should set visibility to false somewhere
489 // in it's closing chain but currently does not.
490 form.Visible = false;
493 private void OnMinimizeHandler (object sender, EventArgs e)
495 form.SuspendLayout ();
496 form.Width = MinTitleBarSize.Width + (BorderWidth * 2);
497 form.Height = MinTitleBarSize.Height + (BorderWidth * 2);
498 form.ResumeLayout ();
501 private void OnMaximizeHandler (object sender, EventArgs e)
504 form.Bounds = prev_bounds;
507 prev_bounds = form.Bounds;
508 form.Bounds = form.Parent.Bounds;
513 private Point NewLocation (Message m)
515 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
516 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
517 int x_move = x - start.X;
518 int y_move = y - start.Y;
520 return new Point (form.Left + x_move, form.Top + y_move);
523 private Point MouseMove (Message m)
525 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
526 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
527 int x_move = x - start.X;
528 int y_move = y - start.Y;
530 return new Point (x_move, y_move);
533 private void DrawVirtualPosition ()
535 ClearVirtualPosition ();
537 XplatUI.DrawReversibleRectangle (mdi_container.Handle, virtual_position, 2);
538 prev_virtual_position = virtual_position;
541 private void ClearVirtualPosition ()
543 if (prev_virtual_position != Rectangle.Empty)
544 XplatUI.DrawReversibleRectangle (mdi_container.Handle,
545 prev_virtual_position, 2);
546 prev_virtual_position = Rectangle.Empty;
549 private FormPos FormPosForCoords (int x, int y)
551 if (y < TitleBarHeight + BorderWidth) {
553 if (y > BorderWidth && x > BorderWidth &&
554 x < form.Width - BorderWidth)
555 return FormPos.TitleBar;
557 if (x < BorderWidth || (x < 20 && y < BorderWidth))
558 return FormPos.TopLeft;
560 if (x > form.Width - BorderWidth ||
561 (x > form.Width - 20 && y < BorderWidth))
562 return FormPos.TopRight;
567 } else if (y > form.Height - 20) {
569 if (x < BorderWidth ||
570 (x < 20 && y > form.Height - BorderWidth))
571 return FormPos.BottomLeft;
573 if (x > form.Width - BorderWidth ||
574 (x > form.Width - 20 &&
575 y > form.Height - BorderWidth))
576 return FormPos.BottomRight;
578 if (y > form.Height - BorderWidth)
579 return FormPos.Bottom;
582 } else if (x < BorderWidth) {
584 } else if (x > form.Width - BorderWidth) {
585 return FormPos.Right;