Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Shell.d @ 0:6dd524f61e62
add dwt win and basic java stuff
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 02 Mar 2009 14:44:16 +0100 |
parents | |
children | d46287db17ed |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6dd524f61e62 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.eclipse.swt.widgets.Shell; | |
14 | |
15 import org.eclipse.swt.SWT; | |
16 import org.eclipse.swt.SWTException; | |
17 import org.eclipse.swt.events.ShellListener; | |
18 import org.eclipse.swt.graphics.Cursor; | |
19 import org.eclipse.swt.graphics.GC; | |
20 import org.eclipse.swt.graphics.Point; | |
21 import org.eclipse.swt.graphics.Rectangle; | |
22 import org.eclipse.swt.graphics.Region; | |
23 import org.eclipse.swt.internal.win32.OS; | |
24 | |
25 import org.eclipse.swt.widgets.Composite; | |
26 import org.eclipse.swt.widgets.Decorations; | |
27 import org.eclipse.swt.widgets.Control; | |
28 import org.eclipse.swt.widgets.Menu; | |
29 import org.eclipse.swt.widgets.ToolTip; | |
30 import org.eclipse.swt.widgets.Display; | |
31 import org.eclipse.swt.widgets.TypedListener; | |
32 import org.eclipse.swt.widgets.Event; | |
33 | |
34 import java.lang.all; | |
35 | |
36 /** | |
37 * Instances of this class represent the "windows" | |
38 * which the desktop or "window manager" is managing. | |
39 * Instances that do not have a parent (that is, they | |
40 * are built using the constructor, which takes a | |
41 * <code>Display</code> as the argument) are described | |
42 * as <em>top level</em> shells. Instances that do have | |
43 * a parent are described as <em>secondary</em> or | |
44 * <em>dialog</em> shells. | |
45 * <p> | |
46 * Instances are always displayed in one of the maximized, | |
47 * minimized or normal states: | |
48 * <ul> | |
49 * <li> | |
50 * When an instance is marked as <em>maximized</em>, the | |
51 * window manager will typically resize it to fill the | |
52 * entire visible area of the display, and the instance | |
53 * is usually put in a state where it can not be resized | |
54 * (even if it has style <code>RESIZE</code>) until it is | |
55 * no longer maximized. | |
56 * </li><li> | |
57 * When an instance is in the <em>normal</em> state (neither | |
58 * maximized or minimized), its appearance is controlled by | |
59 * the style constants which were specified when it was created | |
60 * and the restrictions of the window manager (see below). | |
61 * </li><li> | |
62 * When an instance has been marked as <em>minimized</em>, | |
63 * its contents (client area) will usually not be visible, | |
64 * and depending on the window manager, it may be | |
65 * "iconified" (that is, replaced on the desktop by a small | |
66 * simplified representation of itself), relocated to a | |
67 * distinguished area of the screen, or hidden. Combinations | |
68 * of these changes are also possible. | |
69 * </li> | |
70 * </ul> | |
71 * </p><p> | |
72 * The <em>modality</em> of an instance may be specified using | |
73 * style bits. The modality style bits are used to determine | |
74 * whether input is blocked for other shells on the display. | |
75 * The <code>PRIMARY_MODAL</code> style allows an instance to block | |
76 * input to its parent. The <code>APPLICATION_MODAL</code> style | |
77 * allows an instance to block input to every other shell in the | |
78 * display. The <code>SYSTEM_MODAL</code> style allows an instance | |
79 * to block input to all shells, including shells belonging to | |
80 * different applications. | |
81 * </p><p> | |
82 * Note: The styles supported by this class are treated | |
83 * as <em>HINT</em>s, since the window manager for the | |
84 * desktop on which the instance is visible has ultimate | |
85 * control over the appearance and behavior of decorations | |
86 * and modality. For example, some window managers only | |
87 * support resizable windows and will always assume the | |
88 * RESIZE style, even if it is not set. In addition, if a | |
89 * modality style is not supported, it is "upgraded" to a | |
90 * more restrictive modality style that is supported. For | |
91 * example, if <code>PRIMARY_MODAL</code> is not supported, | |
92 * it would be upgraded to <code>APPLICATION_MODAL</code>. | |
93 * A modality style may also be "downgraded" to a less | |
94 * restrictive style. For example, most operating systems | |
95 * no longer support <code>SYSTEM_MODAL</code> because | |
96 * it can freeze up the desktop, so this is typically | |
97 * downgraded to <code>APPLICATION_MODAL</code>. | |
98 * <dl> | |
99 * <dt><b>Styles:</b></dt> | |
100 * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd> | |
101 * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd> | |
102 * <dt><b>Events:</b></dt> | |
103 * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd> | |
104 * </dl> | |
105 * Class <code>SWT</code> provides two "convenience constants" | |
106 * for the most commonly required style combinations: | |
107 * <dl> | |
108 * <dt><code>SHELL_TRIM</code></dt> | |
109 * <dd> | |
110 * the result of combining the constants which are required | |
111 * to produce a typical application top level shell: (that | |
112 * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>) | |
113 * </dd> | |
114 * <dt><code>DIALOG_TRIM</code></dt> | |
115 * <dd> | |
116 * the result of combining the constants which are required | |
117 * to produce a typical application dialog shell: (that | |
118 * is, <code>TITLE | CLOSE | BORDER</code>) | |
119 * </dd> | |
120 * </dl> | |
121 * </p> | |
122 * <p> | |
123 * Note: Only one of the styles APPLICATION_MODAL, MODELESS, | |
124 * PRIMARY_MODAL and SYSTEM_MODAL may be specified. | |
125 * </p><p> | |
126 * IMPORTANT: This class is not intended to be subclassed. | |
127 * </p> | |
128 * | |
129 * @see Decorations | |
130 * @see SWT | |
131 * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a> | |
132 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> | |
133 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
134 */ | |
135 public class Shell : Decorations { | |
136 | |
137 alias Decorations.setBounds setBounds; | |
138 alias Decorations.setParent setParent; | |
139 alias Decorations.setToolTipText setToolTipText; | |
140 | |
141 Menu activeMenu; | |
142 ToolTip [] toolTips; | |
143 HIMC hIMC; | |
144 HWND hwndMDIClient_; | |
145 TCHAR* lpstrTip; | |
146 HANDLE toolTipHandle_; | |
147 HANDLE balloonTipHandle_; | |
148 int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT; | |
149 HBRUSH [] brushes; | |
150 bool showWithParent, fullScreen, wasMaximized; | |
151 String toolTitle, balloonTitle; | |
152 HICON toolIcon; | |
153 HICON balloonIcon; | |
154 WNDPROC windowProc_; | |
155 Control lastActive; | |
156 static if( OS.IsWinCE ){ | |
157 SHACTIVATEINFO psai; | |
158 } | |
159 static /+const+/ WNDPROC ToolTipProc; | |
160 static /+const+/ WNDPROC DialogProc; | |
161 static if( OS.IsWinCE ){ | |
162 static const TCHAR[] DialogClass = "Dialog\0"w; | |
163 } | |
164 else{ | |
165 static const TCHAR[] DialogClass = "#32770\0"w; | |
166 } | |
167 const static int [] SYSTEM_COLORS = [ | |
168 OS.COLOR_BTNFACE, | |
169 OS.COLOR_WINDOW, | |
170 OS.COLOR_BTNTEXT, | |
171 OS.COLOR_WINDOWTEXT, | |
172 OS.COLOR_HIGHLIGHT, | |
173 OS.COLOR_SCROLLBAR, | |
174 ]; | |
175 final static int BRUSHES_SIZE = 32; | |
176 | |
177 private static bool static_this_completed = false; | |
178 private static void static_this() { | |
179 if( static_this_completed ){ | |
180 return; | |
181 } | |
182 synchronized { | |
183 if( static_this_completed ){ | |
184 return; | |
185 } | |
186 WNDCLASS lpWndClass; | |
187 OS.GetClassInfo (null, DialogClass.ptr, &lpWndClass); | |
188 DialogProc = lpWndClass.lpfnWndProc; | |
189 static_this_completed = true; | |
190 } | |
191 } | |
192 | |
193 /** | |
194 * Constructs a new instance of this class. This is equivalent | |
195 * to calling <code>Shell((Display) null)</code>. | |
196 * | |
197 * @exception SWTException <ul> | |
198 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
199 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
200 * </ul> | |
201 */ | |
202 public this () { | |
203 this (cast(Display) null); | |
204 } | |
205 | |
206 /** | |
207 * Constructs a new instance of this class given only the style | |
208 * value describing its behavior and appearance. This is equivalent | |
209 * to calling <code>Shell((Display) null, style)</code>. | |
210 * <p> | |
211 * The style value is either one of the style constants defined in | |
212 * class <code>SWT</code> which is applicable to instances of this | |
213 * class, or must be built by <em>bitwise OR</em>'ing together | |
214 * (that is, using the <code>int</code> "|" operator) two or more | |
215 * of those <code>SWT</code> style constants. The class description | |
216 * lists the style constants that are applicable to the class. | |
217 * Style bits are also inherited from superclasses. | |
218 * </p> | |
219 * | |
220 * @param style the style of control to construct | |
221 * | |
222 * @exception SWTException <ul> | |
223 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
224 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
225 * </ul> | |
226 * | |
227 * @see SWT#BORDER | |
228 * @see SWT#CLOSE | |
229 * @see SWT#MIN | |
230 * @see SWT#MAX | |
231 * @see SWT#RESIZE | |
232 * @see SWT#TITLE | |
233 * @see SWT#NO_TRIM | |
234 * @see SWT#SHELL_TRIM | |
235 * @see SWT#DIALOG_TRIM | |
236 * @see SWT#MODELESS | |
237 * @see SWT#PRIMARY_MODAL | |
238 * @see SWT#APPLICATION_MODAL | |
239 * @see SWT#SYSTEM_MODAL | |
240 */ | |
241 public this (int style) { | |
242 this (cast(Display) null, style); | |
243 } | |
244 | |
245 /** | |
246 * Constructs a new instance of this class given only the display | |
247 * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>. | |
248 * <p> | |
249 * Note: Currently, null can be passed in for the display argument. | |
250 * This has the effect of creating the shell on the currently active | |
251 * display if there is one. If there is no current display, the | |
252 * shell is created on a "default" display. <b>Passing in null as | |
253 * the display argument is not considered to be good coding style, | |
254 * and may not be supported in a future release of SWT.</b> | |
255 * </p> | |
256 * | |
257 * @param display the display to create the shell on | |
258 * | |
259 * @exception SWTException <ul> | |
260 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
261 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
262 * </ul> | |
263 */ | |
264 public this (Display display) { | |
265 this (display, OS.IsWinCE ? SWT.NONE : SWT.SHELL_TRIM); | |
266 } | |
267 | |
268 /** | |
269 * Constructs a new instance of this class given the display | |
270 * to create it on and a style value describing its behavior | |
271 * and appearance. | |
272 * <p> | |
273 * The style value is either one of the style constants defined in | |
274 * class <code>SWT</code> which is applicable to instances of this | |
275 * class, or must be built by <em>bitwise OR</em>'ing together | |
276 * (that is, using the <code>int</code> "|" operator) two or more | |
277 * of those <code>SWT</code> style constants. The class description | |
278 * lists the style constants that are applicable to the class. | |
279 * Style bits are also inherited from superclasses. | |
280 * </p><p> | |
281 * Note: Currently, null can be passed in for the display argument. | |
282 * This has the effect of creating the shell on the currently active | |
283 * display if there is one. If there is no current display, the | |
284 * shell is created on a "default" display. <b>Passing in null as | |
285 * the display argument is not considered to be good coding style, | |
286 * and may not be supported in a future release of SWT.</b> | |
287 * </p> | |
288 * | |
289 * @param display the display to create the shell on | |
290 * @param style the style of control to construct | |
291 * | |
292 * @exception SWTException <ul> | |
293 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
294 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
295 * </ul> | |
296 * | |
297 * @see SWT#BORDER | |
298 * @see SWT#CLOSE | |
299 * @see SWT#MIN | |
300 * @see SWT#MAX | |
301 * @see SWT#RESIZE | |
302 * @see SWT#TITLE | |
303 * @see SWT#NO_TRIM | |
304 * @see SWT#SHELL_TRIM | |
305 * @see SWT#DIALOG_TRIM | |
306 * @see SWT#MODELESS | |
307 * @see SWT#PRIMARY_MODAL | |
308 * @see SWT#APPLICATION_MODAL | |
309 * @see SWT#SYSTEM_MODAL | |
310 */ | |
311 public this (Display display, int style) { | |
312 this (display, null, style, null, false); | |
313 } | |
314 | |
315 this (Display display, Shell parent, int style, HWND handle, bool embedded) { | |
316 static_this(); | |
317 super (); | |
318 checkSubclass (); | |
319 if (display is null) display = Display.getCurrent (); | |
320 if (display is null) display = Display.getDefault (); | |
321 if (!display.isValidThread ()) { | |
322 error (SWT.ERROR_THREAD_INVALID_ACCESS); | |
323 } | |
324 if (parent !is null && parent.isDisposed ()) { | |
325 error (SWT.ERROR_INVALID_ARGUMENT); | |
326 } | |
327 this.style = checkStyle (style); | |
328 this.parent = parent; | |
329 this.display = display; | |
330 this.handle = handle; | |
331 if (handle !is null && !embedded) { | |
332 state |= FOREIGN_HANDLE; | |
333 } | |
334 createWidget (); | |
335 } | |
336 | |
337 /** | |
338 * Constructs a new instance of this class given only its | |
339 * parent. It is created with style <code>SWT.DIALOG_TRIM</code>. | |
340 * <p> | |
341 * Note: Currently, null can be passed in for the parent. | |
342 * This has the effect of creating the shell on the currently active | |
343 * display if there is one. If there is no current display, the | |
344 * shell is created on a "default" display. <b>Passing in null as | |
345 * the parent is not considered to be good coding style, | |
346 * and may not be supported in a future release of SWT.</b> | |
347 * </p> | |
348 * | |
349 * @param parent a shell which will be the parent of the new instance | |
350 * | |
351 * @exception IllegalArgumentException <ul> | |
352 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li> | |
353 * </ul> | |
354 * @exception SWTException <ul> | |
355 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
356 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
357 * </ul> | |
358 */ | |
359 public this (Shell parent) { | |
360 this (parent, OS.IsWinCE ? SWT.NONE : SWT.DIALOG_TRIM); | |
361 } | |
362 | |
363 /** | |
364 * Constructs a new instance of this class given its parent | |
365 * and a style value describing its behavior and appearance. | |
366 * <p> | |
367 * The style value is either one of the style constants defined in | |
368 * class <code>SWT</code> which is applicable to instances of this | |
369 * class, or must be built by <em>bitwise OR</em>'ing together | |
370 * (that is, using the <code>int</code> "|" operator) two or more | |
371 * of those <code>SWT</code> style constants. The class description | |
372 * lists the style constants that are applicable to the class. | |
373 * Style bits are also inherited from superclasses. | |
374 * </p><p> | |
375 * Note: Currently, null can be passed in for the parent. | |
376 * This has the effect of creating the shell on the currently active | |
377 * display if there is one. If there is no current display, the | |
378 * shell is created on a "default" display. <b>Passing in null as | |
379 * the parent is not considered to be good coding style, | |
380 * and may not be supported in a future release of SWT.</b> | |
381 * </p> | |
382 * | |
383 * @param parent a shell which will be the parent of the new instance | |
384 * @param style the style of control to construct | |
385 * | |
386 * @exception IllegalArgumentException <ul> | |
387 * <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li> | |
388 * </ul> | |
389 * @exception SWTException <ul> | |
390 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
391 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
392 * </ul> | |
393 * | |
394 * @see SWT#BORDER | |
395 * @see SWT#CLOSE | |
396 * @see SWT#MIN | |
397 * @see SWT#MAX | |
398 * @see SWT#RESIZE | |
399 * @see SWT#TITLE | |
400 * @see SWT#NO_TRIM | |
401 * @see SWT#SHELL_TRIM | |
402 * @see SWT#DIALOG_TRIM | |
403 * @see SWT#ON_TOP | |
404 * @see SWT#TOOL | |
405 * @see SWT#MODELESS | |
406 * @see SWT#PRIMARY_MODAL | |
407 * @see SWT#APPLICATION_MODAL | |
408 * @see SWT#SYSTEM_MODAL | |
409 */ | |
410 public this (Shell parent, int style) { | |
411 this (parent !is null ? parent.display : null, parent, style, null, false); | |
412 } | |
413 | |
414 /** | |
415 * Invokes platform specific functionality to allocate a new shell | |
416 * that is embedded. | |
417 * <p> | |
418 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
419 * API for <code>Shell</code>. It is marked public only so that it | |
420 * can be shared within the packages provided by SWT. It is not | |
421 * available on all platforms, and should never be called from | |
422 * application code. | |
423 * </p> | |
424 * | |
425 * @param display the display for the shell | |
426 * @param handle the handle for the shell | |
427 * @return a new shell object containing the specified display and handle | |
428 */ | |
429 public static Shell win32_new (Display display, HWND handle) { | |
430 return new Shell (display, null, SWT.NO_TRIM, handle, true); | |
431 } | |
432 | |
433 /** | |
434 * Invokes platform specific functionality to allocate a new shell | |
435 * that is not embedded. | |
436 * <p> | |
437 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public | |
438 * API for <code>Shell</code>. It is marked public only so that it | |
439 * can be shared within the packages provided by SWT. It is not | |
440 * available on all platforms, and should never be called from | |
441 * application code. | |
442 * </p> | |
443 * | |
444 * @param display the display for the shell | |
445 * @param handle the handle for the shell | |
446 * @return a new shell object containing the specified display and handle | |
447 * | |
448 * @since 3.3 | |
449 */ | |
450 public static Shell internal_new (Display display, HWND handle) { | |
451 return new Shell (display, null, SWT.NO_TRIM, handle, false); | |
452 } | |
453 | |
454 static int checkStyle (int style) { | |
455 style = Decorations.checkStyle (style); | |
456 style &= ~SWT.TRANSPARENT; | |
457 int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL; | |
458 int bits = style & ~mask; | |
459 if ((style & SWT.SYSTEM_MODAL) !is 0) return bits | SWT.SYSTEM_MODAL; | |
460 if ((style & SWT.APPLICATION_MODAL) !is 0) return bits | SWT.APPLICATION_MODAL; | |
461 if ((style & SWT.PRIMARY_MODAL) !is 0) return bits | SWT.PRIMARY_MODAL; | |
462 return bits; | |
463 } | |
464 | |
465 /** | |
466 * Adds the listener to the collection of listeners who will | |
467 * be notified when operations are performed on the receiver, | |
468 * by sending the listener one of the messages defined in the | |
469 * <code>ShellListener</code> interface. | |
470 * | |
471 * @param listener the listener which should be notified | |
472 * | |
473 * @exception IllegalArgumentException <ul> | |
474 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
475 * </ul> | |
476 * @exception SWTException <ul> | |
477 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
478 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
479 * </ul> | |
480 * | |
481 * @see ShellListener | |
482 * @see #removeShellListener | |
483 */ | |
484 public void addShellListener (ShellListener listener) { | |
485 checkWidget (); | |
486 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
487 TypedListener typedListener = new TypedListener (listener); | |
488 addListener (SWT.Close,typedListener); | |
489 addListener (SWT.Iconify,typedListener); | |
490 addListener (SWT.Deiconify,typedListener); | |
491 addListener (SWT.Activate, typedListener); | |
492 addListener (SWT.Deactivate, typedListener); | |
493 } | |
494 | |
495 HANDLE balloonTipHandle () { | |
496 if (balloonTipHandle_ is null) createBalloonTipHandle (); | |
497 return balloonTipHandle_; | |
498 } | |
499 | |
500 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
501 if (handle is null) return 0; | |
502 if (hwnd is toolTipHandle_ || hwnd is balloonTipHandle_) { | |
503 return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam); | |
504 } | |
505 if (hwndMDIClient_ !is null) { | |
506 return OS.DefFrameProc (hwnd, hwndMDIClient_, msg, wParam, lParam); | |
507 } | |
508 if (windowProc_ !is null) { | |
509 return OS.CallWindowProc (windowProc_, hwnd, msg, wParam, lParam); | |
510 } | |
511 if ((style & SWT.TOOL) !is 0) { | |
512 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; | |
513 if ((style & trim) is 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam); | |
514 } | |
515 if (parent !is null) { | |
516 switch (msg) { | |
517 case OS.WM_KILLFOCUS: | |
518 case OS.WM_SETFOCUS: | |
519 return OS.DefWindowProc (hwnd, msg, wParam, lParam); | |
520 default: | |
521 } | |
522 return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam); | |
523 } | |
524 return OS.DefWindowProc (hwnd, msg, wParam, lParam); | |
525 } | |
526 | |
527 /** | |
528 * Requests that the window manager close the receiver in | |
529 * the same way it would be closed when the user clicks on | |
530 * the "close box" or performs some other platform specific | |
531 * key or mouse combination that indicates the window | |
532 * should be removed. | |
533 * | |
534 * @exception SWTException <ul> | |
535 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
536 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
537 * </ul> | |
538 * | |
539 * @see SWT#Close | |
540 * @see #dispose | |
541 */ | |
542 public void close () { | |
543 checkWidget (); | |
544 closeWidget (); | |
545 } | |
546 | |
547 void createBalloonTipHandle () { | |
548 balloonTipHandle_ = OS.CreateWindowEx ( | |
549 0, | |
550 OS.TOOLTIPS_CLASS.ptr, | |
551 null, | |
552 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON, | |
553 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, | |
554 handle, | |
555 null, | |
556 OS.GetModuleHandle (null), | |
557 null); | |
558 if (balloonTipHandle_ is null) error (SWT.ERROR_NO_HANDLES); | |
559 if (ToolTipProc is null) { | |
560 ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC); | |
561 } | |
562 /* | |
563 * Feature in Windows. Despite the fact that the | |
564 * tool tip text contains \r\n, the tooltip will | |
565 * not honour the new line unless TTM_SETMAXTIPWIDTH | |
566 * is set. The fix is to set TTM_SETMAXTIPWIDTH to | |
567 * a large value. | |
568 */ | |
569 OS.SendMessage (balloonTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); | |
570 display.addControl (balloonTipHandle_, this); | |
571 OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, display.windowProc); | |
572 } | |
573 | |
574 override void createHandle () { | |
575 bool embedded = handle !is null && (state & FOREIGN_HANDLE) is 0; | |
576 | |
577 /* | |
578 * On Windows 98 and NT, setting a window to be the | |
579 * top most window using HWND_TOPMOST can result in a | |
580 * parent dialog shell being moved behind its parent | |
581 * if the dialog has a sibling that is currently on top | |
582 * This only occurs using SetWindowPos (), not when the | |
583 * handle is created. | |
584 */ | |
585 /* | |
586 * The following code is intentionally commented. | |
587 */ | |
588 // if ((style & SWT.ON_TOP) !is 0) display.lockActiveWindow = true; | |
589 if (handle is null || embedded) { | |
590 super.createHandle (); | |
591 } else { | |
592 state |= CANVAS; | |
593 if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) is 0) { | |
594 state |= THEME_BACKGROUND; | |
595 } | |
596 windowProc_ = cast(WNDPROC) OS.GetWindowLong (handle, OS.GWL_WNDPROC); | |
597 } | |
598 | |
599 /* | |
600 * The following code is intentionally commented. | |
601 */ | |
602 // if ((style & SWT.ON_TOP) !is 0) display.lockActiveWindow = false; | |
603 | |
604 if (!embedded) { | |
605 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
606 bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION); | |
607 static if (!OS.IsWinCE) bits |= OS.WS_POPUP; | |
608 if ((style & SWT.TITLE) !is 0) bits |= OS.WS_CAPTION; | |
609 if ((style & SWT.NO_TRIM) is 0) { | |
610 if ((style & (SWT.BORDER | SWT.RESIZE)) is 0) bits |= OS.WS_BORDER; | |
611 } | |
612 /* | |
613 * Bug in Windows. When the WS_CAPTION bits are cleared using | |
614 * SetWindowLong(), Windows does not resize the client area of | |
615 * the window to get rid of the caption until the first resize. | |
616 * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force | |
617 * the frame to be redrawn and resized. | |
618 */ | |
619 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); | |
620 int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE; | |
621 SetWindowPos (handle, null, 0, 0, 0, 0, flags); | |
622 static if (OS.IsWinCE) _setMaximized (true); | |
623 static if (OS.IsPPC) { | |
624 psai = new SHACTIVATEINFO (); | |
625 psai.cbSize = SHACTIVATEINFO.sizeof; | |
626 } | |
627 } | |
628 if (OS.IsDBLocale) { | |
629 hIMC = OS.ImmCreateContext (); | |
630 if (hIMC !is null) OS.ImmAssociateContext (handle, hIMC); | |
631 } | |
632 } | |
633 | |
634 void createToolTip (ToolTip toolTip) { | |
635 int id = 0; | |
636 if (toolTips is null) toolTips = new ToolTip [4]; | |
637 while (id < toolTips.length && toolTips [id] !is null) id++; | |
638 if (id is toolTips.length) { | |
639 ToolTip [] newToolTips = new ToolTip [toolTips.length + 4]; | |
640 System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length); | |
641 toolTips = newToolTips; | |
642 } | |
643 toolTips [id] = toolTip; | |
644 toolTip.id = id + Display.ID_START; | |
645 static if (OS.IsWinCE) return; | |
646 TOOLINFO lpti; | |
647 lpti.cbSize = OS.TOOLINFO_sizeof; | |
648 lpti.hwnd = handle; | |
649 lpti.uId = toolTip.id; | |
650 lpti.uFlags = OS.TTF_TRACK; | |
651 lpti.lpszText = OS.LPSTR_TEXTCALLBACK; | |
652 OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, &lpti); | |
653 } | |
654 | |
655 void createToolTipHandle () { | |
656 toolTipHandle_ = OS.CreateWindowEx ( | |
657 0, | |
658 OS.TOOLTIPS_CLASS.ptr, | |
659 null, | |
660 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX, | |
661 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, | |
662 handle, | |
663 null, | |
664 OS.GetModuleHandle (null), | |
665 null); | |
666 if (toolTipHandle_ is null) error (SWT.ERROR_NO_HANDLES); | |
667 if (ToolTipProc is null) { | |
668 ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC); | |
669 } | |
670 /* | |
671 * Feature in Windows. Despite the fact that the | |
672 * tool tip text contains \r\n, the tooltip will | |
673 * not honour the new line unless TTM_SETMAXTIPWIDTH | |
674 * is set. The fix is to set TTM_SETMAXTIPWIDTH to | |
675 * a large value. | |
676 */ | |
677 OS.SendMessage (toolTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); | |
678 display.addControl (toolTipHandle_, this); | |
679 OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, display.windowProc); | |
680 } | |
681 | |
682 override void deregister () { | |
683 super.deregister (); | |
684 if (toolTipHandle_ !is null) display.removeControl (toolTipHandle_); | |
685 if (balloonTipHandle_ !is null) display.removeControl (balloonTipHandle_); | |
686 } | |
687 | |
688 void destroyToolTip (ToolTip toolTip) { | |
689 if (toolTips is null) return; | |
690 toolTips [toolTip.id - Display.ID_START] = null; | |
691 static if (OS.IsWinCE) return; | |
692 if (balloonTipHandle_ !is null) { | |
693 TOOLINFO lpti; | |
694 lpti.cbSize = OS.TOOLINFO_sizeof; | |
695 lpti.uId = toolTip.id; | |
696 lpti.hwnd = handle; | |
697 OS.SendMessage (balloonTipHandle_, OS.TTM_DELTOOL, 0, &lpti); | |
698 } | |
699 toolTip.id = -1; | |
700 } | |
701 | |
702 override void destroyWidget () { | |
703 fixActiveShell (); | |
704 super.destroyWidget (); | |
705 } | |
706 | |
707 override public void dispose () { | |
708 /* | |
709 * This code is intentionally commented. On some | |
710 * platforms, the owner window is repainted right | |
711 * away when a dialog window exits. This behavior | |
712 * is currently unspecified. | |
713 */ | |
714 // /* | |
715 // * Note: It is valid to attempt to dispose a widget | |
716 // * more than once. If this happens, fail silently. | |
717 // */ | |
718 // if (!isValidWidget ()) return; | |
719 // if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); | |
720 // Display oldDisplay = display; | |
721 super.dispose (); | |
722 // widget is disposed at this point | |
723 // if (oldDisplay !is null) oldDisplay.update (); | |
724 } | |
725 | |
726 override void enableWidget (bool enabled) { | |
727 if (enabled) { | |
728 state &= ~DISABLED; | |
729 } else { | |
730 state |= DISABLED; | |
731 } | |
732 if (Display.TrimEnabled) { | |
733 if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled); | |
734 } else { | |
735 OS.EnableWindow (handle, enabled); | |
736 } | |
737 } | |
738 | |
739 override HBRUSH findBrush (int value, int lbStyle) { | |
740 if (lbStyle is OS.BS_SOLID) { | |
741 for (int i=0; i<SYSTEM_COLORS.length; i++) { | |
742 if (value is OS.GetSysColor (SYSTEM_COLORS [i])) { | |
743 return OS.GetSysColorBrush (SYSTEM_COLORS [i]); | |
744 } | |
745 } | |
746 } | |
747 if (brushes is null) brushes = new HBRUSH [BRUSHES_SIZE]; | |
748 LOGBRUSH logBrush; | |
749 for (int i=0; i<brushes.length; i++) { | |
750 HBRUSH hBrush = brushes [i]; | |
751 if (hBrush is null) break; | |
752 OS.GetObject (hBrush, LOGBRUSH.sizeof, &logBrush); | |
753 switch (logBrush.lbStyle) { | |
754 case OS.BS_SOLID: | |
755 if (lbStyle is OS.BS_SOLID) { | |
756 if (logBrush.lbColor is value) return hBrush; | |
757 } | |
758 break; | |
759 case OS.BS_PATTERN: | |
760 if (lbStyle is OS.BS_PATTERN) { | |
761 if (logBrush.lbHatch is value) return hBrush; | |
762 } | |
763 break; | |
764 default: | |
765 } | |
766 } | |
767 int length_ = brushes.length; | |
768 HBRUSH hBrush = brushes [--length_]; | |
769 if (hBrush !is null) OS.DeleteObject (hBrush); | |
770 System.arraycopy (brushes, 0, brushes, 1, length_); | |
771 switch (lbStyle) { | |
772 case OS.BS_SOLID: | |
773 hBrush = OS.CreateSolidBrush (value); | |
774 break; | |
775 case OS.BS_PATTERN: | |
776 hBrush = OS.CreatePatternBrush ( cast(HBITMAP) value); | |
777 break; | |
778 default: | |
779 } | |
780 return brushes [0] = hBrush; | |
781 } | |
782 | |
783 override Control findBackgroundControl () { | |
784 return background !is -1 || backgroundImage !is null ? this : null; | |
785 } | |
786 | |
787 override Cursor findCursor () { | |
788 return cursor; | |
789 } | |
790 | |
791 override Control findThemeControl () { | |
792 return null; | |
793 } | |
794 | |
795 ToolTip findToolTip (int id) { | |
796 if (toolTips is null) return null; | |
797 id = id - Display.ID_START; | |
798 return 0 <= id && id < toolTips.length ? toolTips [id] : null; | |
799 } | |
800 | |
801 void fixActiveShell () { | |
802 /* | |
803 * Feature in Windows. When the active shell is disposed | |
804 * or hidden, Windows normally makes the parent shell active | |
805 * and assigns focus. This does not happen when the parent | |
806 * shell is disabled. Instead, Windows assigns focus to the | |
807 * next shell on the desktop (possibly a shell in another | |
808 * application). The fix is to activate the disabled parent | |
809 * shell before disposing or hiding the active shell. | |
810 */ | |
811 auto hwndParent = OS.GetParent (handle); | |
812 if (hwndParent !is null && handle is OS.GetActiveWindow ()) { | |
813 if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) { | |
814 OS.SetActiveWindow (hwndParent); | |
815 } | |
816 } | |
817 } | |
818 | |
819 void fixShell (Shell newShell, Control control) { | |
820 if (this is newShell) return; | |
821 if (control is lastActive) setActiveControl (null); | |
822 String toolTipText = control.toolTipText_; | |
823 if (toolTipText !is null) { | |
824 control.setToolTipText (this, null); | |
825 control.setToolTipText (newShell, toolTipText); | |
826 } | |
827 } | |
828 | |
829 void fixToolTip () { | |
830 /* | |
831 * Bug in Windows. On XP, when a tooltip is | |
832 * hidden due to a time out or mouse press, | |
833 * the tooltip remains active although no | |
834 * longer visible and won't show again until | |
835 * another tooltip becomes active. If there | |
836 * is only one tooltip in the window, it will | |
837 * never show again. The fix is to remove the | |
838 * current tooltip and add it again every time | |
839 * the mouse leaves the control. | |
840 */ | |
841 if (OS.COMCTL32_MAJOR >= 6) { | |
842 if (toolTipHandle_ is null) return; | |
843 TOOLINFO lpti; | |
844 lpti.cbSize = OS.TOOLINFO_sizeof; | |
845 if (OS.SendMessage (toolTipHandle_, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) { | |
846 if ((lpti.uFlags & OS.TTF_IDISHWND) !is 0) { | |
847 OS.SendMessage (toolTipHandle_, OS.TTM_DELTOOL, 0, &lpti); | |
848 OS.SendMessage (toolTipHandle_, OS.TTM_ADDTOOL, 0, &lpti); | |
849 } | |
850 } | |
851 } | |
852 } | |
853 | |
854 /** | |
855 * If the receiver is visible, moves it to the top of the | |
856 * drawing order for the display on which it was created | |
857 * (so that all other shells on that display, which are not | |
858 * the receiver's children will be drawn behind it) and forces | |
859 * the window manager to make the shell active. | |
860 * | |
861 * @exception SWTException <ul> | |
862 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
863 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
864 * </ul> | |
865 * | |
866 * @since 2.0 | |
867 * @see Control#moveAbove | |
868 * @see Control#setFocus | |
869 * @see Control#setVisible | |
870 * @see Display#getActiveShell | |
871 * @see Decorations#setDefaultButton(Button) | |
872 * @see Shell#open | |
873 * @see Shell#setActive | |
874 */ | |
875 public void forceActive () { | |
876 checkWidget (); | |
877 if(!isVisible()) return; | |
878 OS.SetForegroundWindow (handle); | |
879 } | |
880 | |
881 override void forceResize () { | |
882 /* Do nothing */ | |
883 } | |
884 | |
885 /** | |
886 * Returns the receiver's alpha value. The alpha value | |
887 * is between 0 (transparent) and 255 (opaque). | |
888 * | |
889 * @return the alpha value | |
890 * | |
891 * @exception SWTException <ul> | |
892 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
893 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
894 * </ul> | |
895 * | |
896 * @since 3.4 | |
897 */ | |
898 public int getAlpha () { | |
899 checkWidget (); | |
900 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { | |
901 ubyte [1] pbAlpha; | |
902 if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha.ptr, null)) { | |
903 return pbAlpha [0] & 0xFF; | |
904 } | |
905 } | |
906 return 0xFF; | |
907 } | |
908 | |
909 override public Rectangle getBounds () { | |
910 checkWidget (); | |
911 static if (!OS.IsWinCE) { | |
912 if (OS.IsIconic (handle)) return super.getBounds (); | |
913 } | |
914 RECT rect; | |
915 OS.GetWindowRect (handle, &rect); | |
916 int width = rect.right - rect.left; | |
917 int height = rect.bottom - rect.top; | |
918 return new Rectangle (rect.left, rect.top, width, height); | |
919 } | |
920 | |
921 ToolTip getCurrentToolTip () { | |
922 if (toolTipHandle_ !is null) { | |
923 ToolTip tip = getCurrentToolTip (toolTipHandle_); | |
924 if (tip !is null) return tip; | |
925 } | |
926 if (balloonTipHandle_ !is null) { | |
927 ToolTip tip = getCurrentToolTip (balloonTipHandle_); | |
928 if (tip !is null) return tip; | |
929 } | |
930 return null; | |
931 } | |
932 | |
933 ToolTip getCurrentToolTip (HWND hwndToolTip) { | |
934 if (hwndToolTip is null) return null; | |
935 if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) { | |
936 TOOLINFO lpti; | |
937 lpti.cbSize = OS.TOOLINFO_sizeof; | |
938 if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, &lpti) !is 0) { | |
939 if ((lpti.uFlags & OS.TTF_IDISHWND) is 0) return findToolTip (lpti.uId); | |
940 } | |
941 } | |
942 return null; | |
943 } | |
944 | |
945 override public bool getEnabled () { | |
946 checkWidget (); | |
947 return (state & DISABLED) is 0; | |
948 } | |
949 | |
950 /** | |
951 * Returns <code>true</code> if the receiver is currently | |
952 * in fullscreen state, and false otherwise. | |
953 * <p> | |
954 * | |
955 * @return the fullscreen state | |
956 * | |
957 * @exception SWTException <ul> | |
958 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
959 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
960 * </ul> | |
961 * | |
962 * @since 3.4 | |
963 */ | |
964 public bool getFullScreen () { | |
965 checkWidget(); | |
966 return fullScreen; | |
967 } | |
968 | |
969 /** | |
970 * Returns the receiver's input method editor mode. This | |
971 * will be the result of bitwise OR'ing together one or | |
972 * more of the following constants defined in class | |
973 * <code>SWT</code>: | |
974 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>, | |
975 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>. | |
976 * | |
977 * @return the IME mode | |
978 * | |
979 * @exception SWTException <ul> | |
980 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
981 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
982 * </ul> | |
983 * | |
984 * @see SWT | |
985 */ | |
986 public int getImeInputMode () { | |
987 checkWidget (); | |
988 if (!OS.IsDBLocale) return 0; | |
989 auto hIMC = OS.ImmGetContext (handle); | |
990 uint lpfdwConversion, lpfdwSentence; | |
991 bool open = cast(bool) OS.ImmGetOpenStatus (hIMC); | |
992 if (open) open = cast(bool) OS.ImmGetConversionStatus (hIMC, &lpfdwConversion, &lpfdwSentence); | |
993 OS.ImmReleaseContext (handle, hIMC); | |
994 if (!open) return SWT.NONE; | |
995 int result = 0; | |
996 if ((lpfdwConversion & OS.IME_CMODE_ROMAN) !is 0) result |= SWT.ROMAN; | |
997 if ((lpfdwConversion & OS.IME_CMODE_FULLSHAPE) !is 0) result |= SWT.DBCS; | |
998 if ((lpfdwConversion & OS.IME_CMODE_KATAKANA) !is 0) return result | SWT.PHONETIC; | |
999 if ((lpfdwConversion & OS.IME_CMODE_NATIVE) !is 0) return result | SWT.NATIVE; | |
1000 return result | SWT.ALPHA; | |
1001 } | |
1002 | |
1003 override public Point getLocation () { | |
1004 checkWidget (); | |
1005 static if (!OS.IsWinCE) { | |
1006 if (OS.IsIconic (handle)) { | |
1007 return super.getLocation (); | |
1008 } | |
1009 } | |
1010 RECT rect; | |
1011 OS.GetWindowRect (handle, &rect); | |
1012 return new Point (rect.left, rect.top); | |
1013 } | |
1014 | |
1015 public bool getMaximized () { | |
1016 checkWidget (); | |
1017 return !fullScreen && super.getMaximized (); | |
1018 } | |
1019 | |
1020 /** | |
1021 * Returns a point describing the minimum receiver's size. The | |
1022 * x coordinate of the result is the minimum width of the receiver. | |
1023 * The y coordinate of the result is the minimum height of the | |
1024 * receiver. | |
1025 * | |
1026 * @return the receiver's size | |
1027 * | |
1028 * @exception SWTException <ul> | |
1029 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1030 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1031 * </ul> | |
1032 * | |
1033 * @since 3.1 | |
1034 */ | |
1035 public Point getMinimumSize () { | |
1036 checkWidget (); | |
1037 int width = Math.max (0, minWidth); | |
1038 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; | |
1039 if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) { | |
1040 width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK)); | |
1041 } | |
1042 int height = Math.max (0, minHeight); | |
1043 if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) { | |
1044 if ((style & SWT.RESIZE) !is 0) { | |
1045 height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK)); | |
1046 } else { | |
1047 RECT rect; | |
1048 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
1049 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
1050 OS.AdjustWindowRectEx (&rect, bits1, false, bits2); | |
1051 height = Math.max (height, rect.bottom - rect.top); | |
1052 } | |
1053 } | |
1054 return new Point (width, height); | |
1055 } | |
1056 | |
1057 /** | |
1058 * Returns the region that defines the shape of the shell, | |
1059 * or null if the shell has the default shape. | |
1060 * | |
1061 * @return the region that defines the shape of the shell (or null) | |
1062 * | |
1063 * @exception SWTException <ul> | |
1064 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1065 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1066 * </ul> | |
1067 * | |
1068 * @since 3.0 | |
1069 * | |
1070 */ | |
1071 public Region getRegion () { | |
1072 /* This method is needed for the @since 3.0 Javadoc */ | |
1073 checkWidget (); | |
1074 return region; | |
1075 } | |
1076 | |
1077 override public Shell getShell () { | |
1078 checkWidget (); | |
1079 return this; | |
1080 } | |
1081 | |
1082 override public Point getSize () { | |
1083 checkWidget (); | |
1084 static if (!OS.IsWinCE) { | |
1085 if (OS.IsIconic (handle)) return super.getSize (); | |
1086 } | |
1087 RECT rect; | |
1088 OS.GetWindowRect (handle, &rect); | |
1089 int width = rect.right - rect.left; | |
1090 int height = rect.bottom - rect.top; | |
1091 return new Point (width, height); | |
1092 } | |
1093 | |
1094 /** | |
1095 * Returns an array containing all shells which are | |
1096 * descendants of the receiver. | |
1097 * <p> | |
1098 * @return the dialog shells | |
1099 * | |
1100 * @exception SWTException <ul> | |
1101 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1102 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1103 * </ul> | |
1104 */ | |
1105 public Shell [] getShells () { | |
1106 checkWidget (); | |
1107 int count = 0; | |
1108 Shell [] shells = display.getShells (); | |
1109 for (int i=0; i<shells.length; i++) { | |
1110 Control shell = shells [i]; | |
1111 do { | |
1112 shell = shell.parent; | |
1113 } while (shell !is null && shell !is this); | |
1114 if (shell is this) count++; | |
1115 } | |
1116 int index = 0; | |
1117 Shell [] result = new Shell [count]; | |
1118 for (int i=0; i<shells.length; i++) { | |
1119 Control shell = shells [i]; | |
1120 do { | |
1121 shell = shell.parent; | |
1122 } while (shell !is null && shell !is this); | |
1123 if (shell is this) { | |
1124 result [index++] = shells [i]; | |
1125 } | |
1126 } | |
1127 return result; | |
1128 } | |
1129 | |
1130 override Composite findDeferredControl () { | |
1131 return layoutCount > 0 ? this : null; | |
1132 } | |
1133 | |
1134 override public bool isEnabled () { | |
1135 checkWidget (); | |
1136 return getEnabled (); | |
1137 } | |
1138 | |
1139 override public bool isVisible () { | |
1140 checkWidget (); | |
1141 return getVisible (); | |
1142 } | |
1143 | |
1144 HWND hwndMDIClient () { | |
1145 if (hwndMDIClient_ is null) { | |
1146 int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS; | |
1147 hwndMDIClient_ = OS.CreateWindowEx ( | |
1148 0, | |
1149 StrToTCHARz("MDICLIENT"), | |
1150 null, | |
1151 widgetStyle, | |
1152 0, 0, 0, 0, | |
1153 handle, | |
1154 null, | |
1155 OS.GetModuleHandle (null), | |
1156 new CREATESTRUCT ()); | |
1157 // OS.ShowWindow (hwndMDIClient_, OS.SW_SHOW); | |
1158 } | |
1159 return hwndMDIClient_; | |
1160 } | |
1161 | |
1162 /** | |
1163 * Moves the receiver to the top of the drawing order for | |
1164 * the display on which it was created (so that all other | |
1165 * shells on that display, which are not the receiver's | |
1166 * children will be drawn behind it), marks it visible, | |
1167 * sets the focus and asks the window manager to make the | |
1168 * shell active. | |
1169 * | |
1170 * @exception SWTException <ul> | |
1171 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1172 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1173 * </ul> | |
1174 * | |
1175 * @see Control#moveAbove | |
1176 * @see Control#setFocus | |
1177 * @see Control#setVisible | |
1178 * @see Display#getActiveShell | |
1179 * @see Decorations#setDefaultButton(Button) | |
1180 * @see Shell#setActive | |
1181 * @see Shell#forceActive | |
1182 */ | |
1183 public void open () { | |
1184 checkWidget (); | |
1185 STARTUPINFO* lpStartUpInfo = Display.lpStartupInfo; | |
1186 if (lpStartUpInfo is null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) is 0) { | |
1187 bringToTop (); | |
1188 if (isDisposed ()) return; | |
1189 } | |
1190 /* | |
1191 * Feature on WinCE PPC. A new application becomes | |
1192 * the foreground application only if it has at least | |
1193 * one visible window before the event loop is started. | |
1194 * The workaround is to explicitly force the shell to | |
1195 * be the foreground window. | |
1196 */ | |
1197 static if (OS.IsWinCE) OS.SetForegroundWindow (handle); | |
1198 OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); | |
1199 setVisible (true); | |
1200 if (isDisposed ()) return; | |
1201 /* | |
1202 * Bug in Windows XP. Despite the fact that an icon has been | |
1203 * set for a window, the task bar displays the wrong icon the | |
1204 * first time the window is made visible with ShowWindow() after | |
1205 * a call to BringToTop(), when a long time elapses between the | |
1206 * ShowWindow() and the time the event queue is read. The icon | |
1207 * in the window trimming is correct but the one in the task | |
1208 * bar does not get updated. The fix is to call PeekMessage() | |
1209 * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond | |
1210 * to a cross thread WM_GETICON. | |
1211 * | |
1212 * NOTE: This allows other cross thread messages to be delivered, | |
1213 * most notably WM_ACTIVATE. | |
1214 */ | |
1215 MSG msg; | |
1216 int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE; | |
1217 OS.PeekMessage (&msg, null, 0, 0, flags); | |
1218 if (!restoreFocus () && !traverseGroup (true)) setFocus (); | |
1219 } | |
1220 | |
1221 public bool print (GC gc) { | |
1222 checkWidget (); | |
1223 if (gc is null) error (SWT.ERROR_NULL_ARGUMENT); | |
1224 if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); | |
1225 return false; | |
1226 } | |
1227 | |
1228 override void register () { | |
1229 super.register (); | |
1230 if (toolTipHandle_ !is null) display.addControl (toolTipHandle_, this); | |
1231 if (balloonTipHandle_ !is null) display.addControl (balloonTipHandle_, this); | |
1232 } | |
1233 | |
1234 void releaseBrushes () { | |
1235 if (brushes !is null) { | |
1236 for (int i=0; i<brushes.length; i++) { | |
1237 if (brushes [i] !is null) OS.DeleteObject (brushes [i]); | |
1238 } | |
1239 } | |
1240 brushes = null; | |
1241 } | |
1242 | |
1243 override void releaseChildren (bool destroy) { | |
1244 Shell [] shells = getShells (); | |
1245 for (int i=0; i<shells.length; i++) { | |
1246 Shell shell = shells [i]; | |
1247 if (shell !is null && !shell.isDisposed ()) { | |
1248 shell.release (false); | |
1249 } | |
1250 } | |
1251 if (toolTips !is null) { | |
1252 for (int i=0; i<toolTips.length; i++) { | |
1253 ToolTip toolTip = toolTips [i]; | |
1254 if (toolTip !is null && !toolTip.isDisposed ()) { | |
1255 toolTip.release (false); | |
1256 } | |
1257 } | |
1258 } | |
1259 toolTips = null; | |
1260 super.releaseChildren (destroy); | |
1261 } | |
1262 | |
1263 override void releaseHandle () { | |
1264 super.releaseHandle (); | |
1265 hwndMDIClient_ = null; | |
1266 } | |
1267 | |
1268 override void releaseParent () { | |
1269 /* Do nothing */ | |
1270 } | |
1271 | |
1272 override void releaseWidget () { | |
1273 super.releaseWidget (); | |
1274 releaseBrushes (); | |
1275 activeMenu = null; | |
1276 display.clearModal (this); | |
1277 if (lpstrTip !is null) { | |
1278 auto hHeap = OS.GetProcessHeap (); | |
1279 OS.HeapFree (hHeap, 0, lpstrTip); | |
1280 } | |
1281 lpstrTip = null; | |
1282 toolTipHandle_ = balloonTipHandle_ = null; | |
1283 if (OS.IsDBLocale) { | |
1284 if (hIMC !is null) OS.ImmDestroyContext (hIMC); | |
1285 } | |
1286 lastActive = null; | |
1287 toolTitle = balloonTitle = null; | |
1288 } | |
1289 | |
1290 override void removeMenu (Menu menu) { | |
1291 super.removeMenu (menu); | |
1292 if (menu is activeMenu) activeMenu = null; | |
1293 } | |
1294 | |
1295 /** | |
1296 * Removes the listener from the collection of listeners who will | |
1297 * be notified when operations are performed on the receiver. | |
1298 * | |
1299 * @param listener the listener which should no longer be notified | |
1300 * | |
1301 * @exception IllegalArgumentException <ul> | |
1302 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> | |
1303 * </ul> | |
1304 * @exception SWTException <ul> | |
1305 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1306 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1307 * </ul> | |
1308 * | |
1309 * @see ShellListener | |
1310 * @see #addShellListener | |
1311 */ | |
1312 public void removeShellListener (ShellListener listener) { | |
1313 checkWidget (); | |
1314 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT); | |
1315 if (eventTable is null) return; | |
1316 eventTable.unhook (SWT.Close, listener); | |
1317 eventTable.unhook (SWT.Iconify,listener); | |
1318 eventTable.unhook (SWT.Deiconify,listener); | |
1319 eventTable.unhook (SWT.Activate, listener); | |
1320 eventTable.unhook (SWT.Deactivate, listener); | |
1321 } | |
1322 | |
1323 LRESULT selectPalette (HPALETTE hPalette) { | |
1324 auto hDC = OS.GetDC (handle); | |
1325 auto hOld = OS.SelectPalette (hDC, hPalette, false); | |
1326 int result = OS.RealizePalette (hDC); | |
1327 if (result > 0) { | |
1328 OS.InvalidateRect (handle, null, true); | |
1329 } else { | |
1330 OS.SelectPalette (hDC, hOld, true); | |
1331 OS.RealizePalette (hDC); | |
1332 } | |
1333 OS.ReleaseDC (handle, hDC); | |
1334 return (result > 0) ? LRESULT.ONE : LRESULT.ZERO; | |
1335 } | |
1336 | |
1337 bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam, Event event) { | |
1338 if (!isEnabled () || !isActive ()) return false; | |
1339 return super.sendKeyEvent (type, msg, wParam, lParam, event); | |
1340 } | |
1341 | |
1342 /** | |
1343 * If the receiver is visible, moves it to the top of the | |
1344 * drawing order for the display on which it was created | |
1345 * (so that all other shells on that display, which are not | |
1346 * the receiver's children will be drawn behind it) and asks | |
1347 * the window manager to make the shell active | |
1348 * | |
1349 * @exception SWTException <ul> | |
1350 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1351 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1352 * </ul> | |
1353 * | |
1354 * @since 2.0 | |
1355 * @see Control#moveAbove | |
1356 * @see Control#setFocus | |
1357 * @see Control#setVisible | |
1358 * @see Display#getActiveShell | |
1359 * @see Decorations#setDefaultButton(Button) | |
1360 * @see Shell#open | |
1361 * @see Shell#setActive | |
1362 */ | |
1363 public void setActive () { | |
1364 checkWidget (); | |
1365 if (!isVisible ()) return; | |
1366 bringToTop (); | |
1367 // widget could be disposed at this point | |
1368 } | |
1369 | |
1370 void setActiveControl (Control control) { | |
1371 if (control !is null && control.isDisposed ()) control = null; | |
1372 if (lastActive !is null && lastActive.isDisposed ()) lastActive = null; | |
1373 if (lastActive is control) return; | |
1374 | |
1375 /* | |
1376 * Compute the list of controls to be activated and | |
1377 * deactivated by finding the first common parent | |
1378 * control. | |
1379 */ | |
1380 Control [] activate = (control is null) ? new Control [0] : control.getPath (); | |
1381 Control [] deactivate = (lastActive is null) ? new Control [0] : lastActive.getPath (); | |
1382 lastActive = control; | |
1383 int index = 0, length = Math.min (activate.length, deactivate.length); | |
1384 while (index < length) { | |
1385 if (activate [index] !is deactivate [index]) break; | |
1386 index++; | |
1387 } | |
1388 | |
1389 /* | |
1390 * It is possible (but unlikely), that application | |
1391 * code could have destroyed some of the widgets. If | |
1392 * this happens, keep processing those widgets that | |
1393 * are not disposed. | |
1394 */ | |
1395 for (int i=deactivate.length-1; i>=index; --i) { | |
1396 if (!deactivate [i].isDisposed ()) { | |
1397 deactivate [i].sendEvent (SWT.Deactivate); | |
1398 } | |
1399 } | |
1400 for (int i=activate.length-1; i>=index; --i) { | |
1401 if (!activate [i].isDisposed ()) { | |
1402 activate [i].sendEvent (SWT.Activate); | |
1403 } | |
1404 } | |
1405 } | |
1406 | |
1407 /** | |
1408 * Sets the receiver's alpha value which must be | |
1409 * between 0 (transparent) and 255 (opaque). | |
1410 * <p> | |
1411 * This operation requires the operating system's advanced | |
1412 * widgets subsystem which may not be available on some | |
1413 * platforms. | |
1414 * </p> | |
1415 * @param alpha the alpha value | |
1416 * | |
1417 * @exception SWTException <ul> | |
1418 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1419 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1420 * </ul> | |
1421 * | |
1422 * @since 3.4 | |
1423 */ | |
1424 public void setAlpha (int alpha) { | |
1425 checkWidget (); | |
1426 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { | |
1427 alpha &= 0xFF; | |
1428 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
1429 if (alpha is 0xFF) { | |
1430 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits & ~OS.WS_EX_LAYERED); | |
1431 int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_FRAME | OS.RDW_ALLCHILDREN; | |
1432 OS.RedrawWindow (handle, null, null, flags); | |
1433 } else { | |
1434 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED); | |
1435 OS.SetLayeredWindowAttributes (handle, 0, cast(byte)alpha, OS.LWA_ALPHA); | |
1436 } | |
1437 } | |
1438 } | |
1439 | |
1440 override void setBounds (int x, int y, int width, int height, int flags, bool defer) { | |
1441 if (fullScreen) setFullScreen (false); | |
1442 /* | |
1443 * Bug in Windows. When a window has alpha and | |
1444 * SetWindowPos() is called with SWP_DRAWFRAME, | |
1445 * the contents of the window are copied rather | |
1446 * than allowing the windows underneath to draw. | |
1447 * This causes pixel corruption. The fix is to | |
1448 * clear the SWP_DRAWFRAME bits. | |
1449 */ | |
1450 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
1451 if ((bits & OS.WS_EX_LAYERED) !is 0) { | |
1452 flags &= ~OS.SWP_DRAWFRAME; | |
1453 } | |
1454 super.setBounds (x, y, width, height, flags, false); | |
1455 } | |
1456 | |
1457 override public void setEnabled (bool enabled) { | |
1458 checkWidget (); | |
1459 if (((state & DISABLED) is 0) is enabled) return; | |
1460 super.setEnabled (enabled); | |
1461 if (enabled && handle is OS.GetActiveWindow ()) { | |
1462 if (!restoreFocus ()) traverseGroup (true); | |
1463 } | |
1464 } | |
1465 | |
1466 /** | |
1467 * Sets the full screen state of the receiver. | |
1468 * If the argument is <code>true</code> causes the receiver | |
1469 * to switch to the full screen state, and if the argument is | |
1470 * <code>false</code> and the receiver was previously switched | |
1471 * into full screen state, causes the receiver to switch back | |
1472 * to either the maximmized or normal states. | |
1473 * <p> | |
1474 * Note: The result of intermixing calls to <code>setFullScreen(true)</code>, | |
1475 * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will | |
1476 * vary by platform. Typically, the behavior will match the platform user's | |
1477 * expectations, but not always. This should be avoided if possible. | |
1478 * </p> | |
1479 * | |
1480 * @param fullScreen the new fullscreen state | |
1481 * | |
1482 * @exception SWTException <ul> | |
1483 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1484 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1485 * </ul> | |
1486 * | |
1487 * @since 3.4 | |
1488 */ | |
1489 public void setFullScreen (bool fullScreen) { | |
1490 checkWidget(); | |
1491 if (this.fullScreen is fullScreen) return; | |
1492 int stateFlags = fullScreen ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE; | |
1493 int styleFlags = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
1494 int mask = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; | |
1495 if ((style & mask) !is 0) { | |
1496 if (fullScreen) { | |
1497 styleFlags = styleFlags & ~OS.WS_CAPTION; | |
1498 } else { | |
1499 styleFlags = styleFlags | OS.WS_CAPTION; | |
1500 } | |
1501 } | |
1502 if (fullScreen) wasMaximized = getMaximized (); | |
1503 bool visible = isVisible (); | |
1504 OS.SetWindowLong (handle, OS.GWL_STYLE, styleFlags); | |
1505 if (wasMaximized) { | |
1506 OS.ShowWindow (handle, OS.SW_HIDE); | |
1507 stateFlags = OS.SW_SHOWMAXIMIZED; | |
1508 } | |
1509 if (visible) OS.ShowWindow (handle, stateFlags); | |
1510 OS.UpdateWindow (handle); | |
1511 this.fullScreen = fullScreen; | |
1512 } | |
1513 | |
1514 /** | |
1515 * Sets the input method editor mode to the argument which | |
1516 * should be the result of bitwise OR'ing together one or more | |
1517 * of the following constants defined in class <code>SWT</code>: | |
1518 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>, | |
1519 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>. | |
1520 * | |
1521 * @param mode the new IME mode | |
1522 * | |
1523 * @exception SWTException <ul> | |
1524 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1525 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1526 * </ul> | |
1527 * | |
1528 * @see SWT | |
1529 */ | |
1530 public void setImeInputMode (int mode) { | |
1531 checkWidget (); | |
1532 if (!OS.IsDBLocale) return; | |
1533 bool imeOn = mode !is SWT.NONE; | |
1534 auto hIMC = OS.ImmGetContext (handle); | |
1535 OS.ImmSetOpenStatus (hIMC, imeOn); | |
1536 if (imeOn) { | |
1537 uint lpfdwConversion, lpfdwSentence; | |
1538 if (OS.ImmGetConversionStatus (hIMC, &lpfdwConversion, &lpfdwSentence)) { | |
1539 int newBits = 0; | |
1540 int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA; | |
1541 if ((mode & SWT.PHONETIC) !is 0) { | |
1542 newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE; | |
1543 oldBits = 0; | |
1544 } else { | |
1545 if ((mode & SWT.NATIVE) !is 0) { | |
1546 newBits = OS.IME_CMODE_NATIVE; | |
1547 oldBits = OS.IME_CMODE_KATAKANA; | |
1548 } | |
1549 } | |
1550 if ((mode & (SWT.DBCS | SWT.NATIVE)) !is 0) { | |
1551 newBits |= OS.IME_CMODE_FULLSHAPE; | |
1552 } else { | |
1553 oldBits |= OS.IME_CMODE_FULLSHAPE; | |
1554 } | |
1555 if ((mode & SWT.ROMAN) !is 0) { | |
1556 newBits |= OS.IME_CMODE_ROMAN; | |
1557 } else { | |
1558 oldBits |= OS.IME_CMODE_ROMAN; | |
1559 } | |
1560 lpfdwConversion |= newBits; | |
1561 lpfdwConversion &= ~oldBits; | |
1562 OS.ImmSetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence); | |
1563 } | |
1564 } | |
1565 OS.ImmReleaseContext (handle, hIMC); | |
1566 } | |
1567 | |
1568 /** | |
1569 * Sets the receiver's minimum size to the size specified by the arguments. | |
1570 * If the new minimum size is larger than the current size of the receiver, | |
1571 * the receiver is resized to the new minimum size. | |
1572 * | |
1573 * @param width the new minimum width for the receiver | |
1574 * @param height the new minimum height for the receiver | |
1575 * | |
1576 * @exception SWTException <ul> | |
1577 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1578 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1579 * </ul> | |
1580 * | |
1581 * @since 3.1 | |
1582 */ | |
1583 public void setMinimumSize (int width, int height) { | |
1584 checkWidget (); | |
1585 int widthLimit = 0, heightLimit = 0; | |
1586 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; | |
1587 if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) { | |
1588 widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK); | |
1589 if ((style & SWT.RESIZE) !is 0) { | |
1590 heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK); | |
1591 } else { | |
1592 RECT rect; | |
1593 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
1594 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
1595 OS.AdjustWindowRectEx (&rect, bits1, false, bits2); | |
1596 heightLimit = rect.bottom - rect.top; | |
1597 } | |
1598 } | |
1599 minWidth = Math.max (widthLimit, width); | |
1600 minHeight = Math.max (heightLimit, height); | |
1601 Point size = getSize (); | |
1602 int newWidth = Math.max (size.x, minWidth); | |
1603 int newHeight = Math.max (size.y, minHeight); | |
1604 if (minWidth <= widthLimit) minWidth = SWT.DEFAULT; | |
1605 if (minHeight <= heightLimit) minHeight = SWT.DEFAULT; | |
1606 if (newWidth !is size.x || newHeight !is size.y) setSize (newWidth, newHeight); | |
1607 } | |
1608 | |
1609 /** | |
1610 * Sets the receiver's minimum size to the size specified by the argument. | |
1611 * If the new minimum size is larger than the current size of the receiver, | |
1612 * the receiver is resized to the new minimum size. | |
1613 * | |
1614 * @param size the new minimum size for the receiver | |
1615 * | |
1616 * @exception IllegalArgumentException <ul> | |
1617 * <li>ERROR_NULL_ARGUMENT - if the point is null</li> | |
1618 * </ul> | |
1619 * @exception SWTException <ul> | |
1620 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1621 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1622 * </ul> | |
1623 * | |
1624 * @since 3.1 | |
1625 */ | |
1626 public void setMinimumSize (Point size) { | |
1627 checkWidget (); | |
1628 if (size is null) error (SWT.ERROR_NULL_ARGUMENT); | |
1629 setMinimumSize (size.x, size.y); | |
1630 } | |
1631 | |
1632 void setItemEnabled (int cmd, bool enabled) { | |
1633 auto hMenu = OS.GetSystemMenu (handle, false); | |
1634 if (hMenu is null) return; | |
1635 int flags = OS.MF_ENABLED; | |
1636 if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED; | |
1637 OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags); | |
1638 } | |
1639 | |
1640 override void setParent () { | |
1641 /* Do nothing. Not necessary for Shells */ | |
1642 } | |
1643 | |
1644 /** | |
1645 * Sets the shape of the shell to the region specified | |
1646 * by the argument. When the argument is null, the | |
1647 * default shape of the shell is restored. The shell | |
1648 * must be created with the style SWT.NO_TRIM in order | |
1649 * to specify a region. | |
1650 * | |
1651 * @param region the region that defines the shape of the shell (or null) | |
1652 * | |
1653 * @exception IllegalArgumentException <ul> | |
1654 * <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li> | |
1655 * </ul> | |
1656 * @exception SWTException <ul> | |
1657 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1658 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1659 * </ul> | |
1660 * | |
1661 * @since 3.0 | |
1662 * | |
1663 */ | |
1664 public void setRegion (Region region) { | |
1665 checkWidget (); | |
1666 if ((style & SWT.NO_TRIM) is 0) return; | |
1667 super.setRegion (region); | |
1668 } | |
1669 | |
1670 void setToolTipText (HWND hwnd, String text) { | |
1671 static if (OS.IsWinCE) return; | |
1672 TOOLINFO lpti; | |
1673 lpti.cbSize = OS.TOOLINFO_sizeof; | |
1674 lpti.hwnd = handle; | |
1675 lpti.uId = cast(uint) hwnd; | |
1676 auto hwndToolTip = toolTipHandle (); | |
1677 if (text is null) { | |
1678 OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, cast(int)&lpti); | |
1679 } else { | |
1680 if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, cast(int)&lpti) !is 0) { | |
1681 OS.SendMessage (hwndToolTip, OS.TTM_UPDATE, 0, 0); | |
1682 } else { | |
1683 lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS; | |
1684 lpti.lpszText = OS.LPSTR_TEXTCALLBACK; | |
1685 OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, cast(int)&lpti); | |
1686 } | |
1687 } | |
1688 } | |
1689 | |
1690 void setToolTipText (NMTTDISPINFO* lpnmtdi, CHAR [] buffer) { | |
1691 /* | |
1692 * Ensure that the current position of the mouse | |
1693 * is inside the client area of the shell. This | |
1694 * prevents tool tips from popping up over the | |
1695 * shell trimmings. | |
1696 */ | |
1697 if (!hasCursor ()) return; | |
1698 auto hHeap = OS.GetProcessHeap (); | |
1699 if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip); | |
1700 int byteCount = buffer.length; | |
1701 lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
1702 OS.MoveMemory (lpstrTip, buffer.ptr, byteCount); | |
1703 lpnmtdi.lpszText = lpstrTip; | |
1704 } | |
1705 | |
1706 void setToolTipText (NMTTDISPINFO* lpnmtdi, WCHAR [] buffer) { | |
1707 /* | |
1708 * Ensure that the current position of the mouse | |
1709 * is inside the client area of the shell. This | |
1710 * prevents tool tips from popping up over the | |
1711 * shell trimmings. | |
1712 */ | |
1713 if (!hasCursor ()) return; | |
1714 auto hHeap = OS.GetProcessHeap (); | |
1715 if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip); | |
1716 int byteCount = buffer.length * 2; | |
1717 lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
1718 OS.MoveMemory (lpstrTip, buffer.ptr, byteCount); | |
1719 lpnmtdi.lpszText = lpstrTip; | |
1720 } | |
1721 | |
1722 void setToolTipTitle (HWND hwndToolTip, String text, HICON icon) { | |
1723 /* | |
1724 * Bug in Windows. For some reason, when TTM_SETTITLE | |
1725 * is used to set the title of a tool tip, Windows leaks | |
1726 * GDI objects. This happens even when TTM_SETTITLE is | |
1727 * called with TTI_NONE and NULL. The documentation | |
1728 * states that Windows copies the icon and that the | |
1729 * programmer must free the copy but does not provide | |
1730 * API to get the icon. For example, when TTM_SETTITLE | |
1731 * is called with ICON_ERROR, when TTM_GETTITLE is used | |
1732 * to query the title and the icon, the uTitleBitmap | |
1733 * field in the TTGETTITLE struct is zero. The fix | |
1734 * is to remember these values, only set them when then | |
1735 * change and leak less. | |
1736 * | |
1737 * NOTE: This only happens on Vista. | |
1738 */ | |
1739 if (hwndToolTip !is toolTipHandle_ && hwndToolTip !is balloonTipHandle_) { | |
1740 return; | |
1741 } | |
1742 if (hwndToolTip is toolTipHandle_) { | |
1743 if (text is toolTitle || (toolTitle !is null && toolTitle.equals (text) )) { | |
1744 if (icon is toolIcon) return; | |
1745 } | |
1746 toolTitle = text; | |
1747 toolIcon = icon; | |
1748 } else { | |
1749 if (hwndToolTip is balloonTipHandle_) { | |
1750 if (text is balloonTitle || (balloonTitle !is null && balloonTitle.equals (text))) { | |
1751 if (icon is toolIcon) return; | |
1752 } | |
1753 balloonTitle = text; | |
1754 balloonIcon = icon; | |
1755 } | |
1756 } | |
1757 if (text !is null) { | |
1758 static if( OS.IsUnicode ){ | |
1759 TCHAR* pszTitle = StrToTCHARz( text); | |
1760 } | |
1761 else { | |
1762 TCHAR* pszTitle = StrToTCHARz( text, getCodePage ()); | |
1763 } | |
1764 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, cast(int)pszTitle); | |
1765 } else { | |
1766 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0); | |
1767 } | |
1768 } | |
1769 | |
1770 override public void setVisible (bool visible) { | |
1771 checkWidget (); | |
1772 /* | |
1773 * Feature in Windows. When ShowWindow() is called used to hide | |
1774 * a window, Windows attempts to give focus to the parent. If the | |
1775 * parent is disabled by EnableWindow(), focus is assigned to | |
1776 * another windows on the desktop. This means that if you hide | |
1777 * a modal window before the parent is enabled, the parent will | |
1778 * not come to the front. The fix is to change the modal state | |
1779 * before hiding or showing a window so that this does not occur. | |
1780 */ | |
1781 int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL; | |
1782 if ((style & mask) !is 0) { | |
1783 if (visible) { | |
1784 display.setModalShell (this); | |
1785 if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) !is 0) { | |
1786 display.setModalDialog (null); | |
1787 } | |
1788 Control control = display._getFocusControl (); | |
1789 if (control !is null && !control.isActive ()) { | |
1790 bringToTop (); | |
1791 if (isDisposed ()) return; | |
1792 } | |
1793 auto hwndShell = OS.GetActiveWindow (); | |
1794 if (hwndShell is null) { | |
1795 if (parent !is null) hwndShell = parent.handle; | |
1796 } | |
1797 if (hwndShell !is null) { | |
1798 OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0); | |
1799 } | |
1800 OS.ReleaseCapture (); | |
1801 } else { | |
1802 display.clearModal (this); | |
1803 } | |
1804 } else { | |
1805 updateModal (); | |
1806 } | |
1807 | |
1808 /* | |
1809 * Bug in Windows. Calling ShowOwnedPopups() to hide the | |
1810 * child windows of a hidden window causes the application | |
1811 * to be deactivated. The fix is to call ShowOwnedPopups() | |
1812 * to hide children before hiding the parent. | |
1813 */ | |
1814 if (showWithParent && !visible) { | |
1815 static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, false); | |
1816 } | |
1817 if (!visible) fixActiveShell (); | |
1818 super.setVisible (visible); | |
1819 if (isDisposed ()) return; | |
1820 if (showWithParent !is visible) { | |
1821 showWithParent = visible; | |
1822 if (visible) { | |
1823 static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true); | |
1824 } | |
1825 } | |
1826 | |
1827 /* Make the splash screen appear in the task bar */ | |
1828 if (visible) { | |
1829 if (parent !is null && (parent.state & FOREIGN_HANDLE) !is 0) { | |
1830 auto hwndParent = parent.handle; | |
1831 int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); | |
1832 if ((style & OS.WS_EX_TOOLWINDOW) !is 0) { | |
1833 OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, style & ~OS.WS_EX_TOOLWINDOW); | |
1834 /* | |
1835 * Bug in Windows. The window does not show in the task bar when | |
1836 * WS_EX_TOOLWINDOW is removed after the window has already been shown. | |
1837 * The fix is to hide and shown the shell. | |
1838 */ | |
1839 OS.ShowWindow (hwndParent, OS.SW_HIDE); | |
1840 OS.ShowWindow (hwndParent, OS.SW_RESTORE); | |
1841 } | |
1842 } | |
1843 } | |
1844 } | |
1845 | |
1846 override void subclass () { | |
1847 super.subclass (); | |
1848 if (ToolTipProc !is null) { | |
1849 int /*long*/ newProc = display.windowProc; | |
1850 if (toolTipHandle_ !is null) { | |
1851 OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, newProc); | |
1852 } | |
1853 if (balloonTipHandle_ !is null) { | |
1854 OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, newProc); | |
1855 } | |
1856 } | |
1857 } | |
1858 | |
1859 HANDLE toolTipHandle () { | |
1860 if (toolTipHandle_ is null) createToolTipHandle (); | |
1861 return toolTipHandle_; | |
1862 } | |
1863 | |
1864 override bool translateAccelerator (MSG* msg) { | |
1865 if (!isEnabled () || !isActive ()) return false; | |
1866 if (menuBar !is null && !menuBar.isEnabled ()) return false; | |
1867 return translateMDIAccelerator (msg) || translateMenuAccelerator (msg); | |
1868 } | |
1869 | |
1870 override bool traverseEscape () { | |
1871 if (parent is null) return false; | |
1872 if (!isVisible () || !isEnabled ()) return false; | |
1873 close (); | |
1874 return true; | |
1875 } | |
1876 | |
1877 override void unsubclass () { | |
1878 super.unsubclass (); | |
1879 if (ToolTipProc !is null) { | |
1880 if (toolTipHandle_ !is null) { | |
1881 OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc); | |
1882 } | |
1883 if (toolTipHandle_ !is null) { | |
1884 OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc); | |
1885 } | |
1886 } | |
1887 } | |
1888 | |
1889 void updateModal () { | |
1890 if (Display.TrimEnabled) { | |
1891 setItemEnabled (OS.SC_CLOSE, isActive ()); | |
1892 } else { | |
1893 OS.EnableWindow (handle, isActive ()); | |
1894 } | |
1895 } | |
1896 | |
1897 override CREATESTRUCT* widgetCreateStruct () { | |
1898 return null; | |
1899 } | |
1900 | |
1901 override HWND widgetParent () { | |
1902 if (handle !is null) return handle; | |
1903 return parent !is null ? parent.handle : null; | |
1904 } | |
1905 | |
1906 override int widgetExtStyle () { | |
1907 int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD; | |
1908 if ((style & SWT.TOOL) !is 0) bits |= OS.WS_EX_TOOLWINDOW; | |
1909 | |
1910 /* | |
1911 * Feature in Windows. When a window that does not have a parent | |
1912 * is created, it is automatically added to the Windows Task Bar, | |
1913 * even when it has no title. The fix is to use WS_EX_TOOLWINDOW | |
1914 * which does not cause the window to appear in the Task Bar. | |
1915 */ | |
1916 static if (!OS.IsWinCE) { | |
1917 if (parent is null) { | |
1918 if ((style & SWT.ON_TOP) !is 0) { | |
1919 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; | |
1920 if ((style & SWT.NO_TRIM) !is 0 || (style & trim) is 0) { | |
1921 bits |= OS.WS_EX_TOOLWINDOW; | |
1922 } | |
1923 } | |
1924 } | |
1925 } | |
1926 | |
1927 /* | |
1928 * Bug in Windows 98 and NT. Creating a window with the | |
1929 * WS_EX_TOPMOST extended style can result in a dialog shell | |
1930 * being moved behind its parent. The exact case where this | |
1931 * happens is a shell with two dialog shell children where | |
1932 * each dialog child has another hidden dialog child with | |
1933 * the WS_EX_TOPMOST extended style. Clicking on either of | |
1934 * the visible dialogs causes them to become active but move | |
1935 * to the back, behind the parent shell. The fix is to | |
1936 * disallow the WS_EX_TOPMOST extended style on Windows 98 | |
1937 * and NT. | |
1938 */ | |
1939 if (parent !is null) { | |
1940 if (OS.IsWin95) return bits; | |
1941 if (OS.WIN32_VERSION < OS.VERSION (4, 10)) { | |
1942 return bits; | |
1943 } | |
1944 } | |
1945 if ((style & SWT.ON_TOP) !is 0) bits |= OS.WS_EX_TOPMOST; | |
1946 return bits; | |
1947 } | |
1948 | |
1949 override String windowClass () { | |
1950 static if (OS.IsSP) return DialogClass; | |
1951 if ((style & SWT.TOOL) !is 0) { | |
1952 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; | |
1953 if ((style & trim) is 0) return TCHARsToStr( display.windowShadowClass ); | |
1954 } | |
1955 return parent !is null ? TCHARzToStr(DialogClass.ptr) : super.windowClass (); | |
1956 } | |
1957 | |
1958 override int windowProc () { | |
1959 if (windowProc_ !is null) return cast(int) windowProc_; | |
1960 static if (OS.IsSP) return cast(int) DialogProc; | |
1961 if ((style & SWT.TOOL) !is 0) { | |
1962 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE; | |
1963 if ((style & trim) is 0) return super.windowProc (); | |
1964 } | |
1965 return parent !is null ? cast(int) DialogProc : super.windowProc (); | |
1966 } | |
1967 | |
1968 override int windowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
1969 if (handle is null) return 0; | |
1970 if (hwnd is toolTipHandle_ || hwnd is balloonTipHandle_) { | |
1971 switch (msg) { | |
1972 case OS.WM_TIMER: { | |
1973 if (wParam !is ToolTip.TIMER_ID) break; | |
1974 ToolTip tip = getCurrentToolTip (hwnd); | |
1975 if (tip !is null && tip.autoHide) { | |
1976 tip.setVisible (false); | |
1977 } | |
1978 break; | |
1979 } | |
1980 case OS.WM_LBUTTONDOWN: { | |
1981 ToolTip tip = getCurrentToolTip (hwnd); | |
1982 if (tip !is null) { | |
1983 tip.setVisible (false); | |
1984 tip.postEvent (SWT.Selection); | |
1985 } | |
1986 break; | |
1987 } | |
1988 default: | |
1989 } | |
1990 return callWindowProc (hwnd, msg, wParam, lParam); | |
1991 } | |
1992 return super.windowProc (hwnd, msg, wParam, lParam); | |
1993 } | |
1994 | |
1995 override int widgetStyle () { | |
1996 int bits = super.widgetStyle (); | |
1997 if (handle !is null) return bits | OS.WS_CHILD; | |
1998 bits &= ~OS.WS_CHILD; | |
1999 /* | |
2000 * Feature in WinCE. Calling CreateWindowEx () with WS_OVERLAPPED | |
2001 * and a parent window causes the new window to become a WS_CHILD of | |
2002 * the parent instead of a dialog child. The fix is to use WS_POPUP | |
2003 * for a window with a parent. | |
2004 * | |
2005 * Feature in WinCE PPC. A window without a parent with WS_POPUP | |
2006 * always shows on top of the Pocket PC 'Today Screen'. The fix | |
2007 * is to not set WS_POPUP for a window without a parent on WinCE | |
2008 * devices. | |
2009 * | |
2010 * NOTE: WS_POPUP causes CreateWindowEx () to ignore CW_USEDEFAULT | |
2011 * and causes the default window location and size to be zero. | |
2012 */ | |
2013 static if (OS.IsWinCE) { | |
2014 if (OS.IsSP) return bits | OS.WS_POPUP; | |
2015 return parent is null ? bits : bits | OS.WS_POPUP; | |
2016 } | |
2017 | |
2018 /* | |
2019 * Use WS_OVERLAPPED for all windows, either dialog or top level | |
2020 * so that CreateWindowEx () will respect CW_USEDEFAULT and set | |
2021 * the default window location and size. | |
2022 * | |
2023 * NOTE: When a WS_OVERLAPPED window is created, Windows gives | |
2024 * the new window WS_CAPTION style bits. These two constants are | |
2025 * as follows: | |
2026 * | |
2027 * WS_OVERLAPPED = 0 | |
2028 * WS_CAPTION = WS_BORDER | WS_DLGFRAME | |
2029 * | |
2030 */ | |
2031 return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION; | |
2032 } | |
2033 | |
2034 override LRESULT WM_ACTIVATE (int wParam, int lParam) { | |
2035 static if (OS.IsPPC) { | |
2036 /* | |
2037 * Note: this does not work when we get WM_ACTIVATE prior | |
2038 * to adding a listener. | |
2039 */ | |
2040 if (hooks (SWT.HardKeyDown) || hooks (SWT.HardKeyUp)) { | |
2041 int fActive = OS.LOWORD (wParam); | |
2042 int /*long*/ hwnd = fActive !is 0 ? handle : 0; | |
2043 for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) { | |
2044 OS.SHSetAppKeyWndAssoc (cast(byte) bVk, hwnd); | |
2045 } | |
2046 } | |
2047 /* Restore SIP state when window is activated */ | |
2048 if (OS.LOWORD (wParam) !is 0) { | |
2049 OS.SHSipPreference (handle, psai.fSipUp is 0 ? OS.SIP_DOWN : OS.SIP_UP); | |
2050 } | |
2051 } | |
2052 | |
2053 /* | |
2054 * Bug in Windows XP. When a Shell is deactivated, the | |
2055 * IME composition window does not go away. This causes | |
2056 * repaint issues. The fix is to commit the composition | |
2057 * string. | |
2058 */ | |
2059 if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) { | |
2060 if (OS.LOWORD (wParam) is 0 && OS.IsDBLocale && hIMC !is null) { | |
2061 if (OS.ImmGetOpenStatus (hIMC)) { | |
2062 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
2063 } | |
2064 } | |
2065 } | |
2066 | |
2067 /* Process WM_ACTIVATE */ | |
2068 LRESULT result = super.WM_ACTIVATE (wParam, lParam); | |
2069 if (OS.LOWORD (wParam) is 0) { | |
2070 if (lParam is 0 || (cast(HANDLE)lParam !is toolTipHandle_ && cast(HANDLE)lParam !is balloonTipHandle_)) { | |
2071 ToolTip tip = getCurrentToolTip (); | |
2072 if (tip !is null) tip.setVisible (false); | |
2073 } | |
2074 } | |
2075 return parent !is null ? LRESULT.ZERO : result; | |
2076 } | |
2077 | |
2078 override LRESULT WM_COMMAND (int wParam, int lParam) { | |
2079 static if (OS.IsPPC) { | |
2080 /* | |
2081 * Note in WinCE PPC: Close the Shell when the "Done Button" has | |
2082 * been pressed. lParam is either 0 (PocketPC 2002) or the handle | |
2083 * to the Shell (PocketPC). | |
2084 */ | |
2085 int loWord = OS.LOWORD (wParam); | |
2086 if (loWord is OS.IDOK && (lParam is 0 || lParam is handle)) { | |
2087 OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); | |
2088 return LRESULT.ZERO; | |
2089 } | |
2090 } | |
2091 /* | |
2092 * Feature in Windows. On PPC, the menu is not actually an HMENU. | |
2093 * By observation, it is a tool bar that is configured to look like | |
2094 * a menu. Therefore, when the PPC menu sends WM_COMMAND messages, | |
2095 * lParam is not zero because the WM_COMMAND was not sent from a menu. | |
2096 * Sub menu item events originate from the menu bar. Top menu items | |
2097 * events originate from a tool bar. The fix is to detect the source | |
2098 * of the WM_COMMAND and set lParam to zero to pretend that the message | |
2099 * came from a real Windows menu, not a tool bar. | |
2100 */ | |
2101 static if (OS.IsPPC || OS.IsSP) { | |
2102 if (menuBar !is null) { | |
2103 auto hwndCB = menuBar.hwndCB; | |
2104 if (lParam !is 0 && hwndCB !is null) { | |
2105 if (lParam is hwndCB) { | |
2106 return super.WM_COMMAND (wParam, 0); | |
2107 } else { | |
2108 int /*long*/ hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD); | |
2109 if (lParam is hwndChild) return super.WM_COMMAND (wParam, 0); | |
2110 } | |
2111 } | |
2112 } | |
2113 } | |
2114 return super.WM_COMMAND (wParam, lParam); | |
2115 } | |
2116 | |
2117 override LRESULT WM_DESTROY (int wParam, int lParam) { | |
2118 LRESULT result = super.WM_DESTROY (wParam, lParam); | |
2119 /* | |
2120 * When the shell is a WS_CHILD window of a non-SWT | |
2121 * window, the destroy code does not get called because | |
2122 * the non-SWT window does not call dispose (). Instead, | |
2123 * the destroy code is called here in WM_DESTROY. | |
2124 */ | |
2125 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
2126 if ((bits & OS.WS_CHILD) !is 0) { | |
2127 releaseParent (); | |
2128 release (false); | |
2129 } | |
2130 return result; | |
2131 } | |
2132 | |
2133 override LRESULT WM_ERASEBKGND (int wParam, int lParam) { | |
2134 LRESULT result = super.WM_ERASEBKGND (wParam, lParam); | |
2135 if (result !is null) return result; | |
2136 /* | |
2137 * Feature in Windows. When a shell is resized by dragging | |
2138 * the resize handles, Windows temporarily fills in black | |
2139 * rectangles where the new contents of the shell should | |
2140 * draw. The fix is to always draw the background of shells. | |
2141 * | |
2142 * NOTE: This only happens on Vista. | |
2143 */ | |
2144 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { | |
2145 drawBackground (cast(HDC)wParam); | |
2146 return LRESULT.ONE; | |
2147 } | |
2148 return result; | |
2149 } | |
2150 | |
2151 override LRESULT WM_ENTERIDLE (int wParam, int lParam) { | |
2152 LRESULT result = super.WM_ENTERIDLE (wParam, lParam); | |
2153 if (result !is null) return result; | |
2154 if (display.runMessages) { | |
2155 if (display.runAsyncMessages (false)) display.wakeThread (); | |
2156 } | |
2157 return result; | |
2158 } | |
2159 | |
2160 override LRESULT WM_GETMINMAXINFO (int wParam, int lParam) { | |
2161 LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam); | |
2162 if (result !is null) return result; | |
2163 if (minWidth !is SWT.DEFAULT || minHeight !is SWT.DEFAULT) { | |
2164 MINMAXINFO* info = cast(MINMAXINFO*)lParam; | |
2165 //OS.MoveMemory (info, lParam, MINMAXINFO.sizeof); | |
2166 if (minWidth !is SWT.DEFAULT) info.ptMinTrackSize.x = minWidth; | |
2167 if (minHeight !is SWT.DEFAULT) info.ptMinTrackSize.y = minHeight; | |
2168 //OS.MoveMemory (lParam, info, MINMAXINFO.sizeof); | |
2169 return LRESULT.ZERO; | |
2170 } | |
2171 return result; | |
2172 } | |
2173 | |
2174 override LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) { | |
2175 LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam); | |
2176 if (result !is null) return result; | |
2177 | |
2178 /* | |
2179 * Check for WM_MOUSEACTIVATE when an MDI shell is active | |
2180 * and stop the normal shell activation but allow the mouse | |
2181 * down to be delivered. | |
2182 */ | |
2183 int hittest = cast(short) OS.LOWORD (lParam); | |
2184 switch (hittest) { | |
2185 case OS.HTERROR: | |
2186 case OS.HTTRANSPARENT: | |
2187 case OS.HTNOWHERE: | |
2188 break; | |
2189 default: { | |
2190 Control control = display._getFocusControl (); | |
2191 if (control !is null) { | |
2192 Decorations decorations = control.menuShell (); | |
2193 if (decorations.getShell () is this && decorations !is this) { | |
2194 display.ignoreRestoreFocus = true; | |
2195 display.lastHittest = hittest; | |
2196 display.lastHittestControl = null; | |
2197 if (hittest is OS.HTMENU || hittest is OS.HTSYSMENU) { | |
2198 display.lastHittestControl = control; | |
2199 return null; | |
2200 } | |
2201 if (OS.IsWin95 && hittest is OS.HTCAPTION) { | |
2202 display.lastHittestControl = control; | |
2203 } | |
2204 return new LRESULT (OS.MA_NOACTIVATE); | |
2205 } | |
2206 } | |
2207 } | |
2208 } | |
2209 if (hittest is OS.HTMENU) return null; | |
2210 | |
2211 /* | |
2212 * Get the current location of the cursor, | |
2213 * not the location of the cursor when the | |
2214 * WM_MOUSEACTIVATE was generated. This is | |
2215 * strictly incorrect but is necessary in | |
2216 * order to support Activate and Deactivate | |
2217 * events for embedded widgets that have | |
2218 * their own event loop. In that case, the | |
2219 * cursor location reported by GetMessagePos() | |
2220 * is the one for our event loop, not the | |
2221 * embedded widget's event loop. | |
2222 */ | |
2223 POINT pt; | |
2224 if (!OS.GetCursorPos (&pt)) { | |
2225 int pos = OS.GetMessagePos (); | |
2226 OS.POINTSTOPOINT (pt, pos); | |
2227 } | |
2228 auto hwnd = OS.WindowFromPoint (pt); | |
2229 if (hwnd is null) return null; | |
2230 Control control = display.findControl (hwnd); | |
2231 | |
2232 /* | |
2233 * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS, | |
2234 * do not activate the shell when the user clicks on the | |
2235 * the client area or on the border or a control within the | |
2236 * shell that does not take focus. | |
2237 */ | |
2238 if (control !is null && (control.state & CANVAS) !is 0) { | |
2239 if ((control.style & SWT.NO_FOCUS) !is 0) { | |
2240 int bits = SWT.ON_TOP | SWT.NO_FOCUS; | |
2241 if ((style & bits) is bits) { | |
2242 if (hittest is OS.HTBORDER || hittest is OS.HTCLIENT) { | |
2243 return new LRESULT (OS.MA_NOACTIVATE); | |
2244 } | |
2245 } | |
2246 } | |
2247 } | |
2248 | |
2249 int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam); | |
2250 setActiveControl (control); | |
2251 return new LRESULT (code); | |
2252 } | |
2253 | |
2254 override LRESULT WM_MOVE (int wParam, int lParam) { | |
2255 LRESULT result = super.WM_MOVE (wParam, lParam); | |
2256 if (result !is null) return result; | |
2257 ToolTip tip = getCurrentToolTip (); | |
2258 if (tip !is null) tip.setVisible (false); | |
2259 return result; | |
2260 } | |
2261 | |
2262 override LRESULT WM_NCHITTEST (int wParam, int lParam) { | |
2263 if (!OS.IsWindowEnabled (handle)) return null; | |
2264 if (!isEnabled () || !isActive ()) { | |
2265 if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE); | |
2266 int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); | |
2267 if (hittest is OS.HTCLIENT || hittest is OS.HTMENU) hittest = OS.HTBORDER; | |
2268 return new LRESULT (hittest); | |
2269 } | |
2270 if (menuBar !is null && !menuBar.getEnabled ()) { | |
2271 int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); | |
2272 if (hittest is OS.HTMENU) hittest = OS.HTBORDER; | |
2273 return new LRESULT (hittest); | |
2274 } | |
2275 return null; | |
2276 } | |
2277 | |
2278 override LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) { | |
2279 LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam); | |
2280 if (result !is null) return result; | |
2281 /* | |
2282 * When the normal activation was interrupted in WM_MOUSEACTIVATE | |
2283 * because the active shell was an MDI shell, set the active window | |
2284 * to the top level shell but lock the active window and stop focus | |
2285 * changes. This allows the user to interact the top level shell | |
2286 * in the normal manner. | |
2287 */ | |
2288 if (!display.ignoreRestoreFocus) return result; | |
2289 Display display = this.display; | |
2290 HWND hwndActive; | |
2291 bool fixActive = OS.IsWin95 && display.lastHittest is OS.HTCAPTION; | |
2292 if (fixActive) hwndActive = OS.SetActiveWindow (handle); | |
2293 display.lockActiveWindow = true; | |
2294 int /*long*/ code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam); | |
2295 display.lockActiveWindow = false; | |
2296 if (fixActive) OS.SetActiveWindow (hwndActive); | |
2297 Control focusControl = display.lastHittestControl; | |
2298 if (focusControl !is null && !focusControl.isDisposed ()) { | |
2299 focusControl.setFocus (); | |
2300 } | |
2301 display.lastHittestControl = null; | |
2302 display.ignoreRestoreFocus = false; | |
2303 return new LRESULT (code); | |
2304 } | |
2305 | |
2306 override LRESULT WM_PALETTECHANGED (int wParam, int lParam) { | |
2307 if ( cast(HANDLE)wParam !is handle) { | |
2308 auto hPalette = display.hPalette; | |
2309 if (hPalette !is null) return selectPalette (hPalette); | |
2310 } | |
2311 return super.WM_PALETTECHANGED (wParam, lParam); | |
2312 } | |
2313 | |
2314 override LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) { | |
2315 auto hPalette = display.hPalette; | |
2316 if (hPalette !is null) return selectPalette (hPalette); | |
2317 return super.WM_QUERYNEWPALETTE (wParam, lParam); | |
2318 } | |
2319 | |
2320 override LRESULT WM_SETCURSOR (int wParam, int lParam) { | |
2321 /* | |
2322 * Feature in Windows. When the shell is disabled | |
2323 * by a Windows standard dialog (like a MessageBox | |
2324 * or FileDialog), clicking in the shell does not | |
2325 * bring the shell or the dialog to the front. The | |
2326 * fix is to detect this case and bring the shell | |
2327 * forward. | |
2328 */ | |
2329 int msg = OS.HIWORD (lParam); | |
2330 if (msg is OS.WM_LBUTTONDOWN) { | |
2331 if (!Display.TrimEnabled) { | |
2332 Shell modalShell = display.getModalShell (); | |
2333 if (modalShell !is null && !isActive ()) { | |
2334 auto hwndModal = modalShell.handle; | |
2335 if (OS.IsWindowEnabled (hwndModal)) { | |
2336 OS.SetActiveWindow (hwndModal); | |
2337 } | |
2338 } | |
2339 } | |
2340 if (!OS.IsWindowEnabled (handle)) { | |
2341 static if (!OS.IsWinCE) { | |
2342 auto hwndPopup = OS.GetLastActivePopup (handle); | |
2343 if (hwndPopup !is null && hwndPopup !is handle) { | |
2344 if (display.getControl (hwndPopup) is null) { | |
2345 if (OS.IsWindowEnabled (hwndPopup)) { | |
2346 OS.SetActiveWindow (hwndPopup); | |
2347 } | |
2348 } | |
2349 } | |
2350 } | |
2351 } | |
2352 } | |
2353 /* | |
2354 * When the shell that contains a cursor is disabled, | |
2355 * WM_SETCURSOR is called with HTERROR. Normally, | |
2356 * when a control is disabled, the parent will get | |
2357 * mouse and cursor events. In the case of a disabled | |
2358 * shell, there is no enabled parent. In order to | |
2359 * show the cursor when a shell is disabled, it is | |
2360 * necessary to override WM_SETCURSOR when called | |
2361 * with HTERROR to set the cursor but only when the | |
2362 * mouse is in the client area of the shell. | |
2363 */ | |
2364 int hitTest = cast(short) OS.LOWORD (lParam); | |
2365 if (hitTest is OS.HTERROR) { | |
2366 if (!getEnabled ()) { | |
2367 Control control = display.getControl (cast(HANDLE)wParam); | |
2368 if (control is this && cursor !is null) { | |
2369 POINT pt; | |
2370 int pos = OS.GetMessagePos (); | |
2371 OS.POINTSTOPOINT (pt, pos); | |
2372 OS.ScreenToClient (handle, &pt); | |
2373 RECT rect; | |
2374 OS.GetClientRect (handle, &rect); | |
2375 if (OS.PtInRect (&rect, pt)) { | |
2376 OS.SetCursor (cursor.handle); | |
2377 switch (msg) { | |
2378 case OS.WM_LBUTTONDOWN: | |
2379 case OS.WM_RBUTTONDOWN: | |
2380 case OS.WM_MBUTTONDOWN: | |
2381 case OS.WM_XBUTTONDOWN: | |
2382 OS.MessageBeep (OS.MB_OK); | |
2383 default: | |
2384 } | |
2385 return LRESULT.ONE; | |
2386 } | |
2387 } | |
2388 } | |
2389 } | |
2390 return super.WM_SETCURSOR (wParam, lParam); | |
2391 } | |
2392 | |
2393 override LRESULT WM_SETTINGCHANGE (int wParam, int lParam) { | |
2394 LRESULT result = super.WM_SETTINGCHANGE (wParam, lParam); | |
2395 if (result !is null) return result; | |
2396 static if (OS.IsPPC) { | |
2397 if (wParam is OS.SPI_SETSIPINFO) { | |
2398 /* | |
2399 * The SIP is in a new state. Cache its new value. | |
2400 * Resize the Shell if it has the style SWT.RESIZE. | |
2401 * Note that SHHandleWMSettingChange resizes the | |
2402 * Shell and also updates the cached state. | |
2403 */ | |
2404 if ((style & SWT.RESIZE) !is 0) { | |
2405 OS.SHHandleWMSettingChange (handle, wParam, lParam, psai); | |
2406 return LRESULT.ZERO; | |
2407 } else { | |
2408 SIPINFO pSipInfo; | |
2409 pSipInfo.cbSize = SIPINFO.sizeof; | |
2410 OS.SipGetInfo (&pSipInfo); | |
2411 psai.fSipUp = pSipInfo.fdwFlags & OS.SIPF_ON; | |
2412 } | |
2413 } | |
2414 } | |
2415 return result; | |
2416 } | |
2417 | |
2418 override LRESULT WM_SHOWWINDOW (int wParam, int lParam) { | |
2419 LRESULT result = super.WM_SHOWWINDOW (wParam, lParam); | |
2420 if (result !is null) return result; | |
2421 /* | |
2422 * Bug in Windows. If the shell is hidden while the parent | |
2423 * is iconic, Windows shows the shell when the parent is | |
2424 * deiconified. This does not happen if the shell is hidden | |
2425 * while the parent is not an icon. The fix is to track | |
2426 * visible state for the shell and refuse to show the shell | |
2427 * when the parent is shown. | |
2428 */ | |
2429 if (lParam is OS.SW_PARENTOPENING) { | |
2430 Control control = this; | |
2431 while (control !is null) { | |
2432 Shell shell = control.getShell (); | |
2433 if (!shell.showWithParent) return LRESULT.ZERO; | |
2434 control = control.parent; | |
2435 } | |
2436 } | |
2437 return result; | |
2438 } | |
2439 | |
2440 override LRESULT WM_SYSCOMMAND (int wParam, int lParam) { | |
2441 LRESULT result = super.WM_SYSCOMMAND (wParam, lParam); | |
2442 if (result !is null) return result; | |
2443 /* | |
2444 * Feature in Windows. When the last visible window in | |
2445 * a process minimized, Windows swaps out the memory for | |
2446 * the process. The assumption is that the user can no | |
2447 * longer interact with the window, so the memory can be | |
2448 * released to other applications. However, for programs | |
2449 * that use a lot of memory, swapping the memory back in | |
2450 * can take a long time, sometimes minutes. The fix is | |
2451 * to intercept WM_SYSCOMMAND looking for SC_MINIMIZE | |
2452 * and use ShowWindow() with SW_SHOWMINIMIZED to minimize | |
2453 * the window, rather than running the default window proc. | |
2454 * | |
2455 * NOTE: The default window proc activates the next | |
2456 * top-level window in the Z-order while ShowWindow() | |
2457 * with SW_SHOWMINIMIZED does not. There is no fix for | |
2458 * this at this time. | |
2459 */ | |
2460 if (OS.IsWinNT) { | |
2461 int cmd = wParam & 0xFFF0; | |
2462 switch (cmd) { | |
2463 case OS.SC_MINIMIZE: | |
2464 long memory = RuntimeTotalMemory (); | |
2465 if (memory >= 32 * 1024 * 1024) { | |
2466 OS.ShowWindow (handle, OS.SW_SHOWMINIMIZED); | |
2467 return LRESULT.ZERO; | |
2468 } | |
2469 default: | |
2470 } | |
2471 } | |
2472 return result; | |
2473 } | |
2474 | |
2475 override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { | |
2476 LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam); | |
2477 if (result !is null) return result; | |
2478 auto lpwp = cast(WINDOWPOS*)lParam; | |
2479 //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof); | |
2480 if ((lpwp.flags & OS.SWP_NOSIZE) is 0) { | |
2481 lpwp.cx = Math.max (lpwp.cx, minWidth); | |
2482 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX; | |
2483 if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) { | |
2484 lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK)); | |
2485 } | |
2486 lpwp.cy = Math.max (lpwp.cy, minHeight); | |
2487 if ((style & SWT.NO_TRIM) is 0 && (style & trim) !is 0) { | |
2488 if ((style & SWT.RESIZE) !is 0) { | |
2489 lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK)); | |
2490 } else { | |
2491 RECT rect; | |
2492 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
2493 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
2494 OS.AdjustWindowRectEx (&rect, bits1, false, bits2); | |
2495 lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top); | |
2496 } | |
2497 } | |
2498 //OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof); | |
2499 } | |
2500 return result; | |
2501 } | |
2502 } | |
2503 |