Parcourir la source

2006-03-17 Peter Dennis Bartok <[email protected]>

	* CreateParams.cs: Added internal menu field
	* Control.cs: 
	  - Switched call order for UpdateBounds; now we always call
	    the one that also takes ClientSize, and we're calculating the 
	    client size via driver method in the others. The previous
	    method of tracking client size by difference wasn't working
	    for forms where even the starting client size wouldn't match
	    the overall form size (due to borders) (Part of fix for #77729)
	  - CreateParams(): Do not use parent.Handle unless the handle is
	    already created. Causes havoc with Nexxia and throws off our
	    creation of controls
	* XplatUIX11.cs:
	  - Created new PerformNCCalc method to trigger WM_NCCALCSIZE message
	  - Switched handling of ConfigureNotify over to new PerformNCCalc 
	    method (consolidates code)
	  - Changed RequestNCRecalc to use new PerformNCCalc method
	  - Added calls to RequestNCRecalc when menus and borders are changed
	    to allow app to set NC size. (Part of fix for #77729) This matches
	    when MS send a WM_NCRECALC on Win32 windows.
	  - Now sending WM_WINDOWPOSCHANGED when toplevel for is made visible
	    (Part of fix for #77729). This matches what MS does, they also
	    send that message when the form is made visible.
	  - XException.GetMessage: Improved usability of X errors by including
	    a translation of the window into Hwnd and Control class
	  - Improved debug info for window creation, reparenting and destruction
	  - Created helper method WindowIsMapped() [Currently not used]
	* XplatUIWin32.cs: Added ToString() debug helper to RECT structure
	* Form.cs:
	  - CreateParams: Now setting our menu on the new internal menu field
	  - SetClientSizeCore: Now passing cp.menu instead of ActiveMenu to
	    avoid calculating the same property twice
	* Hwnd.cs:
	  - Improved usability of ToString() for debugging purposes
	  - GetWindowRectangle(): Now uses proper CalcMenuBarSize method to
	    determine the height of the menu, instead of just the font. This
	    required to also create a graphics context and to keep a bmp 
	    around (for performance reasons)


svn path=/trunk/mcs/; revision=58131
Peter Dennis Bartok il y a 20 ans
Parent
commit
5601ac2287

+ 40 - 0
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog

@@ -1,3 +1,43 @@
+2006-03-17  Peter Dennis Bartok  <[email protected]> 
+
+	* CreateParams.cs: Added internal menu field
+	* Control.cs: 
+	  - Switched call order for UpdateBounds; now we always call
+	    the one that also takes ClientSize, and we're calculating the 
+	    client size via driver method in the others. The previous
+	    method of tracking client size by difference wasn't working
+	    for forms where even the starting client size wouldn't match
+	    the overall form size (due to borders) (Part of fix for #77729)
+	  - CreateParams(): Do not use parent.Handle unless the handle is
+	    already created. Causes havoc with Nexxia and throws off our
+	    creation of controls
+	* XplatUIX11.cs:
+	  - Created new PerformNCCalc method to trigger WM_NCCALCSIZE message
+	  - Switched handling of ConfigureNotify over to new PerformNCCalc 
+	    method (consolidates code)
+	  - Changed RequestNCRecalc to use new PerformNCCalc method
+	  - Added calls to RequestNCRecalc when menus and borders are changed
+	    to allow app to set NC size. (Part of fix for #77729) This matches
+	    when MS send a WM_NCRECALC on Win32 windows.
+	  - Now sending WM_WINDOWPOSCHANGED when toplevel for is made visible
+	    (Part of fix for #77729). This matches what MS does, they also
+	    send that message when the form is made visible.
+	  - XException.GetMessage: Improved usability of X errors by including
+	    a translation of the window into Hwnd and Control class
+	  - Improved debug info for window creation, reparenting and destruction
+	  - Created helper method WindowIsMapped() [Currently not used]
+	* XplatUIWin32.cs: Added ToString() debug helper to RECT structure
+	* Form.cs:
+	  - CreateParams: Now setting our menu on the new internal menu field
+	  - SetClientSizeCore: Now passing cp.menu instead of ActiveMenu to
+	    avoid calculating the same property twice
+	* Hwnd.cs:
+	  - Improved usability of ToString() for debugging purposes
+	  - GetWindowRectangle(): Now uses proper CalcMenuBarSize method to
+	    determine the height of the menu, instead of just the font. This
+	    required to also create a graphics context and to keep a bmp 
+	    around (for performance reasons)
+
 2006-03-17  Peter Dennis Bartok  <[email protected]>
 
 	* MenuAPI.cs: Added OnMouseUp method

+ 16 - 15
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs

@@ -2345,7 +2345,7 @@ namespace System.Windows.Forms
 					create_params.ExStyle |= (int)WindowExStyles.WS_EX_ACCEPTFILES;
 				}
 
-				if (parent!=null) {
+				if ((parent!=null) && (parent.IsHandleCreated)) {
 					create_params.Parent = parent.Handle;
 				}
 
@@ -3621,13 +3621,23 @@ namespace System.Windows.Forms
 
 		[EditorBrowsable(EditorBrowsableState.Advanced)]
 		protected void UpdateBounds(int x, int y, int width, int height) {
+			CreateParams	cp;
+			Rectangle	rect;
+
+			// Calculate client rectangle
+			rect = new Rectangle(0, 0, 0, 0);
+			cp = CreateParams;
+
+			XplatUI.CalculateWindowRect(ref rect, cp.Style, cp.ExStyle, cp.menu, out rect);
+			UpdateBounds(x, y, width, height, width - (rect.Right - rect.Left), height - (rect.Bottom - rect.Top));
+		}
+
+		[EditorBrowsable(EditorBrowsableState.Advanced)]
+		protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
 			// UpdateBounds only seems to set our sizes and fire events but not update the GUI window to match
 			bool	moved	= false;
 			bool	resized	= false;
 
-			int	client_x_diff = this.bounds.Width-this.client_size.Width;
-			int	client_y_diff = this.bounds.Height-this.client_size.Height;
-
 			// Needed to generate required notifications
 			if ((this.bounds.X!=x) || (this.bounds.Y!=y)) {
 				moved=true;
@@ -3642,9 +3652,8 @@ namespace System.Windows.Forms
 			bounds.Width=width;
 			bounds.Height=height;
 
-			// Update client rectangle as well
-			client_size.Width=width-client_x_diff;
-			client_size.Height=height-client_y_diff;
+			client_size.Width=clientWidth;
+			client_size.Height=clientHeight;
 
 			if (moved) {
 				OnLocationChanged(EventArgs.Empty);
@@ -3655,14 +3664,6 @@ namespace System.Windows.Forms
 			}
 		}
 
-		[EditorBrowsable(EditorBrowsableState.Advanced)]
-		protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
-			UpdateBounds(x, y, width, height);
-
-			this.client_size.Width=clientWidth;
-			this.client_size.Height=clientHeight;
-		}
-
 		[EditorBrowsable(EditorBrowsableState.Advanced)]
 		protected void UpdateStyles() {
 			if (!IsHandleCreated) {

+ 2 - 1
mcs/class/Managed.Windows.Forms/System.Windows.Forms/CreateParams.cs

@@ -17,7 +17,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2004 Novell, Inc.
+// Copyright (c) 2004-2006 Novell, Inc.
 //
 // Authors:
 //	Peter Bartok	[email protected]
@@ -43,6 +43,7 @@ namespace System.Windows.Forms {
 		private int	style;
 		private object	param;
 		private IntPtr	parent;
+		internal Menu	menu;
 		#endregion 	// Local variables
 
 		#region Public Constructors

+ 3 - 2
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs

@@ -17,7 +17,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2004-2005 Novell, Inc.
+// Copyright (c) 2004-2006 Novell, Inc.
 //
 // Authors:
 //	Peter Bartok	[email protected]
@@ -891,6 +891,7 @@ namespace System.Windows.Forms {
 				cp.ExStyle = 0;
 				cp.Param = 0;
 				cp.Parent = IntPtr.Zero;
+				cp.menu = ActiveMenu;
 
 //				if (start_position == FormStartPosition.WindowsDefaultLocation) {
 					cp.X = unchecked((int)0x80000000);
@@ -1575,7 +1576,7 @@ namespace System.Windows.Forms {
 
 			clientsize_set = new Size(x, y);
 
-			if (XplatUI.CalculateWindowRect(ref ClientRect, cp.Style, cp.ExStyle, ActiveMenu, out WindowRect)) {
+			if (XplatUI.CalculateWindowRect(ref ClientRect, cp.Style, cp.ExStyle, cp.menu, out WindowRect)) {
 				SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
 			}
 		}

+ 8 - 3
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Hwnd.cs

@@ -17,7 +17,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2005-2006 Novell, Inc. (http://www.novell.com)
 //
 // Authors:
 //	Peter Bartok	([email protected])
@@ -72,6 +72,7 @@ namespace System.Windows.Forms {
 		internal int		tool_caption_height;
 		internal bool		whacky_wm;
 		internal bool		fixed_size;
+		internal static Bitmap	bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 		#endregion	// Local Variables
 
 		#region Constructors and destructors
@@ -152,7 +153,11 @@ namespace System.Windows.Forms {
 			if (menu != null) {
 				int menu_height = menu.Rect.Height;
 				if (menu_height == 0) {
-					menu_height = ThemeEngine.Current.MenuFont.Height;
+					Graphics g;
+
+					g = Graphics.FromImage(bmp);
+					menu_height = ThemeEngine.Current.CalcMenuBarSize(g, menu, client_rect.Width);
+					g.Dispose();
 				}
 
 				rect.Y -= menu_height;
@@ -562,7 +567,7 @@ namespace System.Windows.Forms {
 		}
 
 		public override string ToString() {
-			return String.Format("Hwnd, ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Handle:0x{2:X}", client_window.ToInt32(), whole_window.ToInt32(), handle.ToInt32());
+			return String.Format("Hwnd, ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Parent:[{2:X}]", client_window.ToInt32(), whole_window.ToInt32(), parent != null ? parent.ToString() : "<null>");
 		}
 
 		#endregion	// Methods

+ 4 - 0
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIWin32.cs

@@ -86,6 +86,10 @@ namespace System.Windows.Forms {
 			internal int		top;
 			internal int		right;
 			internal int		bottom;
+			public override string ToString() {
+				return String.Format("RECT left={0}, top={1}, right={2}, bottom={3}, width={4}, height={5}", left, top, right, bottom, right-left, bottom-top);
+			}
+
 		}
 
 		[StructLayout(LayoutKind.Sequential)]

+ 72 - 56
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

@@ -285,12 +285,30 @@ namespace System.Windows.Forms {
 				StringBuilder	sb;
 				string		x_error_text;
 				string		error;
+				string		hwnd_text;
+				string		control_text;
+				Hwnd		hwnd;
+				Control		c;
 
 				sb = new StringBuilder(160);
 				XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
 				x_error_text = sb.ToString();
+				hwnd = Hwnd.ObjectFromHandle(ResourceID);
+				if (hwnd != null) {
+					hwnd_text = hwnd.ToString();
+					c = Control.FromHandle(hwnd.Handle);
+					if (c != null) {
+						control_text = c.ToString();
+					} else {
+						control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
+					}
+				} else {
+					hwnd_text = "<null>";
+					control_text = "<null>";
+				}
+
 
-				error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:x}\n  Serial:      {4}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial);
+				error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:X}\n  Serial:      {4}\n  Hwnd:        {5}\n  Control:     {6}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
 				return error;
 			}
 		}
@@ -1368,6 +1386,37 @@ namespace System.Windows.Forms {
 			}
 		}
 
+		private void PerformNCCalc(Hwnd hwnd) {
+			XplatUIWin32.NCCALCSIZE_PARAMS	ncp;
+			IntPtr				ptr;
+			Rectangle			rect;
+
+			rect = hwnd.DefaultClientRect;
+
+			ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
+			ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
+
+			ncp.rgrc1.left = rect.Left;
+			ncp.rgrc1.top = rect.Top;
+			ncp.rgrc1.right = rect.Right;
+			ncp.rgrc1.bottom = rect.Bottom;
+
+			Marshal.StructureToPtr(ncp, ptr, true);
+			NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
+			ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
+			Marshal.FreeHGlobal(ptr);
+
+			// FIXME - debug this with Menus, need to set hwnd.ClientRect
+
+			rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
+
+			Control c;
+			c = Control.FromHandle(hwnd.Handle);
+
+			if (hwnd.visible) {
+				XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
+			}
+		}
 		#endregion	// Private Methods
 
 		#region	Callbacks
@@ -1983,7 +2032,7 @@ namespace System.Windows.Forms {
 			hwnd.ClientWindow = ClientWindow;
 
 			#if DriverDebug || DriverDebugCreate
-				Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
+				Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
 			#endif
 				       
 			lock (XlibLock) {
@@ -2366,13 +2415,13 @@ namespace System.Windows.Forms {
 			hwnd = Hwnd.ObjectFromHandle(handle);
 
 			if (hwnd == null) {
-				#if DriverDebug
+				#if DriverDebug || DriverDebugDestroy
 					Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
 				#endif
 				return;
 			}
 
-			#if DriverDebug
+			#if DriverDebug || DriverDebugDestroy
 				Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
 			#endif
 
@@ -2977,10 +3026,6 @@ namespace System.Windows.Forms {
 
 				case XEventName.ConfigureNotify: {
 					if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {	// Ignore events for children (SubstructureNotify) and client areas
-						XplatUIWin32.NCCALCSIZE_PARAMS	ncp;
-						IntPtr				ptr;
-						Rectangle			rect;
-
 						#if DriverDebugExtra
 							Console.WriteLine("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}", hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
 						#endif
@@ -2988,26 +3033,7 @@ namespace System.Windows.Forms {
 						hwnd.configure_pending = false;
 
 						// We need to adjust our client window to track the resize of whole_window
-						rect = hwnd.DefaultClientRect;
-
-						ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
-						ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
-
-						ncp.rgrc1.left = rect.Left;
-						ncp.rgrc1.top = rect.Top;
-						ncp.rgrc1.right = rect.Right;
-						ncp.rgrc1.bottom = rect.Bottom;
-
-						Marshal.StructureToPtr(ncp, ptr, true);
-						NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
-						ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
-						Marshal.FreeHGlobal(ptr);
-
-						// FIXME - debug this with Menus, need to set hwnd.ClientRect
-
-						rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
-
-						XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
+						PerformNCCalc(hwnd);
 					} else {
 						goto ProcessNextMessage;
 					}
@@ -3517,9 +3543,6 @@ namespace System.Windows.Forms {
 		}
 
 		internal override void RequestNCRecalc(IntPtr handle) {
-			XplatUIWin32.NCCALCSIZE_PARAMS	ncp;
-			IntPtr				ptr;
-			Rectangle			rect;
 			Hwnd				hwnd;
 
 			hwnd = Hwnd.ObjectFromHandle(handle);
@@ -3528,27 +3551,9 @@ namespace System.Windows.Forms {
 				return;
 			}
 
-			// We need to adjust our client window to track the resize of whole_window
-			rect = hwnd.DefaultClientRect;
-
-			ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
-			ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
-
-			ncp.rgrc1.left = rect.Left;
-			ncp.rgrc1.top = rect.Top;
-			ncp.rgrc1.right = rect.Right;
-			ncp.rgrc1.bottom = rect.Bottom;
-
-			Marshal.StructureToPtr(ncp, ptr, true);
-			NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
-			ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
-			Marshal.FreeHGlobal(ptr);
-
-			rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
-
-			XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
-
+			PerformNCCalc(hwnd);
 			SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
+			InvalidateWholeWindow(handle);
 		}
 
 		internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
@@ -3686,10 +3691,7 @@ namespace System.Windows.Forms {
 			hwnd = Hwnd.ObjectFromHandle(handle);
 
 			hwnd.border_style = border_style;
-
-			XMoveResizeWindow(DisplayHandle, hwnd.client_window, hwnd.ClientRect.X, hwnd.ClientRect.Y, hwnd.ClientRect.Width, hwnd.ClientRect.Height);
-
-			InvalidateWholeWindow(handle);
+			RequestNCRecalc(handle);
 		}
 
 		internal override void SetCaretPos(IntPtr handle, int x, int y) {
@@ -3785,7 +3787,7 @@ namespace System.Windows.Forms {
 			hwnd = Hwnd.ObjectFromHandle(handle);
 			hwnd.menu = menu;
 
-			// FIXME - do we need to trigger some resize?
+			RequestNCRecalc(handle);
 		}
 
 		internal override void SetModal(IntPtr handle, bool Modal) {
@@ -3872,6 +3874,8 @@ namespace System.Windows.Forms {
 							case FormWindowState.Minimized:	SetWindowState(handle, FormWindowState.Minimized); break;
 							case FormWindowState.Maximized:	SetWindowState(handle, FormWindowState.Maximized); break;
 						}
+
+						SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
 					} else {
 						XMapWindow(DisplayHandle, hwnd.whole_window);
 						XMapWindow(DisplayHandle, hwnd.client_window);
@@ -4229,6 +4233,18 @@ namespace System.Windows.Forms {
 			hwnd.expose_pending = true;
 #endif
 		}
+
+		private bool WindowIsMapped(IntPtr handle) {
+			XWindowAttributes attributes;
+
+			attributes = new XWindowAttributes();
+			XGetWindowAttributes(DisplayHandle, handle, ref attributes);
+			if (attributes.map_state == MapState.IsUnmapped) {
+				return false;
+			}
+			return true;
+		}
+
 		#endregion	// Public Static Methods
 
 		#region Events