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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok (pbartok@novell.com)
30 using System.Collections;
32 using System.Runtime.InteropServices;
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)
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
44 private IntPtr handle;
45 internal IntPtr client_window;
46 internal IntPtr whole_window;
48 internal TitleStyle title_style;
49 internal FormBorderStyle border_style;
54 internal bool allow_drop;
56 internal bool visible;
57 internal uint opacity;
58 internal bool enabled;
59 internal bool zero_sized;
60 internal Rectangle invalid;
61 internal bool expose_pending;
62 internal bool nc_expose_pending;
63 internal bool configure_pending;
64 internal bool reparented;
65 internal Graphics client_dc;
66 internal object user_data;
67 internal Rectangle client_rectangle;
68 internal ArrayList marshal_free_list;
69 internal int caption_height;
70 internal int tool_caption_height;
71 #endregion // Local Variables
73 #region Constructors and destructors
81 border_style = FormBorderStyle.None;
82 client_window = IntPtr.Zero;
83 whole_window = IntPtr.Zero;
86 invalid = Rectangle.Empty;
87 expose_pending = false;
88 nc_expose_pending = false;
91 client_rectangle = Rectangle.Empty;
92 marshal_free_list = new ArrayList(2);
96 public void Dispose() {
97 windows[client_window] = null;
98 windows[whole_window] = null;
99 for (int i = 0; i < marshal_free_list.Count; i++) {
100 Marshal.FreeHGlobal((IntPtr)marshal_free_list[i]);
102 marshal_free_list.Clear();
106 #region Static Methods
107 public void SetObjectWindow(Hwnd obj, IntPtr window) {
108 windows[window] = obj;
111 public static Hwnd ObjectFromWindow(IntPtr window) {
112 return (Hwnd)windows[window];
115 public static Hwnd ObjectFromHandle(IntPtr handle) {
116 //return (Hwnd)(((GCHandle)handle).Target);
117 return (Hwnd)windows[handle];
120 public static IntPtr HandleFromObject(Hwnd obj) {
124 public static Hwnd GetObjectFromWindow(IntPtr window) {
125 return (Hwnd)windows[window];
128 public static IntPtr GetHandleFromWindow(IntPtr window) {
131 hwnd = (Hwnd)windows[window];
139 public static Rectangle GetWindowRectangle(FormBorderStyle border_style,
140 Menu menu, TitleStyle title_style, int caption_height,
141 int tool_caption_height, Rectangle client_rect)
145 rect = new Rectangle(client_rect.Location, client_rect.Size);
148 int menu_height = menu.Rect.Height;
149 rect.Y -= menu_height;
150 rect.Height += menu_height;
153 if (border_style == FormBorderStyle.Fixed3D) {
154 Size border_3D_size = ThemeEngine.Current.Border3DSize;
156 rect.X -= border_3D_size.Width;
157 rect.Y -= border_3D_size.Height;
158 rect.Width += border_3D_size.Width * 2;
159 rect.Height += border_3D_size.Height * 2;
160 } else if (border_style == FormBorderStyle.FixedSingle) {
165 } else if ((int) border_style == 0xFFFF) {
172 if (title_style == TitleStyle.Normal) {
173 rect.Y -= caption_height;
174 rect.Height += caption_height;
175 } else if (title_style == TitleStyle.Tool) {
176 rect.Y -= tool_caption_height;
177 rect.Height += tool_caption_height;
183 public static Rectangle GetClientRectangle(FormBorderStyle border_style, Menu menu, TitleStyle title_style, int caption_height, int tool_caption_height, int width, int height) {
186 rect = new Rectangle(0, 0, width, height);
189 int menu_height = menu.Rect.Height;
190 rect.Y += menu_height;
191 rect.Height -= menu_height;
194 if (border_style == FormBorderStyle.Fixed3D) {
195 Size border_3D_size = ThemeEngine.Current.Border3DSize;
197 rect.X += border_3D_size.Width;
198 rect.Y += border_3D_size.Height;
199 rect.Width -= border_3D_size.Width * 2;
200 rect.Height -= border_3D_size.Height * 2;
201 } else if (border_style == FormBorderStyle.FixedSingle) {
206 } else if ((int) border_style == 0xFFFF) {
213 if (title_style == TitleStyle.Normal) {
214 rect.Y += caption_height;
215 rect.Height -= caption_height;
216 } else if (title_style == TitleStyle.Tool) {
217 rect.Y += tool_caption_height;
218 rect.Height -= tool_caption_height;
223 #endregion // Static Methods
225 #region Instance Properties
226 public FormBorderStyle BorderStyle {
232 border_style = value;
236 public Graphics ClientDC {
246 public Rectangle ClientRect {
248 if (client_rectangle == Rectangle.Empty) {
249 return DefaultClientRect;
251 return client_rectangle;
255 client_rectangle = value;
259 public IntPtr ClientWindow {
261 return client_window;
265 client_window = value;
268 if (windows[client_window] == null) {
269 windows[client_window] = this;
274 public Rectangle DefaultClientRect {
276 // We pass a Zero for the menu handle so the menu size is
277 // not computed this is done via an WM_NCCALC
278 return GetClientRectangle (border_style, null, title_style,
279 caption_height, tool_caption_height, width, height);
283 public bool ExposePending {
285 return expose_pending;
289 expose_pending = value;
293 public IntPtr Handle {
295 if (handle == IntPtr.Zero) {
296 throw new ArgumentNullException("Handle", "Handle is not yet assigned, need a ClientWindow");
322 public bool Reparented {
332 public uint Opacity {
342 public bool Enabled {
348 if (parent != null) {
349 return parent.Enabled;
360 public IntPtr EnabledHwnd {
362 if (Enabled || parent == null) {
366 return parent.EnabledHwnd;
370 public Point MenuOrigin {
373 Size border_3D_size = ThemeEngine.Current.Border3DSize;
375 pt = new Point(0, 0);
377 if (border_style == FormBorderStyle.Fixed3D) {
378 pt.X += border_3D_size.Width;
379 pt.Y += border_3D_size.Height;
380 } else if (border_style == FormBorderStyle.FixedSingle) {
385 if (this.title_style == TitleStyle.Normal) {
386 pt.Y += caption_height;
387 } else if (this.title_style == TitleStyle.Normal) {
388 pt.Y += tool_caption_height;
394 public Rectangle Invalid {
404 public bool NCExposePending {
406 return nc_expose_pending;
410 nc_expose_pending = value;
424 public int CaptionHeight {
425 get { return caption_height; }
426 set { caption_height = value; }
429 public int ToolCaptionHeight {
430 get { return tool_caption_height; }
431 set { tool_caption_height = value; }
434 public TitleStyle TitleStyle {
444 public object UserData {
454 public IntPtr WholeWindow {
460 whole_window = value;
462 if (windows[whole_window] == null) {
463 windows[whole_window] = this;
478 public bool Visible {
507 #endregion // Instance properties
510 public void AddInvalidArea(int x, int y, int width, int height) {
511 if (invalid == Rectangle.Empty) {
512 invalid = new Rectangle (x, y, width, height);
517 right = Math.Max (invalid.Right, x + width);
518 bottom = Math.Max (invalid.Bottom, y + height);
519 invalid.X = Math.Min (invalid.X, x);
520 invalid.Y = Math.Min (invalid.Y, y);
522 invalid.Width = right - invalid.X;
523 invalid.Height = bottom - invalid.Y;
526 public void AddInvalidArea(Rectangle rect) {
527 if (invalid == Rectangle.Empty) {
531 invalid = Rectangle.Union (invalid, rect);
534 public void ClearInvalidArea() {
535 invalid = Rectangle.Empty;
536 expose_pending = false;
539 public override string ToString() {
540 return String.Format("Hwnd, ClientWindow:0x{0:X}, WholeWindow:0x{1:X}, Handle:0x{2:X}", client_window.ToInt32(), whole_window.ToInt32(), handle.ToInt32());
543 #endregion // Methods