2008-03-27 Carlos Alberto Cortez <calberto.cortez@gmail.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 #if NET_2_0
42                 , IWin32Window
43 #endif
44         {
45                 internal IntPtr                 window_handle;
46                 static internal Hashtable       window_collection = new Hashtable();
47
48                 [ThreadStatic]
49                 static NativeWindow WindowCreating;
50
51                 #region Public Constructors
52                 public NativeWindow()
53                 {
54                         window_handle=IntPtr.Zero;
55                 }
56                 #endregion      // Public Constructors
57
58                 #region Public Instance Properties
59                 public IntPtr Handle {
60                         get {
61                                 return window_handle;
62                         }
63                 }
64                 #endregion      // Public Instance Properties
65
66                 #region Public Static Methods
67                 public static NativeWindow FromHandle(IntPtr handle)
68                 {
69                         NativeWindow window=new NativeWindow();
70
71                         window.AssignHandle(handle);
72                         return window;
73                 }
74                 #endregion      // Public Static Methods
75
76                 #region Private and Internal Methods
77                 internal static NativeWindow FindWindow(IntPtr handle)
78                 {
79                         NativeWindow rv;
80                         lock (window_collection) {
81                                 rv = (NativeWindow)window_collection[handle];
82                         }
83                         return rv;
84                 }
85
86                 internal void InvalidateHandle()
87                 {
88                         lock (window_collection) {
89                                 window_collection.Remove(window_handle);
90                         }
91                         window_handle = IntPtr.Zero;
92                 }
93                 #endregion
94
95                 #region Public Instance Methods
96                 public void AssignHandle(IntPtr handle)
97                 {
98                         lock (window_collection) {
99                                 if (window_handle != IntPtr.Zero)
100                                         window_collection.Remove(window_handle);
101                                 window_handle=handle;
102                                 window_collection.Add(window_handle, this);
103                         }
104                         OnHandleChange();
105                 }
106
107                 public virtual void CreateHandle(CreateParams cp)
108                 {
109                         if (cp != null) {
110                                 WindowCreating = this;
111
112                                 window_handle=XplatUI.CreateWindow(cp);
113
114                                 WindowCreating = null;
115
116                                 if (window_handle != IntPtr.Zero) {
117                                         lock (window_collection) {
118                                                 window_collection[window_handle] = this;
119                                         }
120                                 }
121                         }
122
123                 }
124
125                 public void DefWndProc(ref Message m)
126                 {
127                         m.Result=XplatUI.DefWndProc(ref m);
128                 }
129
130                 public virtual void DestroyHandle()
131                 {
132                         if (window_handle != IntPtr.Zero) {
133                                 XplatUI.DestroyWindow(window_handle);
134                         }
135                 }
136
137                 public virtual void ReleaseHandle()
138                 {
139                         lock (window_collection) {
140                                 window_collection.Remove(window_handle);
141                         }
142                         window_handle=IntPtr.Zero;
143                         OnHandleChange();
144                 }
145
146                 #endregion      // Public Instance Methods
147
148                 #region Protected Instance Methods
149                 ~NativeWindow()
150                 {
151                 }
152
153                 protected virtual void OnHandleChange()
154                 {
155                 }
156
157                 protected virtual void OnThreadException(Exception e)
158                 {
159                         Application.OnThreadException(e);
160                 }
161
162                 protected virtual void WndProc(ref Message m)
163                 {
164                         DefWndProc(ref m);
165                 }
166
167                 internal static IntPtr WndProc(IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam)
168                 {
169                         Message         m = new Message();
170                         NativeWindow    window = null;
171                                         
172 #if debug
173                         Console.WriteLine("NativeWindow.cs ({0}, {1}, {2}, {3}): result {4}", hWnd, msg, wParam, lParam, m.Result);
174 #endif
175
176
177                         //try {
178                                 lock (window_collection) {
179                                         window = (NativeWindow)window_collection[hWnd];
180                                 }
181                                 m.HWnd=hWnd;
182                                 m.Msg=(int)msg;
183                                 m.WParam=wParam;
184                                 m.LParam=lParam;
185                                 m.Result=IntPtr.Zero;
186
187                                 if (window != null)
188                                         window.WndProc(ref m);
189                                 else if (WindowCreating != null) {
190                                         // we need to do this AssignHandle here instead of relying on
191                                         // Control.WndProc to do it, because subclasses can override
192                                         // WndProc, install their own WM_CREATE block, and look at
193                                         // this.Handle, and it needs to be set.  Otherwise, we end up
194                                         // recursively creating windows and emitting WM_CREATE.
195                                         window = WindowCreating;
196                                         WindowCreating = null;
197                                         if (window.window_handle == IntPtr.Zero)
198                                                 window.AssignHandle (hWnd);
199
200                                         window.WndProc (ref m);
201                                 }
202                                 else
203                                         m.Result=XplatUI.DefWndProc(ref m);
204 //            }
205 //            catch (Exception ex) {
206 //#if !ExternalExceptionHandler                         
207 //                if (window != null)
208 //                    window.OnThreadException(ex);
209 //#else
210 //                throw;
211 //#endif
212 //            }
213
214                         #if debug
215                                 Console.WriteLine("NativeWindow.cs: Message {0}, result {1}", msg, m.Result);
216                         #endif
217
218                         return m.Result;
219                 }
220                 #endregion      // Protected Instance Methods
221         }
222 }