* TreeView.cs: Don't draw the selected node when we lose
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Hwnd.cs
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 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                 private const int       caption_height = 0;                     // FIXME - Read this value from somewhere
44                 private const int       tool_caption_height = 0;                // FIXME - Read this value from somewhere
45
46                 private IntPtr          handle;
47                 internal IntPtr         client_window;
48                 internal IntPtr         whole_window;
49                 internal IntPtr         menu_handle;
50                 internal TitleStyle     title_style;
51                 internal FormBorderStyle        border_style;
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           zero_sized;
60                 internal Rectangle      invalid;
61                 internal bool           expose_pending;
62                 internal bool           nc_expose_pending;
63                 internal bool           configure_pending;
64                 internal Graphics       client_dc;
65                 internal object         user_data;
66                 internal Rectangle      client_rectangle;
67                 internal ArrayList      marshal_free_list;
68                 #endregion      // Local Variables
69
70                 #region Constructors and destructors
71                 public Hwnd() {
72                         x = 0;
73                         y = 0;
74                         width = 0;
75                         height = 0;
76                         visible = false;
77                         menu_handle = IntPtr.Zero;
78                         border_style = FormBorderStyle.None;
79                         client_window = IntPtr.Zero;
80                         whole_window = IntPtr.Zero;
81                         handle = IntPtr.Zero;
82                         parent = null;
83                         invalid = Rectangle.Empty;
84                         expose_pending = false;
85                         nc_expose_pending = false;
86                         client_rectangle = Rectangle.Empty;
87                         marshal_free_list = new ArrayList(2);
88                 }
89
90                 public void Dispose() {
91                         windows[client_window] = null;
92                         windows[whole_window] = null;
93                         for (int i = 0; i < marshal_free_list.Count; i++) {
94                                 Marshal.FreeHGlobal((IntPtr)marshal_free_list[i]);
95                         }
96                         marshal_free_list.Clear();
97                 }
98                 #endregion
99
100                 #region Static Methods
101                 public void SetObjectWindow(Hwnd obj, IntPtr window) {
102                         windows[window] = obj;
103                 }
104
105                 public static Hwnd ObjectFromWindow(IntPtr window) {
106                         return (Hwnd)windows[window];
107                 }
108
109                 public static Hwnd ObjectFromHandle(IntPtr handle) {
110                         //return (Hwnd)(((GCHandle)handle).Target);
111                         return (Hwnd)windows[handle];
112                 }
113
114                 public static IntPtr HandleFromObject(Hwnd obj) {
115                         return obj.handle;
116                 }
117
118                 public static Hwnd GetObjectFromWindow(IntPtr window) {
119                         return (Hwnd)windows[window];
120                 }
121
122                 public static IntPtr GetHandleFromWindow(IntPtr window) {
123                         Hwnd    hwnd;
124
125                         hwnd = (Hwnd)windows[window];
126                         if (hwnd != null) {
127                                 return hwnd.handle;
128                         } else {
129                                 return IntPtr.Zero;
130                         }
131                 }
132
133                 public static Rectangle GetWindowRectangle(FormBorderStyle border_style, IntPtr menu_handle, TitleStyle title_style, Rectangle client_rect) {
134                         Rectangle       rect;
135
136                         rect = new Rectangle(client_rect.Location, client_rect.Size);
137
138                         if (menu_handle != IntPtr.Zero) {
139                                 MenuAPI.MENU menu = MenuAPI.GetMenuFromID (menu_handle);
140                                 if (menu != null) {
141                                         int menu_height = menu.Height;
142                                         rect.Y -= menu_height;
143                                         rect.Height += menu_height;
144                                 } else
145                                         Console.WriteLine("Hwnd.GetWindowRectangle: No MENU for menu_handle = {0}", menu_handle);
146                         }
147
148                         switch(border_style) {
149                                 case FormBorderStyle.Fixed3D: {
150                                         rect.X -= 2;
151                                         rect.Y -= 2;
152                                         rect.Width += 4;
153                                         rect.Height += 4;
154                                         break;
155                                 }
156
157                                 case FormBorderStyle.FixedSingle: {
158                                         rect.X -= 1;
159                                         rect.Y -= 1;
160                                         rect.Width += 2;
161                                         rect.Height += 2;
162                                         break;
163                                 }
164                         }
165
166                         if (title_style == TitleStyle.Normal) {
167                                 rect.Y -= caption_height;
168                                 rect.Height += caption_height;
169                         } else if (title_style == TitleStyle.Tool) {
170                                 rect.Y -= tool_caption_height;
171                                 rect.Height += tool_caption_height;
172                         }
173
174                         return rect;
175                 }
176
177                 public static Rectangle GetClientRectangle(FormBorderStyle border_style, IntPtr menu_handle, TitleStyle title_style, int width, int height) {
178                         Rectangle rect;
179
180                         rect = new Rectangle(0, 0, width, height);
181
182                         if (menu_handle != IntPtr.Zero) {
183                                 MenuAPI.MENU menu = MenuAPI.GetMenuFromID (menu_handle);
184                                 if (menu != null) {
185                                         int menu_height = menu.Height;
186                                         rect.Y += menu_height;
187                                         rect.Height -= menu_height;
188                                 } else
189                                         Console.WriteLine("Hwnd.GetClientRectangle: No MENU for menu_handle = {0}", menu_handle);
190                         }
191
192                         if (border_style == FormBorderStyle.Fixed3D) {
193                                 rect.X += 2;
194                                 rect.Y += 2;
195                                 rect.Width -= 4;
196                                 rect.Height -= 4;
197                         } else if (border_style == FormBorderStyle.FixedSingle) {
198                                 rect.X += 1;
199                                 rect.Y += 1;
200                                 rect.Width -= 2;
201                                 rect.Height -= 2;
202                         }
203
204                         if (title_style == TitleStyle.Normal)  {
205                                 rect.Y += caption_height;
206                                 rect.Height -= caption_height;
207                         } else if (title_style == TitleStyle.Normal)  {
208                                 rect.Y += tool_caption_height;
209                                 rect.Height -= tool_caption_height;
210                         }
211
212                         return rect;
213                 }
214                 #endregion      // Static Methods
215
216                 #region Instance Properties
217                 public FormBorderStyle BorderStyle {
218                         get {
219                                 return border_style;
220                         }
221
222                         set {
223                                 border_style = value;
224                         }
225                 }
226
227                 public Graphics ClientDC {
228                         get {
229                                 return client_dc;
230                         }
231
232                         set {
233                                 client_dc = value;
234                         }
235                 }
236
237                 public Rectangle ClientRect {
238                         get {
239                                 if (client_rectangle == Rectangle.Empty) {
240                                         return DefaultClientRect;
241                                 }
242                                 return client_rectangle;
243                         }
244
245                         set {
246                                 client_rectangle = value;
247                         }
248                 }
249
250                 public IntPtr ClientWindow {
251                         get {
252                                 return client_window;
253                         }
254
255                         set {
256                                 client_window = value;
257                                 handle = value;
258
259                                 if (windows[client_window] == null) {
260                                         windows[client_window] = this;
261                                 }
262                         }
263                 }
264
265                 public Rectangle DefaultClientRect {
266                         get {
267                                 Rectangle rect;
268
269                                 rect = new Rectangle(0, 0, width, height);
270
271                                 if (border_style == FormBorderStyle.Fixed3D) {
272                                         rect.X += 2;
273                                         rect.Y += 2;
274                                         rect.Width -= 4;
275                                         rect.Height -= 4;
276                                 } else if (border_style == FormBorderStyle.FixedSingle) {
277                                         rect.X += 1;
278                                         rect.Y += 1;
279                                         rect.Width -= 2;
280                                         rect.Height -= 2;
281                                 }
282
283                                 if (this.title_style == TitleStyle.Normal)  {
284                                         rect.Y += caption_height;
285                                         rect.Height -= caption_height;
286                                 } else if (this.title_style == TitleStyle.Normal)  {
287                                         rect.Y += tool_caption_height;
288                                         rect.Height -= tool_caption_height;
289                                 }
290
291                                 return rect;
292                         }
293                 }
294
295                 public bool ExposePending {
296                         get {
297                                 return expose_pending;
298                         }
299
300                         set {
301                                 expose_pending = value;
302                         }
303                 }
304
305                 public IntPtr Handle {
306                         get {
307                                 if (handle == IntPtr.Zero) {
308                                         throw new ArgumentNullException("Handle", "Handle is not yet assigned, need a ClientWindow");
309                                 }
310                                 return handle;
311                         }
312                 }
313
314                 public int Height {
315                         get {
316                                 return height;
317                         }
318
319                         set {
320                                 height = value;
321                         }
322                 }
323
324                 public IntPtr MenuHandle {
325                         get {
326                                 return menu_handle;
327                         }
328
329                         set {
330                                 menu_handle = value;
331                         }
332                 }
333
334                 public Point MenuOrigin {
335                         get {
336                                 Point   pt;
337
338                                 pt = new Point(0, 0);
339
340                                 if (border_style == FormBorderStyle.Fixed3D) {
341                                         pt.X += 2;
342                                         pt.Y += 2;
343                                 } else if (border_style == FormBorderStyle.FixedSingle) {
344                                         pt.X += 1;
345                                         pt.Y += 1;
346                                 }
347
348                                 if (this.title_style == TitleStyle.Normal)  {
349                                         pt.Y += caption_height;
350                                 } else if (this.title_style == TitleStyle.Normal)  {
351                                         pt.Y += tool_caption_height;
352                                 }
353
354                                 return pt;
355                         }
356                 }
357                 public Rectangle Invalid {
358                         get {
359                                 return invalid;
360                         }
361
362                         set {
363                                 invalid = value;
364                         }
365                 }
366
367                 public bool NCExposePending {
368                         get {
369                                 return nc_expose_pending;
370                         }
371
372                         set {
373                                 nc_expose_pending = value;
374                         }
375                 }
376
377                 public Hwnd Parent {
378                         get {
379                                 return parent;
380                         }
381
382                         set {
383                                 parent = value;
384                         }
385                 }
386
387                 public TitleStyle TitleStyle {
388                         get {
389                                 return title_style;
390                         }
391
392                         set {
393                                 title_style = value;
394                         }
395                 }
396
397                 public object UserData {
398                         get {
399                                 return user_data;
400                         }
401
402                         set {
403                                 user_data = value;
404                         }
405                 }
406
407                 public IntPtr WholeWindow {
408                         get {
409                                 return whole_window;
410                         }
411
412                         set {
413                                 whole_window = value;
414
415                                 if (windows[whole_window] == null) {
416                                         windows[whole_window] = this;
417                                 }
418                         }
419                 }
420
421                 public int Width {
422                         get {
423                                 return width;
424                         }
425
426                         set {
427                                 width = value;
428                         }
429                 }
430
431                 public bool Visible {
432                         get {
433                                 return visible;
434                         }
435
436                         set {
437                                 visible = value;
438                         }
439                 }
440
441                 public int X {
442                         get {
443                                 return x;
444                         }
445
446                         set {
447                                 x = value;
448                         }
449                 }
450
451                 public int Y {
452                         get {
453                                 return y;
454                         }
455
456                         set {
457                                 y = value;
458                         }
459                 }
460                 #endregion      // Instance properties
461
462                 #region Methods
463                 public void AddInvalidArea(int x, int y, int width, int height) {
464                         if (invalid == Rectangle.Empty) {
465                                 invalid = new Rectangle (x, y, width, height);
466                                 return;
467                         }
468
469                         int right, bottom;
470                         right = Math.Max (invalid.Right, x + width);
471                         bottom = Math.Max (invalid.Bottom, y + height);
472                         invalid.X = Math.Min (invalid.X, x);
473                         invalid.Y = Math.Min (invalid.Y, y);
474
475                         invalid.Width = right - invalid.X;
476                         invalid.Height = bottom - invalid.Y;
477                 }
478
479                 public void AddInvalidArea(Rectangle rect) {
480                         if (invalid == Rectangle.Empty) {
481                                 invalid = rect;
482                                 return;
483                         }
484                         invalid = Rectangle.Union (invalid, rect);
485                 }
486
487                 public void ClearInvalidArea() {
488                         invalid = Rectangle.Empty;
489                         expose_pending = false;
490                 }
491                 #endregion      // Methods
492         }
493 }