Button painting, MouseDown/Up, LAYOUT_SUSPENDED
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / NativeWindow.cs
1 //
2 // System.Windows.Forms.NativeWindow.cs
3 //
4 // Author:
5 //   stubbed out by Paul Osman (paul.osman@sympatico.ca)
6 //   Dennis Hayes (dennish@Raytek.com)
7 //   WINELib implementation started by John Sohn (jsohn@columbus.rr.com)
8 //
9 // (C) 2002/3 Ximian, Inc
10 //
11
12 using System.Runtime.Remoting;
13 using System.Runtime.InteropServices;
14 using System.Runtime.CompilerServices;
15 using System.Collections;
16
17 namespace System.Windows.Forms {
18
19         // <summary>
20         // </summary>
21
22         public class NativeWindow : MarshalByRefObject {
23
24                 // the window's HWND
25                 private IntPtr windowHandle;
26                 static private Hashtable windowCollection = new Hashtable ();
27                 static bool registeredClass = false;
28                 
29                 // Important!  If this variable was initialized and supplied to Windows API,
30                 // we cannot *free* (GC) a delegate until all our windows destroyed, or better 
31                 // keep it forever.
32                 static Win32.WndProc wp = null;
33
34                 //
35                 //  --- Constructor
36                 //
37                 public NativeWindow () 
38                 {
39                         windowHandle = (IntPtr) 0;
40                         // Important! Do not reinitialize wp, because this will *free* (GC) 
41                         // WindowProc delegate on every Control creation, but this delegate could
42                         // already be passed to RegisterClass for the Form and others windows.
43                         // We will get problems in Get/Translate/Dispatch Message loop
44                         // (like call to invalid address)
45                         // wp = null;
46                 }
47
48                 //
49                 //  --- Public Properties
50                 //
51                 public IntPtr Handle 
52                 {
53                         get {
54                                 return windowHandle;
55                         }
56                 }
57
58                 //
59                 //  --- Public Methods
60                 //
61                 public void AssignHandle (IntPtr handle) 
62                 {
63                         if (windowHandle != (IntPtr) 0)
64                                 windowCollection.Remove (windowHandle);
65
66                         windowHandle = handle;
67                         windowCollection.Add (windowHandle, this);
68                         OnHandleChange ();
69                 }
70
71                 public virtual void CreateHandle (CreateParams cp) 
72                 {
73                         if( cp != null ) {
74                                 IntPtr createdHWnd = (IntPtr) 0;
75
76                                 if (!registeredClass) {
77                                         WNDCLASS wndClass = new WNDCLASS();
78
79                                         wndClass.style = (int) (CS_.CS_OWNDC /*|
80                                                 CS_.CS_VREDRAW |
81                                                 CS_.CS_HREDRAW*/);
82                                         wndClass.lpfnWndProc = GetWindowProc();
83                                         wndClass.cbClsExtra = 0;
84                                         wndClass.cbWndExtra = 0;
85                                         wndClass.hInstance = (IntPtr)0;
86                                         wndClass.hIcon = (IntPtr)0;
87                                         wndClass.hCursor = Win32.LoadCursor( (IntPtr)0, LC_.IDC_ARROW);
88                                         wndClass.hbrBackground = (IntPtr)((int)GetSysColorIndex.COLOR_BTNFACE + 1);
89                                         wndClass.lpszMenuName = "";
90                                         wndClass.lpszClassName = "mono_native_window";
91
92                                         if (Win32.RegisterClass(ref wndClass) != 0) {
93                                                 registeredClass = true;
94                                         } else {
95                                                 windowHandle = (IntPtr)0;
96                                                 return;
97                                         }
98                                 }
99
100                                 IntPtr lParam = IntPtr.Zero;
101                                 
102                                 if ( cp.Param != null && cp.Param is CLIENTCREATESTRUCT ) {
103                                         lParam = Marshal.AllocHGlobal ( Marshal.SizeOf ( cp.Param ) );
104                                         Marshal.StructureToPtr ( cp.Param, lParam, false );
105                                 }
106                                 
107                                 windowHandle = Win32.CreateWindowEx (
108                                         (uint) cp.ExStyle, cp.ClassName,
109                                         cp.Caption,(uint) cp.Style,
110                                         cp.X, cp.Y, cp.Width, cp.Height,
111                                         (IntPtr) cp.Parent, (IntPtr) 0,
112                                         (IntPtr) 0, lParam);
113                                         
114                                 if ( lParam != IntPtr.Zero )
115                                         Marshal.FreeHGlobal ( lParam );
116
117                                 if (windowHandle != (IntPtr) 0) {
118                                         windowCollection.Add (windowHandle, this);
119                                         if( (cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
120                                                 IntPtr curId = Win32.GetWindowLong( windowHandle, GetWindowLongFlag.GWL_ID);
121                                                 if( curId == IntPtr.Zero)
122                                                         Win32.SetWindowLong(windowHandle, GetWindowLongFlag.GWL_ID, (int)windowHandle);
123                                         }
124                                 }
125                                 //debug
126                                 else {
127                                         System.Console.WriteLine("Cannot create window {0}", Win32.FormatMessage(Win32.GetLastError()));
128                                 }
129                         }
130                 }
131
132                 public void DefWndProc (ref Message m) 
133                 {
134                         m.Result = Win32.DefWindowProcA (m.HWnd, m.Msg, 
135                                                          m.WParam, m.LParam);
136                 }
137
138                 internal void DefMDIChildProc ( ref Message m ) {
139                         m.Result = Win32.DefMDIChildProc(m.HWnd, m.Msg, m.WParam, m.LParam);
140                 }
141
142                 internal void DefFrameProc ( ref Message m , Control MdiClient) {
143                         m.Result = Win32.DefFrameProc(m.HWnd, MdiClient != null ? MdiClient.Handle : IntPtr.Zero, 
144                                                         m.Msg, m.WParam, m.LParam);
145                 }
146
147                 public virtual void DestroyHandle () 
148                 {
149                         windowCollection.Remove (windowHandle);
150                         Win32.DestroyWindow (windowHandle);
151                         windowHandle = (IntPtr)0;
152                 }
153
154                 public static NativeWindow FromHandle (IntPtr handle) 
155                 {
156                         NativeWindow window = new NativeWindow ();
157                         window.AssignHandle (handle);
158                         return window;
159                 }
160
161                 public virtual void ReleaseHandle () 
162                 {
163                         windowHandle = (IntPtr) 0;
164                         OnHandleChange ();
165                 }
166
167                 //
168                 //  --- Protected Methods
169                 //
170
171
172                 [MonoTODO]
173                 protected virtual void OnHandleChange () 
174                 {
175                         // to be overridden
176                 }
177
178                 [MonoTODO]
179                 protected virtual void OnThreadException (Exception e) 
180                 {
181                         Application.OnThreadException(e);
182                         //Console.WriteLine(e.Message + "\n" + ex.StackTrace);
183                 }
184
185                 protected virtual void WndProc (ref Message m) 
186                 {
187                         if (m.Msg == Msg.WM_CREATE)
188                                 Console.WriteLine ("NW WndProc WM_CREATE");
189                         DefWndProc (ref m);
190                 }
191
192                 //
193                 //  --- Destructor
194                 //
195                 ~NativeWindow ()
196                 {
197                         if ( windowHandle != IntPtr.Zero )
198                                 DestroyHandle ( );
199                 }
200
201                 static private IntPtr WndProc (
202                         IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) 
203                 {
204 //                      Console.WriteLine("NativeWindow.Message {0}", msg);
205                         Message message = new Message ();
206                         NativeWindow window = null;
207                         // CHECKME: This try/catch is implemented to keep Message Handlers "Exception safe"
208                         try {
209                                 // windowCollection is a collection of all the 
210                                 // NativeWindow(s) that have been created.
211                                 // Dispatch the current message to the approriate
212                                 // window.
213                                 window = (NativeWindow) windowCollection[hWnd];
214                                 message.HWnd = hWnd;
215                                 message.Msg = msg;
216                                 message.WParam = wParam;
217                                 message.LParam = lParam;
218                                 message.Result = (IntPtr) 0;
219
220 #if false
221                                 if (msg == Msg.WM_CREATE)
222                                         Console.WriteLine ("WM_CREATE (static)");
223 #endif
224                                 
225                                 if (window != null) {
226                                         if (msg == Msg.WM_CREATE) {
227                                                 // Console.WriteLine ("WM_CREATE (static != null)");
228                                         }
229                                         window.WndProc(ref message);
230                                 } else {
231                                         // Console.WriteLine ("no window, defwndproc");
232                                         // even though we are not managing the
233                                         // window let the window get the message
234                                         message.Result = Win32.DefWindowProcA (
235                                                 hWnd, msg, wParam, lParam);
236                                 }
237                         }
238                         catch( System.Exception ex) {
239                                 if( window != null)
240                                         window.OnThreadException(ex);
241                         }
242                         //Console.WriteLine("NativeWindow.Message {0}, result {1}", msg, message.Result);
243                         return message.Result;
244                 }
245                 
246                 internal static Win32.WndProc GetWindowProc() {
247                         if( wp == null){
248                                 wp = new Win32.WndProc (WndProc);
249                         }
250                         return wp;
251                 }
252         }
253 }