1 // Permission is hereby granted, free of charge, to any person obtaining 2 // a copy of this software and associated documentation files (the 3 // "Software"), to deal in the Software without restriction, including 4 // without limitation the rights to use, copy, modify, merge, publish, 5 // distribute, sublicense, and/or sell copies of the Software, and to 6 // permit persons to whom the Software is furnished to do so, subject to 7 // the following conditions: 8 // 9 // The above copyright notice and this permission notice shall be 10 // included in all copies or substantial portions of the Software. 11 // 12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 // 20 // Copyright (c) 2005-2006 Novell, Inc. (http://www.novell.com) 21 // 22 // Authors: 23 // Peter Bartok (pbartok@novell.com) 24 // 25 // 26 27 // NOT COMPLETE 28 29 using System; 30 using System.Collections; 31 using System.Drawing; 32 using System.Runtime.InteropServices; 33 34 // NOTE: Possible optimization: 35 // Several properties calculate dimensions on the fly; instead; they can 36 // be stored in a field and only be recalculated when a style is changed (DefaultClientRect, for example) 37 38 namespace System.Windows.Forms { 39 internal class Hwnd : IDisposable { 40 #region Local Variables 41 private static Hashtable windows = new Hashtable(100, 0.5f); 42 //private const int menu_height = 14; // FIXME - Read this value from somewhere 43 44 private IntPtr handle; 45 internal IntPtr client_window; 46 internal IntPtr whole_window; 47 internal IntPtr cursor; 48 internal Menu menu; 49 internal TitleStyle title_style; 50 internal FormBorderStyle border_style; 51 internal bool border_static; 52 internal int x; 53 internal int y; 54 internal int width; 55 internal int height; 56 internal bool allow_drop; 57 internal Hwnd parent; 58 internal bool visible; 59 internal bool mapped; 60 internal uint opacity; 61 internal bool enabled; 62 internal bool zero_sized; 63 internal ArrayList invalid_list; 64 internal Rectangle nc_invalid; 65 internal bool expose_pending; 66 internal bool nc_expose_pending; 67 internal bool configure_pending; 68 internal bool resizing_or_moving; // Used by the X11 backend to track form resize/move 69 internal bool reparented; 70 internal Stack drawing_stack; 71 internal object user_data; 72 internal Rectangle client_rectangle; 73 internal ArrayList marshal_free_list; 74 internal int caption_height; 75 internal int tool_caption_height; 76 internal bool whacky_wm; 77 internal bool fixed_size; 78 internal bool zombie; /* X11 only flag. true if the X windows have been destroyed but we haven't been Disposed */ 79 internal bool topmost; /* X11 only. */ 80 internal Region user_clip; 81 internal XEventQueue queue; 82 internal WindowExStyles initial_ex_style; 83 internal WindowStyles initial_style; 84 internal FormWindowState cached_window_state = (FormWindowState)(-1); /* X11 only field */ 85 internal Point previous_child_startup_location = new Point (int.MinValue, int.MinValue); 86 static internal Point previous_main_startup_location = new Point (int.MinValue, int.MinValue); 87 internal ArrayList children; 88 89 [ThreadStatic] 90 private static Bitmap bmp; 91 [ThreadStatic] 92 private static Graphics bmp_g; 93 #endregion // Local Variables 94 95 // locks for some operations (used in XplatUIX11.cs) 96 internal object configure_lock = new object (); 97 internal object expose_lock = new object (); 98 99 #region Constructors and destructors Hwnd()100 public Hwnd() { 101 x = 0; 102 y = 0; 103 width = 0; 104 height = 0; 105 visible = false; 106 menu = null; 107 border_style = FormBorderStyle.None; 108 client_window = IntPtr.Zero; 109 whole_window = IntPtr.Zero; 110 cursor = IntPtr.Zero; 111 handle = IntPtr.Zero; 112 parent = null; 113 invalid_list = new ArrayList(); 114 expose_pending = false; 115 nc_expose_pending = false; 116 enabled = true; 117 reparented = false; 118 client_rectangle = Rectangle.Empty; 119 marshal_free_list = new ArrayList(2); 120 opacity = 0xffffffff; 121 fixed_size = false; 122 drawing_stack = new Stack (); 123 children = new ArrayList (); 124 resizing_or_moving = false; 125 whacky_wm = false; 126 topmost = false; 127 } 128 Dispose()129 public void Dispose() { 130 expose_pending = false; 131 nc_expose_pending = false; 132 Parent = null; 133 lock (windows) { 134 windows.Remove(client_window); 135 windows.Remove(whole_window); 136 } 137 client_window = IntPtr.Zero; 138 whole_window = IntPtr.Zero; 139 zombie = false; 140 for (int i = 0; i < marshal_free_list.Count; i++) { 141 Marshal.FreeHGlobal((IntPtr)marshal_free_list[i]); 142 } 143 marshal_free_list.Clear(); 144 } 145 #endregion 146 147 #region Static Methods ObjectFromWindow(IntPtr window)148 public static Hwnd ObjectFromWindow(IntPtr window) { 149 Hwnd rv; 150 lock (windows) { 151 rv = (Hwnd)windows[window]; 152 } 153 return rv; 154 } 155 ObjectFromHandle(IntPtr handle)156 public static Hwnd ObjectFromHandle(IntPtr handle) { 157 //return (Hwnd)(((GCHandle)handle).Target); 158 Hwnd rv; 159 lock (windows) { 160 rv = (Hwnd)windows[handle]; 161 } 162 return rv; 163 } 164 HandleFromObject(Hwnd obj)165 public static IntPtr HandleFromObject(Hwnd obj) { 166 return obj.handle; 167 } 168 GetObjectFromWindow(IntPtr window)169 public static Hwnd GetObjectFromWindow(IntPtr window) { 170 Hwnd rv; 171 lock (windows) { 172 rv = (Hwnd)windows[window]; 173 } 174 return rv; 175 } 176 GetHandleFromWindow(IntPtr window)177 public static IntPtr GetHandleFromWindow(IntPtr window) { 178 Hwnd hwnd; 179 180 lock (windows) { 181 hwnd = (Hwnd)windows[window]; 182 } 183 if (hwnd != null) { 184 return hwnd.handle; 185 } else { 186 return IntPtr.Zero; 187 } 188 } 189 GetBorderWidth(CreateParams cp)190 public static Borders GetBorderWidth (CreateParams cp) 191 { 192 Borders border_size = new Borders (); 193 194 Size windowborder = ThemeEngine.Current.BorderSize; /*new Size (1, 1);*/ // This is the only one that can be changed from the display properties in windows. 195 Size border = ThemeEngine.Current.BorderStaticSize; /*new Size (1, 1);*/ 196 Size clientedge = ThemeEngine.Current.Border3DSize; /*new Size (2, 2);*/ 197 Size thickframe = new Size (2 + windowborder.Width, 2 + windowborder.Height); 198 Size dialogframe = ThemeEngine.Current.BorderSizableSize; /* new Size (3, 3);*/ 199 200 if (cp.IsSet (WindowStyles.WS_CAPTION)) { 201 border_size.Inflate (dialogframe); 202 } else if (cp.IsSet (WindowStyles.WS_BORDER)) { 203 if (cp.IsSet (WindowExStyles.WS_EX_DLGMODALFRAME)) { 204 if (cp.IsSet (WindowStyles.WS_THICKFRAME) && (cp.IsSet (WindowExStyles.WS_EX_STATICEDGE) || cp.IsSet (WindowExStyles.WS_EX_CLIENTEDGE))) { 205 border_size.Inflate (border); 206 } 207 } else { 208 border_size.Inflate (border); 209 } 210 } else if (cp.IsSet (WindowStyles.WS_DLGFRAME)) { 211 border_size.Inflate (dialogframe); 212 } 213 214 if (cp.IsSet (WindowStyles.WS_THICKFRAME)) { 215 if (cp.IsSet (WindowStyles.WS_DLGFRAME)) { 216 border_size.Inflate (border); 217 } else { 218 border_size.Inflate (thickframe); 219 } 220 } 221 222 bool only_small_border; 223 Size small_border = Size.Empty; 224 225 only_small_border = cp.IsSet (WindowStyles.WS_THICKFRAME) || cp.IsSet (WindowStyles.WS_DLGFRAME); 226 if (only_small_border && cp.IsSet (WindowStyles.WS_THICKFRAME) && !cp.IsSet (WindowStyles.WS_BORDER) && !cp.IsSet (WindowStyles.WS_DLGFRAME)) { 227 small_border = border; 228 } 229 230 if (cp.IsSet (WindowExStyles.WS_EX_CLIENTEDGE | WindowExStyles.WS_EX_DLGMODALFRAME)) { 231 border_size.Inflate (clientedge + (only_small_border ? small_border : dialogframe)); 232 } else if (cp.IsSet (WindowExStyles.WS_EX_STATICEDGE | WindowExStyles.WS_EX_DLGMODALFRAME)) { 233 border_size.Inflate (only_small_border ? small_border : dialogframe); 234 } else if (cp.IsSet (WindowExStyles.WS_EX_STATICEDGE | WindowExStyles.WS_EX_CLIENTEDGE)) { 235 border_size.Inflate (border + (only_small_border ? Size.Empty : clientedge)); 236 } else { 237 if (cp.IsSet (WindowExStyles.WS_EX_CLIENTEDGE)) { 238 border_size.Inflate (clientedge); 239 } 240 if (cp.IsSet (WindowExStyles.WS_EX_DLGMODALFRAME) && !cp.IsSet (WindowStyles.WS_DLGFRAME)) { 241 border_size.Inflate (cp.IsSet (WindowStyles.WS_THICKFRAME) ? border : dialogframe); 242 } 243 if (cp.IsSet (WindowExStyles.WS_EX_STATICEDGE)) { 244 if (cp.IsSet (WindowStyles.WS_THICKFRAME) || cp.IsSet (WindowStyles.WS_DLGFRAME)) { 245 border_size.Inflate (new Size (-border.Width, -border.Height)); 246 } else { 247 border_size.Inflate (border); 248 } 249 } 250 } 251 252 return border_size; 253 } 254 GetWindowRectangle(CreateParams cp, Menu menu)255 public static Rectangle GetWindowRectangle (CreateParams cp, Menu menu) 256 { 257 return GetWindowRectangle (cp, menu, Rectangle.Empty); 258 } 259 GetWindowRectangle(CreateParams cp, Menu menu, Rectangle client_rect)260 public static Rectangle GetWindowRectangle (CreateParams cp, Menu menu, Rectangle client_rect) 261 { 262 Rectangle rect; 263 Borders borders; 264 265 borders = GetBorders (cp, menu); 266 267 rect = new Rectangle (Point.Empty, client_rect.Size); 268 rect.Y -= borders.top; 269 rect.Height += borders.top + borders.bottom; 270 rect.X -= borders.left; 271 rect.Width += borders.left + borders.right; 272 273 #if debug 274 Console.WriteLine ("GetWindowRectangle ({0}, {1}, {2}): {3}", cp, menu != null, client_rect, rect); 275 #endif 276 return rect; 277 } 278 GetClientRectangle(int width, int height)279 public Rectangle GetClientRectangle (int width, int height) 280 { 281 CreateParams cp = new CreateParams (); 282 cp.WindowStyle = initial_style; 283 cp.WindowExStyle = initial_ex_style; 284 return GetClientRectangle (cp, menu, width, height); 285 } 286 287 // This could be greatly optimized by caching the outputs and only updating when something is moved 288 // in the parent planar space. To do that we need to track z-order in the parent space as well GetClippingRectangles()289 public ArrayList GetClippingRectangles () 290 { 291 ArrayList masks = new ArrayList (); 292 293 if (x < 0) { 294 masks.Add (new Rectangle (0, 0, x*-1, Height)); 295 if (y < 0) { 296 masks.Add (new Rectangle (x*-1, 0, Width, y*-1)); 297 } 298 } else if (y < 0) { 299 masks.Add (new Rectangle (0, 0, Width, y*-1)); 300 } 301 302 foreach (Hwnd child in children) { 303 if (child.visible) 304 masks.Add (new Rectangle (child.X, child.Y, child.Width, child.Height)); 305 } 306 307 if (parent == null) { 308 return masks; 309 } 310 311 ArrayList siblings = parent.children; 312 313 foreach (Hwnd sibling in siblings) { 314 IntPtr sibling_handle = whole_window; 315 316 if (sibling == this) 317 continue; 318 319 // This entire method should be cached to find all higher views at the time of query 320 do { 321 sibling_handle = XplatUI.GetPreviousWindow (sibling_handle); 322 323 if (sibling_handle == sibling.WholeWindow && sibling.visible) { 324 325 Rectangle intersect = Rectangle.Intersect (new Rectangle (X, Y, Width, Height), new Rectangle (sibling.X, sibling.Y, sibling.Width, sibling.Height)); 326 327 if (intersect == Rectangle.Empty) 328 continue; 329 330 intersect.X -= X; 331 intersect.Y -= Y; 332 333 masks.Add (intersect); 334 } 335 } while (sibling_handle != IntPtr.Zero); 336 } 337 338 return masks; 339 } 340 GetBorders(CreateParams cp, Menu menu)341 public static Borders GetBorders (CreateParams cp, Menu menu) 342 { 343 344 Borders borders = new Borders (); 345 346 if (menu != null) { 347 int menu_height = menu.Rect.Height; 348 if (menu_height == 0) 349 menu_height = ThemeEngine.Current.CalcMenuBarSize (GraphicsContext, menu, cp.Width); 350 borders.top += menu_height; 351 } 352 353 if (cp.IsSet (WindowStyles.WS_CAPTION)) { 354 int caption_height; 355 if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) { 356 caption_height = ThemeEngine.Current.ToolWindowCaptionHeight; 357 } else { 358 caption_height = ThemeEngine.Current.CaptionHeight; 359 } 360 borders.top += caption_height; 361 } 362 363 Borders border_width = GetBorderWidth (cp); 364 365 borders.left += border_width.left; 366 borders.right += border_width.right; 367 borders.top += border_width.top; 368 borders.bottom += border_width.bottom; 369 370 return borders; 371 } 372 GetClientRectangle(CreateParams cp, Menu menu, int width, int height)373 public static Rectangle GetClientRectangle(CreateParams cp, Menu menu, int width, int height) { 374 Rectangle rect; 375 Borders borders; 376 377 borders = GetBorders (cp, menu); 378 379 rect = new Rectangle(0, 0, width, height); 380 rect.Y += borders.top; 381 rect.Height -= borders.top + borders.bottom; 382 rect.X += borders.left; 383 rect.Width -= borders.left + borders.right; 384 385 #if debug 386 Console.WriteLine ("GetClientRectangle ({0}, {1}, {2}, {3}): {4}", cp, menu != null, width, height, rect); 387 #endif 388 389 return rect; 390 } 391 392 public static Graphics GraphicsContext { 393 get { 394 if (bmp_g == null) { 395 bmp = new Bitmap (1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 396 bmp_g = Graphics.FromImage (bmp); 397 } 398 399 return bmp_g; 400 } 401 } 402 #endregion // Static Methods 403 404 #region Instance Properties 405 public FormBorderStyle BorderStyle { 406 get { 407 return border_style; 408 } 409 410 set { 411 border_style = value; 412 } 413 } 414 415 public Rectangle ClientRect { 416 get { 417 if (client_rectangle == Rectangle.Empty) { 418 return DefaultClientRect; 419 } 420 return client_rectangle; 421 } 422 423 set { 424 client_rectangle = value; 425 } 426 } 427 428 public IntPtr Cursor { 429 get { 430 return cursor; 431 } 432 433 set { 434 cursor = value; 435 } 436 } 437 438 public IntPtr ClientWindow { 439 get { 440 return client_window; 441 } 442 443 set { 444 client_window = value; 445 handle = value; 446 447 zombie = false; 448 449 if (client_window != IntPtr.Zero) { 450 lock (windows) { 451 if (windows[client_window] == null) { 452 windows[client_window] = this; 453 } 454 } 455 } 456 } 457 } 458 459 public Region UserClip { 460 get { 461 return user_clip; 462 } 463 464 set { 465 user_clip = value; 466 } 467 } 468 469 public Rectangle DefaultClientRect { 470 get { 471 // We pass a Zero for the menu handle so the menu size is 472 // not computed this is done via an WM_NCCALC 473 CreateParams cp = new CreateParams (); 474 Rectangle rect; 475 476 cp.WindowStyle = initial_style; 477 cp.WindowExStyle = initial_ex_style; 478 479 rect = GetClientRectangle (cp, null, width, height); 480 481 return rect; 482 } 483 } 484 485 public bool ExposePending { 486 get { 487 return expose_pending; 488 } 489 } 490 491 public IntPtr Handle { 492 get { 493 if (handle == IntPtr.Zero) { 494 throw new ArgumentNullException("Handle", "Handle is not yet assigned, need a ClientWindow"); 495 } 496 return handle; 497 } 498 } 499 500 public int Height { 501 get { 502 return height; 503 } 504 505 set { 506 height = value; 507 } 508 } 509 510 public Menu Menu { 511 get { 512 return menu; 513 } 514 515 set { 516 menu = value; 517 } 518 } 519 520 public bool Reparented { 521 get { 522 return reparented; 523 } 524 525 set { 526 reparented = value; 527 } 528 } 529 530 public uint Opacity { 531 get { 532 return opacity; 533 } 534 535 set { 536 opacity = value; 537 } 538 } 539 540 public XEventQueue Queue { 541 get { 542 return queue; 543 } 544 545 set { 546 queue = value; 547 } 548 } 549 550 public bool Enabled { 551 get { 552 if (!enabled) { 553 return false; 554 } 555 556 if (parent != null) { 557 return parent.Enabled; 558 } 559 560 return true; 561 } 562 563 set { 564 enabled = value; 565 } 566 } 567 568 public IntPtr EnabledHwnd { 569 get { 570 if (Enabled || parent == null) { 571 return Handle; 572 } 573 574 return parent.EnabledHwnd; 575 } 576 } 577 578 public Point MenuOrigin { 579 get { 580 Form frm = Control.FromHandle (handle) as Form; 581 if (frm != null && frm.window_manager != null) 582 return frm.window_manager.GetMenuOrigin (); 583 584 Point pt; 585 Size border_3D_size = ThemeEngine.Current.Border3DSize; 586 587 pt = new Point(0, 0); 588 589 if (border_style == FormBorderStyle.Fixed3D) { 590 pt.X += border_3D_size.Width; 591 pt.Y += border_3D_size.Height; 592 } else if (border_style == FormBorderStyle.FixedSingle) { 593 pt.X += 1; 594 pt.Y += 1; 595 } 596 597 if (this.title_style == TitleStyle.Normal) { 598 pt.Y += caption_height; 599 } else if (this.title_style == TitleStyle.Tool) { 600 pt.Y += tool_caption_height; 601 } 602 603 return pt; 604 } 605 } 606 607 public Rectangle Invalid { 608 get { 609 if (invalid_list.Count == 0) 610 return Rectangle.Empty; 611 612 Rectangle result = (Rectangle)invalid_list[0]; 613 for (int i = 1; i < invalid_list.Count; i ++) { 614 result = Rectangle.Union (result, (Rectangle)invalid_list[i]); 615 } 616 return result; 617 } 618 } 619 620 public Rectangle[] ClipRectangles { 621 get { 622 return (Rectangle[]) invalid_list.ToArray (typeof (Rectangle)); 623 } 624 } 625 626 public Rectangle NCInvalid { 627 get { return nc_invalid; } 628 set { nc_invalid = value; } 629 630 } 631 632 public bool NCExposePending { 633 get { 634 return nc_expose_pending; 635 } 636 } 637 638 public Hwnd Parent { 639 get { 640 return parent; 641 } 642 643 set { 644 if (parent != null) 645 parent.children.Remove (this); 646 parent = value; 647 if (parent != null) 648 parent.children.Add (this); 649 } 650 } 651 652 public bool Mapped { 653 get { 654 if (!mapped) { 655 return false; 656 } 657 658 if (parent != null) { 659 return parent.Mapped; 660 } 661 662 return true; 663 } 664 665 set { 666 mapped = value; 667 } 668 } 669 670 public int CaptionHeight { 671 get { return caption_height; } 672 set { caption_height = value; } 673 } 674 675 public int ToolCaptionHeight { 676 get { return tool_caption_height; } 677 set { tool_caption_height = value; } 678 } 679 680 public TitleStyle TitleStyle { 681 get { 682 return title_style; 683 } 684 685 set { 686 title_style = value; 687 } 688 } 689 690 public object UserData { 691 get { 692 return user_data; 693 } 694 695 set { 696 user_data = value; 697 } 698 } 699 700 public IntPtr WholeWindow { 701 get { 702 return whole_window; 703 } 704 705 set { 706 whole_window = value; 707 708 zombie = false; 709 710 if (whole_window != IntPtr.Zero) { 711 lock (windows) { 712 if (windows[whole_window] == null) { 713 windows[whole_window] = this; 714 } 715 } 716 } 717 } 718 } 719 720 public int Width { 721 get { 722 return width; 723 } 724 725 set { 726 width = value; 727 } 728 } 729 730 public bool Visible { 731 get { 732 return visible; 733 } 734 735 set { 736 visible = value; 737 } 738 } 739 740 public int X { 741 get { 742 return x; 743 } 744 745 set { 746 x = value; 747 } 748 } 749 750 public int Y { 751 get { 752 return y; 753 } 754 755 set { 756 y = value; 757 } 758 } 759 760 #endregion // Instance properties 761 762 #region Methods AddInvalidArea(int x, int y, int width, int height)763 public void AddInvalidArea(int x, int y, int width, int height) { 764 AddInvalidArea(new Rectangle(x, y, width, height)); 765 } 766 AddInvalidArea(Rectangle rect)767 public void AddInvalidArea(Rectangle rect) { 768 ArrayList tmp = new ArrayList (); 769 foreach (Rectangle r in invalid_list) { 770 if (!rect.Contains (r)) { 771 tmp.Add (r); 772 } 773 } 774 tmp.Add (rect); 775 invalid_list = tmp; 776 } 777 ClearInvalidArea()778 public void ClearInvalidArea() { 779 invalid_list.Clear(); 780 expose_pending = false; 781 } 782 AddNcInvalidArea(int x, int y, int width, int height)783 public void AddNcInvalidArea(int x, int y, int width, int height) { 784 if (nc_invalid == Rectangle.Empty) { 785 nc_invalid = new Rectangle (x, y, width, height); 786 return; 787 } 788 789 int right, bottom; 790 right = Math.Max (nc_invalid.Right, x + width); 791 bottom = Math.Max (nc_invalid.Bottom, y + height); 792 nc_invalid.X = Math.Min (nc_invalid.X, x); 793 nc_invalid.Y = Math.Min (nc_invalid.Y, y); 794 795 nc_invalid.Width = right - nc_invalid.X; 796 nc_invalid.Height = bottom - nc_invalid.Y; 797 } 798 AddNcInvalidArea(Rectangle rect)799 public void AddNcInvalidArea(Rectangle rect) { 800 if (nc_invalid == Rectangle.Empty) { 801 nc_invalid = rect; 802 return; 803 } 804 nc_invalid = Rectangle.Union (nc_invalid, rect); 805 } 806 ClearNcInvalidArea()807 public void ClearNcInvalidArea() { 808 nc_invalid = Rectangle.Empty; 809 nc_expose_pending = false; 810 } 811 ToString()812 public override string ToString() { 813 return String.Format("Hwnd, Mapped:{3} ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Zombie={4}, Parent:[{2:X}]", client_window.ToInt32(), whole_window.ToInt32(), parent != null ? parent.ToString() : "<null>", Mapped, zombie); 814 } 815 GetNextStackedFormLocation(CreateParams cp, Hwnd parent_hwnd)816 public static Point GetNextStackedFormLocation (CreateParams cp, Hwnd parent_hwnd) 817 { 818 if (cp.control == null) 819 return Point.Empty; 820 821 int X = cp.X; 822 int Y = cp.Y; 823 Point previous, next; 824 Rectangle within; 825 826 if (parent_hwnd != null) { 827 Control parent = cp.control.Parent; 828 previous = parent_hwnd.previous_child_startup_location; 829 if (parent_hwnd.client_rectangle == Rectangle.Empty && parent != null) { 830 within = parent.ClientRectangle; 831 } else { 832 within = parent_hwnd.client_rectangle; 833 } 834 } else { 835 previous = Hwnd.previous_main_startup_location; 836 within = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea; 837 } 838 839 if (previous.X == int.MinValue || previous.Y == int.MinValue) { 840 next = Point.Empty; 841 } else { 842 next = new Point (previous.X + 22, previous.Y + 22); 843 } 844 845 if (!within.Contains (next.X * 3, next.Y * 3)) { 846 next = Point.Empty; 847 } 848 849 if (next == Point.Empty && cp.Parent == IntPtr.Zero) { 850 next = new Point (22, 22); 851 } 852 853 if (parent_hwnd != null) { 854 parent_hwnd.previous_child_startup_location = next; 855 } else { 856 Hwnd.previous_main_startup_location = next; 857 } 858 859 if (X == int.MinValue && Y == int.MinValue) { 860 X = next.X; 861 Y = next.Y; 862 } 863 864 return new Point (X, Y); 865 } 866 867 #endregion // Methods 868 869 internal struct Borders 870 { 871 public int top; 872 public int bottom; 873 public int left; 874 public int right; 875 InflateSystem.Windows.Forms.Hwnd.Borders876 public void Inflate (Size size) 877 { 878 left += size.Width; 879 right += size.Width; 880 top += size.Height; 881 bottom += size.Height; 882 } 883 ToStringSystem.Windows.Forms.Hwnd.Borders884 public override string ToString () 885 { 886 return string.Format("{{top={0}, bottom={1}, left={2}, right={3}}}", top, bottom, left, right); 887 } 888 operator ==System.Windows.Forms.Hwnd.Borders889 public static bool operator == (Borders a, Borders b) 890 { 891 return (a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom); 892 } 893 operator !=System.Windows.Forms.Hwnd.Borders894 public static bool operator != (Borders a, Borders b) 895 { 896 return !(a == b); 897 } 898 EqualsSystem.Windows.Forms.Hwnd.Borders899 public override bool Equals (object obj) 900 { 901 return base.Equals (obj); 902 } 903 GetHashCodeSystem.Windows.Forms.Hwnd.Borders904 public override int GetHashCode () 905 { 906 return base.GetHashCode (); 907 } 908 } 909 } 910 } 911