2007-03-29 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / NativeWindow.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) 2004-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Dennis Bartok     pbartok@novell.com
24 //
25
26
27 // COMPLETE
28
29 //#define ExternalExceptionHandler
30
31 using System.Runtime.Remoting;
32 using System.Runtime.InteropServices;
33 using System.Runtime.CompilerServices;
34 using System.Threading;
35 using System.Collections;
36 using System.Diagnostics;
37
38 namespace System.Windows.Forms
39 {
40         public class NativeWindow : MarshalByRefObject {
41                 internal IntPtr                 window_handle;
42                 static internal Hashtable       window_collection = new Hashtable();
43
44                 [ThreadStatic]
45                 static NativeWindow WindowCreating;
46
47                 #region Public Constructors
48                 public NativeWindow()
49                 {
50                         window_handle=IntPtr.Zero;
51                 }
52                 #endregion      // Public Constructors
53
54                 #region Public Instance Properties
55                 public IntPtr Handle {
56                         get {
57                                 return window_handle;
58                         }
59                 }
60                 #endregion      // Public Instance Properties
61
62                 #region Public Static Methods
63                 public static NativeWindow FromHandle(IntPtr handle)
64                 {
65                         NativeWindow window=new NativeWindow();
66
67                         window.AssignHandle(handle);
68                         return window;
69                 }
70                 #endregion      // Public Static Methods
71
72                 #region Private and Internal Methods
73                 internal static NativeWindow FindWindow(IntPtr handle)
74                 {
75                         NativeWindow rv;
76                         lock (window_collection) {
77                                 rv = (NativeWindow)window_collection[handle];
78                         }
79                         return rv;
80                 }
81
82                 internal void InvalidateHandle()
83                 {
84                         lock (window_collection) {
85                                 window_collection.Remove(window_handle);
86                         }
87                         window_handle = IntPtr.Zero;
88                 }
89                 #endregion
90
91                 #region Public Instance Methods
92                 public void AssignHandle(IntPtr handle)
93                 {
94                         lock (window_collection) {
95                                 if (window_handle != IntPtr.Zero)
96                                         window_collection.Remove(window_handle);
97                                 window_handle=handle;
98                                 window_collection.Add(window_handle, this);
99                         }
100                         OnHandleChange();
101                 }
102
103                 public virtual void CreateHandle(CreateParams create_params)
104                 {
105                         if (create_params != null) {
106                                 WindowCreating = this;
107
108                                 window_handle=XplatUI.CreateWindow(create_params);
109
110                                 WindowCreating = null;
111
112                                 if (window_handle != IntPtr.Zero) {
113                                         lock (window_collection) {
114                                                 window_collection[window_handle] = this;
115                                         }
116                                 }
117                         }
118
119                 }
120
121                 public void DefWndProc(ref Message m)
122                 {
123                         m.Result=XplatUI.DefWndProc(ref m);
124                 }
125
126                 public virtual void DestroyHandle()
127                 {
128                         if (window_handle != IntPtr.Zero) {
129                                 XplatUI.DestroyWindow(window_handle);
130                         }
131                 }
132
133                 public virtual void ReleaseHandle()
134                 {
135                         lock (window_collection) {
136                                 window_collection.Remove(window_handle);
137                         }
138                         window_handle=IntPtr.Zero;
139                         OnHandleChange();
140                 }
141
142                 #endregion      // Public Instance Methods
143
144                 #region Protected Instance Methods
145                 ~NativeWindow()
146                 {
147                 }
148
149                 protected virtual void OnHandleChange()
150                 {
151                 }
152
153                 protected virtual void OnThreadException(Exception e)
154                 {
155                         Application.OnThreadException(e);
156                 }
157
158                 protected virtual void WndProc(ref Message m)
159                 {
160                         DefWndProc(ref m);
161                 }
162
163                 internal static IntPtr WndProc(IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam)
164                 {
165                         Message         m = new Message();
166                         NativeWindow    window = null;
167
168                         try {
169                                 lock (window_collection) {
170                                         window = (NativeWindow)window_collection[hWnd];
171                                 }
172                                 m.HWnd=hWnd;
173                                 m.Msg=(int)msg;
174                                 m.WParam=wParam;
175                                 m.LParam=lParam;
176                                 m.Result=IntPtr.Zero;
177
178                                 if (window != null)
179                                         window.WndProc(ref m);
180                                 else if (WindowCreating != null) {
181                                         // we need to do this AssignHandle here instead of relying on
182                                         // Control.WndProc to do it, because subclasses can override
183                                         // WndProc, install their own WM_CREATE block, and look at
184                                         // this.Handle, and it needs to be set.  Otherwise, we end up
185                                         // recursively creating windows and emitting WM_CREATE.
186                                         if (WindowCreating.window_handle == IntPtr.Zero)
187                                                 WindowCreating.AssignHandle (hWnd);
188
189                                         WindowCreating.WndProc (ref m);
190                                 }
191                                 else
192                                         m.Result=XplatUI.DefWndProc(ref m);
193                         }
194                         catch (Exception ex) {
195 #if !ExternalExceptionHandler                           
196                                 if (window != null)
197                                         window.OnThreadException(ex);
198 #else
199                                 throw;
200 #endif
201                         }
202
203                         #if debug
204                                 Console.WriteLine("NativeWindow.cs: Message {0}, result {1}", msg, m.Result);
205                         #endif
206
207                         return m.Result;
208                 }
209                 #endregion      // Protected Instance Methods
210         }
211 }