Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Decorations.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.Decorations; | |
14 | |
15 | |
16 import org.eclipse.swt.SWT; | |
17 import org.eclipse.swt.SWTException; | |
18 import org.eclipse.swt.graphics.Image; | |
19 import org.eclipse.swt.graphics.ImageData; | |
20 import org.eclipse.swt.graphics.Point; | |
21 import org.eclipse.swt.graphics.Rectangle; | |
22 import org.eclipse.swt.internal.win32.OS; | |
23 | |
24 import org.eclipse.swt.widgets.Canvas; | |
25 import org.eclipse.swt.widgets.Menu; | |
26 import org.eclipse.swt.widgets.Control; | |
27 import org.eclipse.swt.widgets.Button; | |
28 import org.eclipse.swt.widgets.Composite; | |
29 import org.eclipse.swt.widgets.Event; | |
30 import org.eclipse.swt.widgets.Shell; | |
31 import org.eclipse.swt.widgets.MenuItem; | |
32 import org.eclipse.swt.widgets.Display; | |
33 | |
34 import java.lang.all; | |
35 | |
36 /** | |
37 * Instances of this class provide the appearance and | |
38 * behavior of <code>Shells</code>, but are not top | |
39 * level shells or dialogs. Class <code>Shell</code> | |
40 * shares a significant amount of code with this class, | |
41 * and is a subclass. | |
42 * <p> | |
43 * IMPORTANT: This class was intended to be abstract and | |
44 * should <em>never</em> be referenced or instantiated. | |
45 * Instead, the class <code>Shell</code> should be used. | |
46 * </p> | |
47 * <p> | |
48 * Instances are always displayed in one of the maximized, | |
49 * minimized or normal states: | |
50 * <ul> | |
51 * <li> | |
52 * When an instance is marked as <em>maximized</em>, the | |
53 * window manager will typically resize it to fill the | |
54 * entire visible area of the display, and the instance | |
55 * is usually put in a state where it can not be resized | |
56 * (even if it has style <code>RESIZE</code>) until it is | |
57 * no longer maximized. | |
58 * </li><li> | |
59 * When an instance is in the <em>normal</em> state (neither | |
60 * maximized or minimized), its appearance is controlled by | |
61 * the style constants which were specified when it was created | |
62 * and the restrictions of the window manager (see below). | |
63 * </li><li> | |
64 * When an instance has been marked as <em>minimized</em>, | |
65 * its contents (client area) will usually not be visible, | |
66 * and depending on the window manager, it may be | |
67 * "iconified" (that is, replaced on the desktop by a small | |
68 * simplified representation of itself), relocated to a | |
69 * distinguished area of the screen, or hidden. Combinations | |
70 * of these changes are also possible. | |
71 * </li> | |
72 * </ul> | |
73 * </p> | |
74 * Note: The styles supported by this class must be treated | |
75 * as <em>HINT</em>s, since the window manager for the | |
76 * desktop on which the instance is visible has ultimate | |
77 * control over the appearance and behavior of decorations. | |
78 * For example, some window managers only support resizable | |
79 * windows and will always assume the RESIZE style, even if | |
80 * it is not set. | |
81 * <dl> | |
82 * <dt><b>Styles:</b></dt> | |
83 * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd> | |
84 * <dt><b>Events:</b></dt> | |
85 * <dd>(none)</dd> | |
86 * </dl> | |
87 * Class <code>SWT</code> provides two "convenience constants" | |
88 * for the most commonly required style combinations: | |
89 * <dl> | |
90 * <dt><code>SHELL_TRIM</code></dt> | |
91 * <dd> | |
92 * the result of combining the constants which are required | |
93 * to produce a typical application top level shell: (that | |
94 * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>) | |
95 * </dd> | |
96 * <dt><code>DIALOG_TRIM</code></dt> | |
97 * <dd> | |
98 * the result of combining the constants which are required | |
99 * to produce a typical application dialog shell: (that | |
100 * is, <code>TITLE | CLOSE | BORDER</code>) | |
101 * </dd> | |
102 * </dl> | |
103 * <p> | |
104 * IMPORTANT: This class is intended to be subclassed <em>only</em> | |
105 * within the SWT implementation. | |
106 * </p> | |
107 * | |
108 * @see #getMinimized | |
109 * @see #getMaximized | |
110 * @see Shell | |
111 * @see SWT | |
112 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
113 */ | |
114 | |
115 public class Decorations : Canvas { | |
116 | |
117 alias Canvas.setBounds setBounds; | |
118 alias Canvas.setParent setParent; | |
119 alias Canvas.setSavedFocus setSavedFocus; | |
120 alias Canvas.sort sort; | |
121 alias Canvas.windowProc windowProc; | |
122 | |
123 Image image, smallImage, largeImage; | |
124 Image [] images; | |
125 Menu menuBar; | |
126 Menu [] menus; | |
127 Control savedFocus; | |
128 Button defaultButton, saveDefault; | |
129 int swFlags; | |
130 HACCEL hAccel; | |
131 int nAccel; | |
132 bool moved, resized, opened; | |
133 int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT; | |
134 int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT; | |
135 | |
136 /** | |
137 * Prevents uninitialized instances from being created outside the package. | |
138 */ | |
139 this () { | |
140 } | |
141 | |
142 /** | |
143 * Constructs a new instance of this class given its parent | |
144 * and a style value describing its behavior and appearance. | |
145 * <p> | |
146 * The style value is either one of the style constants defined in | |
147 * class <code>SWT</code> which is applicable to instances of this | |
148 * class, or must be built by <em>bitwise OR</em>'ing together | |
149 * (that is, using the <code>int</code> "|" operator) two or more | |
150 * of those <code>SWT</code> style constants. The class description | |
151 * lists the style constants that are applicable to the class. | |
152 * Style bits are also inherited from superclasses. | |
153 * </p> | |
154 * | |
155 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
156 * @param style the style of control to construct | |
157 * | |
158 * @exception IllegalArgumentException <ul> | |
159 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
160 * </ul> | |
161 * @exception SWTException <ul> | |
162 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
163 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
164 * </ul> | |
165 * | |
166 * @see SWT#BORDER | |
167 * @see SWT#CLOSE | |
168 * @see SWT#MIN | |
169 * @see SWT#MAX | |
170 * @see SWT#RESIZE | |
171 * @see SWT#TITLE | |
172 * @see SWT#NO_TRIM | |
173 * @see SWT#SHELL_TRIM | |
174 * @see SWT#DIALOG_TRIM | |
175 * @see SWT#ON_TOP | |
176 * @see SWT#TOOL | |
177 * @see Widget#checkSubclass | |
178 * @see Widget#getStyle | |
179 */ | |
180 public this (Composite parent, int style) { | |
181 super (parent, checkStyle (style)); | |
182 } | |
183 | |
184 void _setMaximized (bool maximized) { | |
185 swFlags = maximized ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE; | |
186 static if (OS.IsWinCE) { | |
187 /* | |
188 * Note: WinCE does not support SW_SHOWMAXIMIZED and SW_RESTORE. The | |
189 * workaround is to resize the window to fit the parent client area. | |
190 */ | |
191 if (maximized) { | |
192 RECT rect; | |
193 OS.SystemParametersInfo (OS.SPI_GETWORKAREA, 0, &rect, 0); | |
194 int width = rect.right - rect.left, height = rect.bottom - rect.top; | |
195 if (OS.IsPPC) { | |
196 /* Leave space for the menu bar */ | |
197 if (menuBar !is null) { | |
198 auto hwndCB = menuBar.hwndCB; | |
199 RECT rectCB; | |
200 OS.GetWindowRect (hwndCB, &rectCB); | |
201 height -= rectCB.bottom - rectCB.top; | |
202 } | |
203 } | |
204 int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE; | |
205 SetWindowPos (handle, null, rect.left, rect.top, width, height, flags); | |
206 } | |
207 } else { | |
208 if (!OS.IsWindowVisible (handle)) return; | |
209 if (maximized is OS.IsZoomed (handle)) return; | |
210 OS.ShowWindow (handle, swFlags); | |
211 OS.UpdateWindow (handle); | |
212 } | |
213 } | |
214 | |
215 void _setMinimized (bool minimized) { | |
216 static if (OS.IsWinCE) return; | |
217 swFlags = minimized ? OS.SW_SHOWMINNOACTIVE : OS.SW_RESTORE; | |
218 if (!OS.IsWindowVisible (handle)) return; | |
219 if (minimized is OS.IsIconic (handle)) return; | |
220 int flags = swFlags; | |
221 if (flags is OS.SW_SHOWMINNOACTIVE && handle is OS.GetActiveWindow ()) { | |
222 flags = OS.SW_MINIMIZE; | |
223 } | |
224 OS.ShowWindow (handle, flags); | |
225 OS.UpdateWindow (handle); | |
226 } | |
227 | |
228 void addMenu (Menu menu) { | |
229 if (menus is null) menus = new Menu [4]; | |
230 for (int i=0; i<menus.length; i++) { | |
231 if (menus [i] is null) { | |
232 menus [i] = menu; | |
233 return; | |
234 } | |
235 } | |
236 Menu [] newMenus = new Menu [menus.length + 4]; | |
237 newMenus [menus.length] = menu; | |
238 System.arraycopy (menus, 0, newMenus, 0, menus.length); | |
239 menus = newMenus; | |
240 } | |
241 | |
242 void bringToTop () { | |
243 /* | |
244 * This code is intentionally commented. On some platforms, | |
245 * the ON_TOP style creates a shell that will stay on top | |
246 * of every other shell on the desktop. Using SetWindowPos () | |
247 * with HWND_TOP caused problems on Windows 98 so this code is | |
248 * commented out until this functionality is specified and | |
249 * the problems are fixed. | |
250 */ | |
251 // if ((style & SWT.ON_TOP) !is 0) { | |
252 // int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; | |
253 // OS.SetWindowPos (handle, OS.HWND_TOP, 0, 0, 0, 0, flags); | |
254 // } else { | |
255 OS.BringWindowToTop (handle); | |
256 // widget could be disposed at this point | |
257 // } | |
258 } | |
259 | |
260 static int checkStyle (int style) { | |
261 if ((style & SWT.NO_TRIM) !is 0) { | |
262 style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER); | |
263 } | |
264 static if (OS.IsWinCE) { | |
265 /* | |
266 * Feature in WinCE PPC. WS_MINIMIZEBOX or WS_MAXIMIZEBOX | |
267 * are not supposed to be used. If they are, the result | |
268 * is a button which does not repaint correctly. The fix | |
269 * is to remove this style. | |
270 */ | |
271 if ((style & SWT.MIN) !is 0) style &= ~SWT.MIN; | |
272 if ((style & SWT.MAX) !is 0) style &= ~SWT.MAX; | |
273 return style; | |
274 } | |
275 if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) !is 0) { | |
276 style |= SWT.TITLE; | |
277 } | |
278 | |
279 /* | |
280 * If either WS_MINIMIZEBOX or WS_MAXIMIZEBOX are set, | |
281 * we must also set WS_SYSMENU or the buttons will not | |
282 * appear. | |
283 */ | |
284 if ((style & (SWT.MIN | SWT.MAX)) !is 0) style |= SWT.CLOSE; | |
285 | |
286 /* | |
287 * Both WS_SYSMENU and WS_CAPTION must be set in order | |
288 * to for the system menu to appear. | |
289 */ | |
290 if ((style & SWT.CLOSE) !is 0) style |= SWT.TITLE; | |
291 | |
292 /* | |
293 * Bug in Windows. The WS_CAPTION style must be | |
294 * set when the window is resizable or it does not | |
295 * draw properly. | |
296 */ | |
297 /* | |
298 * This code is intentionally commented. It seems | |
299 * that this problem originally in Windows 3.11, | |
300 * has been fixed in later versions. Because the | |
301 * exact nature of the drawing problem is unknown, | |
302 * keep the commented code around in case it comes | |
303 * back. | |
304 */ | |
305 // if ((style & SWT.RESIZE) !is 0) style |= SWT.TITLE; | |
306 | |
307 return style; | |
308 } | |
309 | |
310 override void checkBorder () { | |
311 /* Do nothing */ | |
312 } | |
313 | |
314 void checkComposited (Composite parent) { | |
315 /* Do nothing */ | |
316 } | |
317 | |
318 override void checkOpened () { | |
319 if (!opened) resized = false; | |
320 } | |
321 | |
322 override protected void checkSubclass () { | |
323 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); | |
324 } | |
325 | |
326 override override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
327 if (handle is null) return 0; | |
328 return OS.DefMDIChildProc (hwnd, msg, wParam, lParam); | |
329 } | |
330 | |
331 void closeWidget () { | |
332 Event event = new Event (); | |
333 sendEvent (SWT.Close, event); | |
334 if (event.doit && !isDisposed ()) dispose (); | |
335 } | |
336 | |
337 int compare (ImageData data1, ImageData data2, int width, int height, int depth) { | |
338 int value1 = Math.abs (data1.width - width), value2 = Math.abs (data2.width - width); | |
339 if (value1 is value2) { | |
340 int transparent1 = data1.getTransparencyType (); | |
341 int transparent2 = data2.getTransparencyType (); | |
342 if (transparent1 is transparent2) { | |
343 if (data1.depth is data2.depth) return 0; | |
344 return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1; | |
345 } | |
346 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { | |
347 if (transparent1 is SWT.TRANSPARENCY_ALPHA) return -1; | |
348 if (transparent2 is SWT.TRANSPARENCY_ALPHA) return 1; | |
349 } | |
350 if (transparent1 is SWT.TRANSPARENCY_MASK) return -1; | |
351 if (transparent2 is SWT.TRANSPARENCY_MASK) return 1; | |
352 if (transparent1 is SWT.TRANSPARENCY_PIXEL) return -1; | |
353 if (transparent2 is SWT.TRANSPARENCY_PIXEL) return 1; | |
354 return 0; | |
355 } | |
356 return value1 < value2 ? -1 : 1; | |
357 } | |
358 | |
359 override Control computeTabGroup () { | |
360 return this; | |
361 } | |
362 | |
363 override Control computeTabRoot () { | |
364 return this; | |
365 } | |
366 | |
367 override public Rectangle computeTrim (int x, int y, int width, int height) { | |
368 checkWidget (); | |
369 | |
370 /* Get the size of the trimmings */ | |
371 RECT rect; | |
372 OS.SetRect (&rect, x, y, x + width, y + height); | |
373 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
374 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
375 bool hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) !is null; | |
376 OS.AdjustWindowRectEx (&rect, bits1, hasMenu, bits2); | |
377 | |
378 /* Get the size of the scroll bars */ | |
379 if (horizontalBar !is null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL); | |
380 if (verticalBar !is null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL); | |
381 | |
382 /* Compute the height of the menu bar */ | |
383 if (hasMenu) { | |
384 RECT testRect; | |
385 OS.SetRect (&testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top); | |
386 OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &testRect); | |
387 while ((testRect.bottom - testRect.top) < height) { | |
388 if (testRect.bottom - testRect.top is 0) break; | |
389 rect.top -= OS.GetSystemMetrics (OS.SM_CYMENU) - OS.GetSystemMetrics (OS.SM_CYBORDER); | |
390 OS.SetRect (&testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top); | |
391 OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, &testRect); | |
392 } | |
393 } | |
394 return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); | |
395 } | |
396 | |
397 void createAccelerators () { | |
398 hAccel = null; | |
399 nAccel = 0; | |
400 int maxAccel = 0; | |
401 MenuItem [] items = display.items; | |
402 if (menuBar is null || items is null) { | |
403 if (!OS.IsPPC) return; | |
404 maxAccel = 1; | |
405 } else { | |
406 maxAccel = OS.IsPPC ? items.length + 1 : items.length; | |
407 } | |
408 ACCEL accel; | |
409 byte [] buffer1 = new byte [ACCEL.sizeof]; | |
410 byte [] buffer2 = new byte [maxAccel * ACCEL.sizeof]; | |
411 if (menuBar !is null && items !is null) { | |
412 for (int i=0; i<items.length; i++) { | |
413 MenuItem item = items [i]; | |
414 if (item !is null && item.accelerator !is 0) { | |
415 Menu menu = item.parent; | |
416 if (menu.parent is this) { | |
417 while (menu !is null && menu !is menuBar) { | |
418 menu = menu.getParentMenu (); | |
419 } | |
420 if (menu is menuBar && item.fillAccel (&accel)) { | |
421 *cast(ACCEL*)buffer1.ptr = accel; | |
422 //OS.MoveMemory (buffer1, accel, ACCEL.sizeof); | |
423 System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof); | |
424 nAccel++; | |
425 } | |
426 } | |
427 } | |
428 } | |
429 } | |
430 if (OS.IsPPC) { | |
431 /* | |
432 * Note on WinCE PPC. Close the shell when user taps CTRL-Q. | |
433 * IDOK represents the "Done Button" which also closes the shell. | |
434 */ | |
435 accel.fVirt = cast(byte) (OS.FVIRTKEY | OS.FCONTROL); | |
436 accel.key = cast(short) 'Q'; | |
437 accel.cmd = cast(short) OS.IDOK; | |
438 *cast(ACCEL*)buffer1.ptr = accel; | |
439 //OS.MoveMemory (buffer1, accel, ACCEL.sizeof); | |
440 System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof); | |
441 nAccel++; | |
442 } | |
443 if (nAccel !is 0) hAccel = OS.CreateAcceleratorTable ( cast(ACCEL*)buffer2.ptr, nAccel); | |
444 } | |
445 | |
446 override void createHandle () { | |
447 super.createHandle (); | |
448 if (parent !is null || ((style & SWT.TOOL) !is 0)) { | |
449 setParent (); | |
450 setSystemMenu (); | |
451 } | |
452 } | |
453 | |
454 override void createWidget () { | |
455 super.createWidget (); | |
456 swFlags = OS.IsWinCE ? OS.SW_SHOWMAXIMIZED : OS.SW_SHOWNOACTIVATE; | |
457 hAccel = cast(HACCEL)-1; | |
458 } | |
459 | |
460 void destroyAccelerators () { | |
461 if (hAccel !is null && hAccel !is cast(HACCEL)-1) OS.DestroyAcceleratorTable (hAccel); | |
462 hAccel = cast(HACCEL)-1; | |
463 } | |
464 | |
465 override public void dispose () { | |
466 if (isDisposed()) return; | |
467 if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); | |
468 if (!(cast(Shell)this)) { | |
469 if (!traverseDecorations (true)) { | |
470 Shell shell = getShell (); | |
471 shell.setFocus (); | |
472 } | |
473 setVisible (false); | |
474 } | |
475 super.dispose (); | |
476 } | |
477 | |
478 Menu findMenu (HMENU hMenu) { | |
479 if (menus is null) return null; | |
480 for (int i=0; i<menus.length; i++) { | |
481 Menu menu = menus [i]; | |
482 if (menu !is null && hMenu is menu.handle) return menu; | |
483 } | |
484 return null; | |
485 } | |
486 | |
487 void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) { | |
488 if (this is newDecorations) return; | |
489 if (control is savedFocus) savedFocus = null; | |
490 if (control is defaultButton) defaultButton = null; | |
491 if (control is saveDefault) saveDefault = null; | |
492 if (menus is null) return; | |
493 Menu menu = control.menu; | |
494 if (menu !is null) { | |
495 int index = 0; | |
496 while (index <menus.length) { | |
497 if (menus [index] is menu) { | |
498 control.setMenu (null); | |
499 return; | |
500 } | |
501 index++; | |
502 } | |
503 menu.fixMenus (newDecorations); | |
504 destroyAccelerators (); | |
505 newDecorations.destroyAccelerators (); | |
506 } | |
507 } | |
508 | |
509 override public Rectangle getBounds () { | |
510 checkWidget (); | |
511 static if (!OS.IsWinCE) { | |
512 if (OS.IsIconic (handle)) { | |
513 WINDOWPLACEMENT lpwndpl; | |
514 lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
515 OS.GetWindowPlacement (handle, &lpwndpl); | |
516 int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left; | |
517 int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top; | |
518 return new Rectangle (lpwndpl.rcNormalPosition.left, lpwndpl.rcNormalPosition.top, width, height); | |
519 } | |
520 } | |
521 return super.getBounds (); | |
522 } | |
523 | |
524 override public Rectangle getClientArea () { | |
525 checkWidget (); | |
526 /* | |
527 * Note: The CommandBar is part of the client area, | |
528 * not the trim. Applications don't expect this so | |
529 * subtract the height of the CommandBar. | |
530 */ | |
531 static if (OS.IsHPC) { | |
532 Rectangle rect = super.getClientArea (); | |
533 if (menuBar !is null) { | |
534 auto hwndCB = menuBar.hwndCB; | |
535 int height = OS.CommandBar_Height (hwndCB); | |
536 rect.y += height; | |
537 rect.height = Math.max (0, rect.height - height); | |
538 } | |
539 return rect; | |
540 } | |
541 static if (!OS.IsWinCE) { | |
542 if (OS.IsIconic (handle)) { | |
543 WINDOWPLACEMENT lpwndpl; | |
544 lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
545 OS.GetWindowPlacement (handle, &lpwndpl); | |
546 int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left; | |
547 int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top; | |
548 /* | |
549 * Feature in Windows. For some reason WM_NCCALCSIZE does | |
550 * not compute the client area when the window is minimized. | |
551 * The fix is to compute it using AdjustWindowRectEx() and | |
552 * GetSystemMetrics(). | |
553 * | |
554 * NOTE: This code fails to compute the correct client area | |
555 * for a minimized window where the menu bar would wrap were | |
556 * the window restored. There is no fix for this problem at | |
557 * this time. | |
558 */ | |
559 if (horizontalBar !is null) width -= OS.GetSystemMetrics (OS.SM_CYHSCROLL); | |
560 if (verticalBar !is null) height -= OS.GetSystemMetrics (OS.SM_CXVSCROLL); | |
561 RECT rect; | |
562 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
563 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); | |
564 bool hasMenu = OS.IsWinCE ? false : OS.GetMenu (handle) !is null; | |
565 OS.AdjustWindowRectEx (&rect, bits1, hasMenu, bits2); | |
566 width = Math.max (0, width - (rect.right - rect.left)); | |
567 height = Math.max (0, height - (rect.bottom - rect.top)); | |
568 return new Rectangle (0, 0, width, height); | |
569 } | |
570 } | |
571 return super.getClientArea (); | |
572 } | |
573 | |
574 /** | |
575 * Returns the receiver's default button if one had | |
576 * previously been set, otherwise returns null. | |
577 * | |
578 * @return the default button or null | |
579 * | |
580 * @exception SWTException <ul> | |
581 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
582 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
583 * </ul> | |
584 * | |
585 * @see #setDefaultButton(Button) | |
586 */ | |
587 public Button getDefaultButton () { | |
588 checkWidget (); | |
589 return defaultButton; | |
590 } | |
591 | |
592 /** | |
593 * Returns the receiver's image if it had previously been | |
594 * set using <code>setImage()</code>. The image is typically | |
595 * displayed by the window manager when the instance is | |
596 * marked as iconified, and may also be displayed somewhere | |
597 * in the trim when the instance is in normal or maximized | |
598 * states. | |
599 * <p> | |
600 * Note: This method will return null if called before | |
601 * <code>setImage()</code> is called. It does not provide | |
602 * access to a window manager provided, "default" image | |
603 * even if one exists. | |
604 * </p> | |
605 * | |
606 * @return the image | |
607 * | |
608 * @exception SWTException <ul> | |
609 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
610 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
611 * </ul> | |
612 */ | |
613 public Image getImage () { | |
614 checkWidget (); | |
615 return image; | |
616 } | |
617 | |
618 /** | |
619 * Returns the receiver's images if they had previously been | |
620 * set using <code>setImages()</code>. Images are typically | |
621 * displayed by the window manager when the instance is | |
622 * marked as iconified, and may also be displayed somewhere | |
623 * in the trim when the instance is in normal or maximized | |
624 * states. Depending where the icon is displayed, the platform | |
625 * chooses the icon with the "best" attributes. It is expected | |
626 * that the array will contain the same icon rendered at different | |
627 * sizes, with different depth and transparency attributes. | |
628 * | |
629 * <p> | |
630 * Note: This method will return an empty array if called before | |
631 * <code>setImages()</code> is called. It does not provide | |
632 * access to a window manager provided, "default" image | |
633 * even if one exists. | |
634 * </p> | |
635 * | |
636 * @return the images | |
637 * | |
638 * @exception SWTException <ul> | |
639 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
640 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
641 * </ul> | |
642 * | |
643 * @since 3.0 | |
644 */ | |
645 public Image [] getImages () { | |
646 checkWidget (); | |
647 if (images is null) return new Image [0]; | |
648 Image [] result = new Image [images.length]; | |
649 System.arraycopy (images, 0, result, 0, images.length); | |
650 return result; | |
651 } | |
652 | |
653 override public Point getLocation () { | |
654 checkWidget (); | |
655 static if (!OS.IsWinCE) { | |
656 if (OS.IsIconic (handle)) { | |
657 WINDOWPLACEMENT lpwndpl; | |
658 lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
659 OS.GetWindowPlacement (handle, &lpwndpl); | |
660 return new Point (lpwndpl.rcNormalPosition.left, lpwndpl.rcNormalPosition.top); | |
661 } | |
662 } | |
663 return super.getLocation (); | |
664 } | |
665 | |
666 /** | |
667 * Returns <code>true</code> if the receiver is currently | |
668 * maximized, and false otherwise. | |
669 * <p> | |
670 * | |
671 * @return the maximized state | |
672 * | |
673 * @exception SWTException <ul> | |
674 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
675 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
676 * </ul> | |
677 * | |
678 * @see #setMaximized | |
679 */ | |
680 public bool getMaximized () { | |
681 checkWidget (); | |
682 static if (OS.IsWinCE) return swFlags is OS.SW_SHOWMAXIMIZED; | |
683 if (OS.IsWindowVisible (handle)) return cast(bool) OS.IsZoomed (handle); | |
684 return swFlags is OS.SW_SHOWMAXIMIZED; | |
685 } | |
686 | |
687 /** | |
688 * Returns the receiver's menu bar if one had previously | |
689 * been set, otherwise returns null. | |
690 * | |
691 * @return the menu bar or null | |
692 * | |
693 * @exception SWTException <ul> | |
694 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
695 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
696 * </ul> | |
697 */ | |
698 public Menu getMenuBar () { | |
699 checkWidget (); | |
700 return menuBar; | |
701 } | |
702 | |
703 /** | |
704 * Returns <code>true</code> if the receiver is currently | |
705 * minimized, and false otherwise. | |
706 * <p> | |
707 * | |
708 * @return the minimized state | |
709 * | |
710 * @exception SWTException <ul> | |
711 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
712 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
713 * </ul> | |
714 * | |
715 * @see #setMinimized | |
716 */ | |
717 public bool getMinimized () { | |
718 checkWidget (); | |
719 static if (OS.IsWinCE) return false; | |
720 if (OS.IsWindowVisible (handle)) return cast(bool) OS.IsIconic (handle); | |
721 return swFlags is OS.SW_SHOWMINNOACTIVE; | |
722 } | |
723 | |
724 override String getNameText () { | |
725 return getText (); | |
726 } | |
727 | |
728 override public Point getSize () { | |
729 checkWidget (); | |
730 static if (!OS.IsWinCE) { | |
731 if (OS.IsIconic (handle)) { | |
732 WINDOWPLACEMENT lpwndpl; | |
733 lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
734 OS.GetWindowPlacement (handle, &lpwndpl); | |
735 int width = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left; | |
736 int height = lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top; | |
737 return new Point (width, height); | |
738 } | |
739 } | |
740 return super.getSize (); | |
741 } | |
742 | |
743 /** | |
744 * Returns the receiver's text, which is the string that the | |
745 * window manager will typically display as the receiver's | |
746 * <em>title</em>. If the text has not previously been set, | |
747 * returns an empty string. | |
748 * | |
749 * @return the text | |
750 * | |
751 * @exception SWTException <ul> | |
752 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
753 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
754 * </ul> | |
755 */ | |
756 public String getText () { | |
757 checkWidget (); | |
758 int length = OS.GetWindowTextLength (handle); | |
759 if (length is 0) return ""; | |
760 /* Use the character encoding for the default locale */ | |
761 TCHAR[] buffer; | |
762 buffer.length = length + 1; | |
763 OS.GetWindowText (handle, buffer.ptr, length + 1); | |
764 return TCHARsToStr( buffer ); | |
765 } | |
766 | |
767 override public bool isReparentable () { | |
768 checkWidget (); | |
769 /* | |
770 * Feature in Windows. Calling SetParent() for a shell causes | |
771 * a kind of fake MDI to happen. It doesn't work well on Windows | |
772 * and is not supported on the other platforms. The fix is to | |
773 * disallow the SetParent(). | |
774 */ | |
775 return false; | |
776 } | |
777 | |
778 override bool isTabGroup () { | |
779 /* | |
780 * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX. | |
781 */ | |
782 return true; | |
783 } | |
784 | |
785 override bool isTabItem () { | |
786 /* | |
787 * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX. | |
788 */ | |
789 return false; | |
790 } | |
791 | |
792 override Decorations menuShell () { | |
793 return this; | |
794 } | |
795 | |
796 override void releaseChildren (bool destroy) { | |
797 if (menuBar !is null) { | |
798 menuBar.release (false); | |
799 menuBar = null; | |
800 } | |
801 super.releaseChildren (destroy); | |
802 if (menus !is null) { | |
803 for (int i=0; i<menus.length; i++) { | |
804 Menu menu = menus [i]; | |
805 if (menu !is null && !menu.isDisposed ()) { | |
806 menu.dispose (); | |
807 } | |
808 } | |
809 menus = null; | |
810 } | |
811 } | |
812 | |
813 override void releaseWidget () { | |
814 super.releaseWidget (); | |
815 if (smallImage !is null) smallImage.dispose (); | |
816 if (largeImage !is null) largeImage.dispose (); | |
817 smallImage = largeImage = image = null; | |
818 images = null; | |
819 savedFocus = null; | |
820 defaultButton = saveDefault = null; | |
821 if (hAccel !is null && hAccel !is cast(HACCEL)-1) OS.DestroyAcceleratorTable (hAccel); | |
822 hAccel = cast(HACCEL)-1; | |
823 } | |
824 | |
825 void removeMenu (Menu menu) { | |
826 if (menus is null) return; | |
827 for (int i=0; i<menus.length; i++) { | |
828 if (menus [i] is menu) { | |
829 menus [i] = null; | |
830 return; | |
831 } | |
832 } | |
833 } | |
834 | |
835 bool restoreFocus () { | |
836 if (display.ignoreRestoreFocus) return true; | |
837 if (savedFocus !is null && savedFocus.isDisposed ()) savedFocus = null; | |
838 if (savedFocus !is null && savedFocus.setSavedFocus ()) return true; | |
839 /* | |
840 * This code is intentionally commented. When no widget | |
841 * has been given focus, some platforms give focus to the | |
842 * default button. Windows doesn't do this. | |
843 */ | |
844 // if (defaultButton !is null && !defaultButton.isDisposed ()) { | |
845 // if (defaultButton.setFocus ()) return true; | |
846 // } | |
847 return false; | |
848 } | |
849 | |
850 void saveFocus () { | |
851 Control control = display._getFocusControl (); | |
852 if (control !is null && control !is this && this is control.menuShell ()) { | |
853 setSavedFocus (control); | |
854 } | |
855 } | |
856 | |
857 override void setBounds (int x, int y, int width, int height, int flags, bool defer) { | |
858 static if (OS.IsWinCE) { | |
859 swFlags = OS.SW_RESTORE; | |
860 } else { | |
861 if (OS.IsIconic (handle)) { | |
862 setPlacement (x, y, width, height, flags); | |
863 return; | |
864 } | |
865 } | |
866 forceResize (); | |
867 RECT rect; | |
868 OS.GetWindowRect (handle, &rect); | |
869 bool sameOrigin = true; | |
870 if ((OS.SWP_NOMOVE & flags) is 0) { | |
871 sameOrigin = rect.left is x && rect.top is y; | |
872 if (!sameOrigin) moved = true; | |
873 } | |
874 bool sameExtent = true; | |
875 if ((OS.SWP_NOSIZE & flags) is 0) { | |
876 sameExtent = rect.right - rect.left is width && rect.bottom - rect.top is height; | |
877 if (!sameExtent) resized = true; | |
878 } | |
879 static if (!OS.IsWinCE) { | |
880 if (OS.IsZoomed (handle)) { | |
881 if (sameOrigin && sameExtent) return; | |
882 setPlacement (x, y, width, height, flags); | |
883 _setMaximized (false); | |
884 return; | |
885 } | |
886 } | |
887 super.setBounds (x, y, width, height, flags, defer); | |
888 } | |
889 | |
890 /** | |
891 * If the argument is not null, sets the receiver's default | |
892 * button to the argument, and if the argument is null, sets | |
893 * the receiver's default button to the first button which | |
894 * was set as the receiver's default button (called the | |
895 * <em>saved default button</em>). If no default button had | |
896 * previously been set, or the saved default button was | |
897 * disposed, the receiver's default button will be set to | |
898 * null. | |
899 * <p> | |
900 * The default button is the button that is selected when | |
901 * the receiver is active and the user presses ENTER. | |
902 * </p> | |
903 * | |
904 * @param button the new default button | |
905 * | |
906 * @exception IllegalArgumentException <ul> | |
907 * <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li> | |
908 * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li> | |
909 * </ul> | |
910 * @exception SWTException <ul> | |
911 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
912 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
913 * </ul> | |
914 */ | |
915 public void setDefaultButton (Button button) { | |
916 checkWidget (); | |
917 if (button !is null) { | |
918 if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); | |
919 if (button.menuShell () !is this) error(SWT.ERROR_INVALID_PARENT); | |
920 } | |
921 setDefaultButton (button, true); | |
922 } | |
923 | |
924 void setDefaultButton (Button button, bool save) { | |
925 if (button is null) { | |
926 if (defaultButton is saveDefault) { | |
927 if (save) saveDefault = null; | |
928 return; | |
929 } | |
930 } else { | |
931 if ((button.style & SWT.PUSH) is 0) return; | |
932 if (button is defaultButton) return; | |
933 } | |
934 if (defaultButton !is null) { | |
935 if (!defaultButton.isDisposed ()) defaultButton.setDefault (false); | |
936 } | |
937 if ((defaultButton = button) is null) defaultButton = saveDefault; | |
938 if (defaultButton !is null) { | |
939 if (!defaultButton.isDisposed ()) defaultButton.setDefault (true); | |
940 } | |
941 if (save) saveDefault = defaultButton; | |
942 if (saveDefault !is null && saveDefault.isDisposed ()) saveDefault = null; | |
943 } | |
944 | |
945 /** | |
946 * Sets the receiver's image to the argument, which may | |
947 * be null. The image is typically displayed by the window | |
948 * manager when the instance is marked as iconified, and | |
949 * may also be displayed somewhere in the trim when the | |
950 * instance is in normal or maximized states. | |
951 * | |
952 * @param image the new image (or null) | |
953 * | |
954 * @exception IllegalArgumentException <ul> | |
955 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> | |
956 * </ul> | |
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 public void setImage (Image image) { | |
963 checkWidget (); | |
964 if (image !is null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); | |
965 this.image = image; | |
966 setImages (image, null); | |
967 } | |
968 | |
969 void setImages (Image image, Image [] images) { | |
970 /* | |
971 * Feature in WinCE. WM_SETICON and WM_GETICON set the icon | |
972 * for the window class, not the window instance. This means | |
973 * that it is possible to set an icon into a window and then | |
974 * later free the icon, thus freeing the icon for every window. | |
975 * The fix is to avoid the API. | |
976 * | |
977 * On WinCE PPC, icons in windows are not displayed. | |
978 */ | |
979 static if (OS.IsWinCE) return; | |
980 if (smallImage !is null) smallImage.dispose (); | |
981 if (largeImage !is null) largeImage.dispose (); | |
982 smallImage = largeImage = null; | |
983 HICON hSmallIcon, hLargeIcon; | |
984 Image smallIcon = null, largeIcon = null; | |
985 if (image !is null) { | |
986 smallIcon = largeIcon = image; | |
987 } else { | |
988 if (images !is null && images.length > 0) { | |
989 int depth = display.getIconDepth (); | |
990 ImageData [] datas = null; | |
991 if (images.length > 1) { | |
992 Image [] bestImages = new Image [images.length]; | |
993 System.arraycopy (images, 0, bestImages, 0, images.length); | |
994 datas = new ImageData [images.length]; | |
995 for (int i=0; i<datas.length; i++) { | |
996 datas [i] = images [i].getImageData (); | |
997 } | |
998 images = bestImages; | |
999 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON), depth); | |
1000 } | |
1001 smallIcon = images [0]; | |
1002 if (images.length > 1) { | |
1003 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON), depth); | |
1004 } | |
1005 largeIcon = images [0]; | |
1006 } | |
1007 } | |
1008 if (smallIcon !is null) { | |
1009 switch (smallIcon.type) { | |
1010 case SWT.BITMAP: | |
1011 smallImage = Display.createIcon (smallIcon); | |
1012 hSmallIcon = smallImage.handle; | |
1013 break; | |
1014 case SWT.ICON: | |
1015 hSmallIcon = smallIcon.handle; | |
1016 break; | |
1017 default: | |
1018 } | |
1019 } | |
1020 OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_SMALL, hSmallIcon); | |
1021 if (largeIcon !is null) { | |
1022 switch (largeIcon.type) { | |
1023 case SWT.BITMAP: | |
1024 largeImage = Display.createIcon (largeIcon); | |
1025 hLargeIcon = largeImage.handle; | |
1026 break; | |
1027 case SWT.ICON: | |
1028 hLargeIcon = largeIcon.handle; | |
1029 break; | |
1030 default: | |
1031 } | |
1032 } | |
1033 OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_BIG, hLargeIcon); | |
1034 | |
1035 /* | |
1036 * Bug in Windows. When WM_SETICON is used to remove an | |
1037 * icon from the window trimmings for a window with the | |
1038 * extended style bits WS_EX_DLGMODALFRAME, the window | |
1039 * trimmings do not redraw to hide the previous icon. | |
1040 * The fix is to force a redraw. | |
1041 */ | |
1042 static if (!OS.IsWinCE) { | |
1043 if (hSmallIcon is null && hLargeIcon is null && (style & SWT.BORDER) !is 0) { | |
1044 int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE; | |
1045 OS.RedrawWindow (handle, null, null, flags); | |
1046 } | |
1047 } | |
1048 } | |
1049 | |
1050 /** | |
1051 * Sets the receiver's images to the argument, which may | |
1052 * be an empty array. Images are typically displayed by the | |
1053 * window manager when the instance is marked as iconified, | |
1054 * and may also be displayed somewhere in the trim when the | |
1055 * instance is in normal or maximized states. Depending where | |
1056 * the icon is displayed, the platform chooses the icon with | |
1057 * the "best" attributes. It is expected that the array will | |
1058 * contain the same icon rendered at different sizes, with | |
1059 * different depth and transparency attributes. | |
1060 * | |
1061 * @param images the new image array | |
1062 * | |
1063 * @exception IllegalArgumentException <ul> | |
1064 * <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</li> | |
1065 * </ul> | |
1066 * @exception SWTException <ul> | |
1067 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1068 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1069 * </ul> | |
1070 * | |
1071 * @since 3.0 | |
1072 */ | |
1073 public void setImages (Image [] images) { | |
1074 checkWidget (); | |
1075 // SWT extension: allow null array | |
1076 //if (images is null) error (SWT.ERROR_INVALID_ARGUMENT); | |
1077 for (int i = 0; i < images.length; i++) { | |
1078 if (images [i] is null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT); | |
1079 } | |
1080 this.images = images; | |
1081 setImages (null, images); | |
1082 } | |
1083 | |
1084 /** | |
1085 * Sets the maximized state of the receiver. | |
1086 * If the argument is <code>true</code> causes the receiver | |
1087 * to switch to the maximized state, and if the argument is | |
1088 * <code>false</code> and the receiver was previously maximized, | |
1089 * causes the receiver to switch back to either the minimized | |
1090 * or normal states. | |
1091 * <p> | |
1092 * Note: The result of intermixing calls to <code>setMaximized(true)</code> | |
1093 * and <code>setMinimized(true)</code> will vary by platform. Typically, | |
1094 * the behavior will match the platform user's expectations, but not | |
1095 * always. This should be avoided if possible. | |
1096 * </p> | |
1097 * | |
1098 * @param maximized the new maximized state | |
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 * @see #setMinimized | |
1106 */ | |
1107 public void setMaximized (bool maximized) { | |
1108 checkWidget (); | |
1109 Display.lpStartupInfo = null; | |
1110 _setMaximized (maximized); | |
1111 } | |
1112 | |
1113 /** | |
1114 * Sets the receiver's menu bar to the argument, which | |
1115 * may be null. | |
1116 * | |
1117 * @param menu the new menu bar | |
1118 * | |
1119 * @exception IllegalArgumentException <ul> | |
1120 * <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li> | |
1121 * <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li> | |
1122 * </ul> | |
1123 * @exception SWTException <ul> | |
1124 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1125 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1126 * </ul> | |
1127 */ | |
1128 public void setMenuBar (Menu menu) { | |
1129 checkWidget (); | |
1130 if (menuBar is menu) return; | |
1131 if (menu !is null) { | |
1132 if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); | |
1133 if ((menu.style & SWT.BAR) is 0) error (SWT.ERROR_MENU_NOT_BAR); | |
1134 if (menu.parent !is this) error (SWT.ERROR_INVALID_PARENT); | |
1135 } | |
1136 static if (OS.IsWinCE) { | |
1137 if (OS.IsHPC) { | |
1138 bool resize = menuBar !is menu; | |
1139 if (menuBar !is null) OS.CommandBar_Show (menuBar.hwndCB, false); | |
1140 menuBar = menu; | |
1141 if (menuBar !is null) OS.CommandBar_Show (menuBar.hwndCB, true); | |
1142 if (resize) { | |
1143 sendEvent (SWT.Resize); | |
1144 if (isDisposed ()) return; | |
1145 if (layout !is null) { | |
1146 markLayout (false, false); | |
1147 updateLayout (true, false); | |
1148 } | |
1149 } | |
1150 } else { | |
1151 if (OS.IsPPC) { | |
1152 /* | |
1153 * Note in WinCE PPC. The menu bar is a separate popup window. | |
1154 * If the shell is full screen, resize its window to leave | |
1155 * space for the menu bar. | |
1156 */ | |
1157 bool resize = getMaximized () && menuBar !is menu; | |
1158 if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE); | |
1159 menuBar = menu; | |
1160 if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW); | |
1161 if (resize) _setMaximized (true); | |
1162 } | |
1163 if (OS.IsSP) { | |
1164 if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_HIDE); | |
1165 menuBar = menu; | |
1166 if (menuBar !is null) OS.ShowWindow (menuBar.hwndCB, OS.SW_SHOW); | |
1167 } | |
1168 } | |
1169 } else { | |
1170 if (menu !is null) display.removeBar (menu); | |
1171 menuBar = menu; | |
1172 auto hMenu = menuBar !is null ? menuBar.handle: null; | |
1173 OS.SetMenu (handle, hMenu); | |
1174 } | |
1175 destroyAccelerators (); | |
1176 } | |
1177 | |
1178 /** | |
1179 * Sets the minimized stated of the receiver. | |
1180 * If the argument is <code>true</code> causes the receiver | |
1181 * to switch to the minimized state, and if the argument is | |
1182 * <code>false</code> and the receiver was previously minimized, | |
1183 * causes the receiver to switch back to either the maximized | |
1184 * or normal states. | |
1185 * <p> | |
1186 * Note: The result of intermixing calls to <code>setMaximized(true)</code> | |
1187 * and <code>setMinimized(true)</code> will vary by platform. Typically, | |
1188 * the behavior will match the platform user's expectations, but not | |
1189 * always. This should be avoided if possible. | |
1190 * </p> | |
1191 * | |
1192 * @param minimized the new maximized state | |
1193 * | |
1194 * @exception SWTException <ul> | |
1195 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1196 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1197 * </ul> | |
1198 * | |
1199 * @see #setMaximized | |
1200 */ | |
1201 public void setMinimized (bool minimized) { | |
1202 checkWidget (); | |
1203 Display.lpStartupInfo = null; | |
1204 _setMinimized (minimized); | |
1205 } | |
1206 | |
1207 void setParent () { | |
1208 /* | |
1209 * In order for an MDI child window to support | |
1210 * a menu bar, setParent () is needed to reset | |
1211 * the parent. Otherwise, the MDI child window | |
1212 * will appear as a separate shell. This is an | |
1213 * undocumented and possibly dangerous Windows | |
1214 * feature. | |
1215 */ | |
1216 auto hwndParent = parent.handle; | |
1217 display.lockActiveWindow = true; | |
1218 OS.SetParent (handle, hwndParent); | |
1219 if (!OS.IsWindowVisible (hwndParent)) { | |
1220 OS.ShowWindow (handle, OS.SW_SHOWNA); | |
1221 } | |
1222 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
1223 bits &= ~OS.WS_CHILD; | |
1224 OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP); | |
1225 OS.SetWindowLongPtr (handle, OS.GWLP_ID, 0); | |
1226 int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; | |
1227 SetWindowPos (handle, cast(HWND)OS.HWND_BOTTOM, 0, 0, 0, 0, flags); | |
1228 display.lockActiveWindow = false; | |
1229 } | |
1230 | |
1231 void setPlacement (int x, int y, int width, int height, int flags) { | |
1232 WINDOWPLACEMENT lpwndpl; | |
1233 lpwndpl.length = WINDOWPLACEMENT.sizeof; | |
1234 OS.GetWindowPlacement (handle, &lpwndpl); | |
1235 lpwndpl.showCmd = OS.SW_SHOWNA; | |
1236 if (OS.IsIconic (handle)) { | |
1237 lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE; | |
1238 } else { | |
1239 if (OS.IsZoomed (handle)) { | |
1240 lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED; | |
1241 } | |
1242 } | |
1243 bool sameOrigin = true; | |
1244 if ((flags & OS.SWP_NOMOVE) is 0) { | |
1245 sameOrigin = lpwndpl.rcNormalPosition.left !is x || lpwndpl.rcNormalPosition.top !is y; | |
1246 lpwndpl.rcNormalPosition.right = x + (lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left); | |
1247 lpwndpl.rcNormalPosition.bottom = y + (lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top); | |
1248 lpwndpl.rcNormalPosition.left = x; | |
1249 lpwndpl.rcNormalPosition.top = y; | |
1250 } | |
1251 bool sameExtent = true; | |
1252 if ((flags & OS.SWP_NOSIZE) is 0) { | |
1253 sameExtent = lpwndpl.rcNormalPosition.right - lpwndpl.rcNormalPosition.left !is width || lpwndpl.rcNormalPosition.bottom - lpwndpl.rcNormalPosition.top !is height; | |
1254 lpwndpl.rcNormalPosition.right = lpwndpl.rcNormalPosition.left + width; | |
1255 lpwndpl.rcNormalPosition.bottom = lpwndpl.rcNormalPosition.top + height; | |
1256 } | |
1257 OS.SetWindowPlacement (handle, &lpwndpl); | |
1258 if (OS.IsIconic (handle)) { | |
1259 if (sameOrigin) { | |
1260 moved = true; | |
1261 Point location = getLocation (); | |
1262 oldX = location.x; | |
1263 oldY = location.y; | |
1264 sendEvent (SWT.Move); | |
1265 if (isDisposed ()) return; | |
1266 } | |
1267 if (sameExtent) { | |
1268 resized = true; | |
1269 Rectangle rect = getClientArea (); | |
1270 oldWidth = rect.width; | |
1271 oldHeight = rect.height; | |
1272 sendEvent (SWT.Resize); | |
1273 if (isDisposed ()) return; | |
1274 if (layout_ !is null) { | |
1275 markLayout (false, false); | |
1276 updateLayout (true, false); | |
1277 } | |
1278 } | |
1279 } | |
1280 } | |
1281 | |
1282 void setSavedFocus (Control control) { | |
1283 savedFocus = control; | |
1284 } | |
1285 | |
1286 void setSystemMenu () { | |
1287 static if (OS.IsWinCE) return; | |
1288 auto hMenu = OS.GetSystemMenu (handle, false); | |
1289 if (hMenu is null) return; | |
1290 int oldCount = OS.GetMenuItemCount (hMenu); | |
1291 if ((style & SWT.RESIZE) is 0) { | |
1292 OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND); | |
1293 } | |
1294 if ((style & SWT.MIN) is 0) { | |
1295 OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND); | |
1296 } | |
1297 if ((style & SWT.MAX) is 0) { | |
1298 OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND); | |
1299 } | |
1300 if ((style & (SWT.MIN | SWT.MAX)) is 0) { | |
1301 OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND); | |
1302 } | |
1303 int newCount = OS.GetMenuItemCount (hMenu); | |
1304 if ((style & SWT.CLOSE) is 0 || newCount !is oldCount) { | |
1305 OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND); | |
1306 MENUITEMINFO info; | |
1307 info.cbSize = OS.MENUITEMINFO_sizeof; | |
1308 info.fMask = OS.MIIM_ID; | |
1309 int index = 0; | |
1310 while (index < newCount) { | |
1311 if (OS.GetMenuItemInfo (hMenu, index, true, &info)) { | |
1312 if (info.wID is OS.SC_CLOSE) break; | |
1313 } | |
1314 index++; | |
1315 } | |
1316 if (index !is newCount) { | |
1317 OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION); | |
1318 if ((style & SWT.CLOSE) is 0) { | |
1319 OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND); | |
1320 } | |
1321 } | |
1322 } | |
1323 } | |
1324 | |
1325 /** | |
1326 * Sets the receiver's text, which is the string that the | |
1327 * window manager will typically display as the receiver's | |
1328 * <em>title</em>, to the argument, which must not be null. | |
1329 * | |
1330 * @param string the new text | |
1331 * | |
1332 * @exception SWTException <ul> | |
1333 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
1334 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
1335 * </ul> | |
1336 */ | |
1337 public void setText (String string) { | |
1338 checkWidget (); | |
1339 // SWT extension: allow null string | |
1340 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT); | |
1341 /* Use the character encoding for the default locale */ | |
1342 TCHAR[] buffer = StrToTCHARs (string, true); | |
1343 /* Ensure that the title appears in the task bar.*/ | |
1344 if ((state & FOREIGN_HANDLE) !is 0) { | |
1345 auto hHeap = OS.GetProcessHeap (); | |
1346 int byteCount = buffer.length * TCHAR.sizeof; | |
1347 auto pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
1348 OS.MoveMemory (pszText, buffer.ptr, byteCount); | |
1349 OS.DefWindowProc (handle, OS.WM_SETTEXT, 0, cast(int) pszText); | |
1350 if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); | |
1351 } else { | |
1352 OS.SetWindowText (handle, buffer.ptr); | |
1353 } | |
1354 } | |
1355 | |
1356 override public void setVisible (bool visible) { | |
1357 checkWidget (); | |
1358 if (drawCount !is 0) { | |
1359 if (((state & HIDDEN) is 0) is visible) return; | |
1360 } else { | |
1361 if (visible is OS.IsWindowVisible (handle)) return; | |
1362 } | |
1363 if (visible) { | |
1364 /* | |
1365 * It is possible (but unlikely), that application | |
1366 * code could have disposed the widget in the show | |
1367 * event. If this happens, just return. | |
1368 */ | |
1369 sendEvent (SWT.Show); | |
1370 if (isDisposed ()) return; | |
1371 static if (OS.IsHPC) { | |
1372 if (menuBar !is null) { | |
1373 auto hwndCB = menuBar.hwndCB; | |
1374 OS.CommandBar_DrawMenuBar (hwndCB, 0); | |
1375 } | |
1376 } | |
1377 if (drawCount !is 0) { | |
1378 state &= ~HIDDEN; | |
1379 } else { | |
1380 static if (OS.IsWinCE) { | |
1381 OS.ShowWindow (handle, OS.SW_SHOW); | |
1382 } else { | |
1383 if (menuBar !is null) { | |
1384 display.removeBar (menuBar); | |
1385 OS.DrawMenuBar (handle); | |
1386 } | |
1387 STARTUPINFO* lpStartUpInfo = Display.lpStartupInfo; | |
1388 if (lpStartUpInfo !is null && (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) !is 0) { | |
1389 OS.ShowWindow (handle, lpStartUpInfo.wShowWindow); | |
1390 } else { | |
1391 OS.ShowWindow (handle, swFlags); | |
1392 } | |
1393 } | |
1394 if (isDisposed ()) return; | |
1395 opened = true; | |
1396 if (!moved) { | |
1397 moved = true; | |
1398 Point location = getLocation (); | |
1399 oldX = location.x; | |
1400 oldY = location.y; | |
1401 } | |
1402 if (!resized) { | |
1403 resized = true; | |
1404 Rectangle rect = getClientArea (); | |
1405 oldWidth = rect.width; | |
1406 oldHeight = rect.height; | |
1407 } | |
1408 /* | |
1409 * Bug in Windows. On Vista using the Classic theme, | |
1410 * when the window is hung and UpdateWindow() is called, | |
1411 * nothing is drawn, and outstanding WM_PAINTs are cleared. | |
1412 * This causes pixel corruption. The fix is to avoid calling | |
1413 * update on hung windows. | |
1414 */ | |
1415 bool update = true; | |
1416 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && !OS.IsAppThemed ()) { | |
1417 update = !OS.IsHungAppWindow (handle); | |
1418 } | |
1419 if (update) OS.UpdateWindow (handle); | |
1420 } | |
1421 } else { | |
1422 static if (!OS.IsWinCE) { | |
1423 if (OS.IsIconic (handle)) { | |
1424 swFlags = OS.SW_SHOWMINNOACTIVE; | |
1425 } else { | |
1426 if (OS.IsZoomed (handle)) { | |
1427 swFlags = OS.SW_SHOWMAXIMIZED; | |
1428 } else { | |
1429 swFlags = OS.SW_SHOWNOACTIVATE; | |
1430 } | |
1431 } | |
1432 } | |
1433 if (drawCount !is 0) { | |
1434 state |= HIDDEN; | |
1435 } else { | |
1436 OS.ShowWindow (handle, OS.SW_HIDE); | |
1437 } | |
1438 if (isDisposed ()) return; | |
1439 sendEvent (SWT.Hide); | |
1440 } | |
1441 } | |
1442 | |
1443 void sort (Image [] images, ImageData [] datas, int width, int height, int depth) { | |
1444 /* Shell Sort from K&R, pg 108 */ | |
1445 int length = images.length; | |
1446 if (length <= 1) return; | |
1447 for (int gap=length/2; gap>0; gap/=2) { | |
1448 for (int i=gap; i<length; i++) { | |
1449 for (int j=i-gap; j>=0; j-=gap) { | |
1450 if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) { | |
1451 Image swap = images [j]; | |
1452 images [j] = images [j + gap]; | |
1453 images [j + gap] = swap; | |
1454 ImageData swapData = datas [j]; | |
1455 datas [j] = datas [j + gap]; | |
1456 datas [j + gap] = swapData; | |
1457 } | |
1458 } | |
1459 } | |
1460 } | |
1461 } | |
1462 | |
1463 override bool translateAccelerator (MSG* msg) { | |
1464 if (!isEnabled () || !isActive ()) return false; | |
1465 if (menuBar !is null && !menuBar.isEnabled ()) return false; | |
1466 if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true; | |
1467 Decorations decorations = parent.menuShell (); | |
1468 return decorations.translateAccelerator (msg); | |
1469 } | |
1470 | |
1471 bool translateMenuAccelerator (MSG* msg) { | |
1472 if (hAccel is cast(HACCEL)-1) createAccelerators (); | |
1473 return hAccel !is null && OS.TranslateAccelerator (handle, hAccel, msg) !is 0; | |
1474 } | |
1475 | |
1476 bool translateMDIAccelerator (MSG* msg) { | |
1477 if (!(cast(Shell)this)) { | |
1478 Shell shell = getShell (); | |
1479 auto hwndMDIClient = shell.hwndMDIClient_; | |
1480 if (hwndMDIClient !is null && OS.TranslateMDISysAccel (hwndMDIClient, msg)) { | |
1481 return true; | |
1482 } | |
1483 if (msg.message is OS.WM_KEYDOWN) { | |
1484 if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false; | |
1485 switch ((msg.wParam)) { | |
1486 case OS.VK_F4: | |
1487 OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); | |
1488 return true; | |
1489 case OS.VK_F6: | |
1490 if (traverseDecorations (true)) return true; | |
1491 default: | |
1492 } | |
1493 return false; | |
1494 } | |
1495 if (msg.message is OS.WM_SYSKEYDOWN) { | |
1496 switch ((msg.wParam)) { | |
1497 case OS.VK_F4: | |
1498 OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0); | |
1499 return true; | |
1500 default: | |
1501 } | |
1502 return false; | |
1503 } | |
1504 } | |
1505 return false; | |
1506 } | |
1507 | |
1508 bool traverseDecorations (bool next) { | |
1509 Control [] children = parent._getChildren (); | |
1510 int length = children.length; | |
1511 int index = 0; | |
1512 while (index < length) { | |
1513 if (children [index] is this) break; | |
1514 index++; | |
1515 } | |
1516 /* | |
1517 * It is possible (but unlikely), that application | |
1518 * code could have disposed the widget in focus in | |
1519 * or out events. Ensure that a disposed widget is | |
1520 * not accessed. | |
1521 */ | |
1522 int start = index, offset = (next) ? 1 : -1; | |
1523 while ((index = (index + offset + length) % length) !is start) { | |
1524 Control child = children [index]; | |
1525 if (!child.isDisposed () && ( null !is cast(Decorations)child)) { | |
1526 if (child.setFocus ()) return true; | |
1527 } | |
1528 } | |
1529 return false; | |
1530 } | |
1531 | |
1532 override bool traverseItem (bool next) { | |
1533 return false; | |
1534 } | |
1535 | |
1536 override bool traverseReturn () { | |
1537 if (defaultButton is null || defaultButton.isDisposed ()) return false; | |
1538 if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false; | |
1539 defaultButton.click (); | |
1540 return true; | |
1541 } | |
1542 | |
1543 override CREATESTRUCT* widgetCreateStruct () { | |
1544 return new CREATESTRUCT (); | |
1545 } | |
1546 | |
1547 override int widgetExtStyle () { | |
1548 int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD; | |
1549 bits &= ~OS.WS_EX_CLIENTEDGE; | |
1550 if ((style & SWT.NO_TRIM) !is 0) return bits; | |
1551 if (OS.IsPPC) { | |
1552 if ((style & SWT.CLOSE) !is 0) bits |= OS.WS_EX_CAPTIONOKBTN; | |
1553 } | |
1554 if ((style & SWT.RESIZE) !is 0) return bits; | |
1555 if ((style & SWT.BORDER) !is 0) bits |= OS.WS_EX_DLGMODALFRAME; | |
1556 return bits; | |
1557 } | |
1558 | |
1559 override HWND widgetParent () { | |
1560 Shell shell = getShell (); | |
1561 return shell.hwndMDIClient (); | |
1562 } | |
1563 | |
1564 override int widgetStyle () { | |
1565 /* | |
1566 * Clear WS_VISIBLE and WS_TABSTOP. NOTE: In Windows, WS_TABSTOP | |
1567 * has the same value as WS_MAXIMIZEBOX so these bits cannot be | |
1568 * used to control tabbing. | |
1569 */ | |
1570 int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE); | |
1571 | |
1572 /* Set the title bits and no-trim bits */ | |
1573 bits &= ~OS.WS_BORDER; | |
1574 if ((style & SWT.NO_TRIM) !is 0) return bits; | |
1575 if ((style & SWT.TITLE) !is 0) bits |= OS.WS_CAPTION; | |
1576 | |
1577 /* Set the min and max button bits */ | |
1578 if ((style & SWT.MIN) !is 0) bits |= OS.WS_MINIMIZEBOX; | |
1579 if ((style & SWT.MAX) !is 0) bits |= OS.WS_MAXIMIZEBOX; | |
1580 | |
1581 /* Set the resize, dialog border or border bits */ | |
1582 if ((style & SWT.RESIZE) !is 0) { | |
1583 /* | |
1584 * Note on WinCE PPC. SWT.RESIZE is used to resize | |
1585 * the Shell according to the state of the IME. | |
1586 * It does not set the WS_THICKFRAME style. | |
1587 */ | |
1588 if (!OS.IsPPC) bits |= OS.WS_THICKFRAME; | |
1589 } else { | |
1590 if ((style & SWT.BORDER) is 0) bits |= OS.WS_BORDER; | |
1591 } | |
1592 | |
1593 /* Set the system menu and close box bits */ | |
1594 if (!OS.IsPPC && !OS.IsSP) { | |
1595 if ((style & SWT.CLOSE) !is 0) bits |= OS.WS_SYSMENU; | |
1596 } | |
1597 | |
1598 return bits; | |
1599 } | |
1600 | |
1601 override int windowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
1602 switch (msg) { | |
1603 case Display.SWT_GETACCEL: | |
1604 case Display.SWT_GETACCELCOUNT: | |
1605 if (hAccel is cast(HACCEL)-1) createAccelerators (); | |
1606 return msg is Display.SWT_GETACCELCOUNT ? nAccel : cast(int)hAccel; | |
1607 default: | |
1608 } | |
1609 return super.windowProc (hwnd, msg, wParam, lParam); | |
1610 } | |
1611 | |
1612 override LRESULT WM_ACTIVATE (int wParam, int lParam) { | |
1613 LRESULT result = super.WM_ACTIVATE (wParam, lParam); | |
1614 if (result !is null) return result; | |
1615 /* | |
1616 * Feature in AWT. When an AWT Window is activated, | |
1617 * for some reason, it seems to forward the WM_ACTIVATE | |
1618 * message to the parent. Normally, the parent is an | |
1619 * AWT Frame. When AWT is embedded in SWT, the SWT | |
1620 * shell gets the WM_ACTIVATE and assumes that it came | |
1621 * from Windows. When an SWT shell is activated it | |
1622 * restores focus to the last control that had focus. | |
1623 * If this control is an embedded composite, it takes | |
1624 * focus from the AWT Window. The fix is to ignore | |
1625 * WM_ACTIVATE messages that come from AWT Windows. | |
1626 */ | |
1627 if (OS.GetParent ( cast(HWND)lParam) is handle) { | |
1628 TCHAR[128] buffer = 0; | |
1629 OS.GetClassName (cast(HWND)lParam, buffer.ptr, buffer.length ); | |
1630 String className = TCHARzToStr( buffer.ptr ); | |
1631 if (className == Display.AWT_WINDOW_CLASS) { | |
1632 return LRESULT.ZERO; | |
1633 } | |
1634 } | |
1635 if (OS.LOWORD (wParam) !is 0) { | |
1636 /* | |
1637 * When the high word of wParam is non-zero, the activation | |
1638 * state of the window is being changed while the window is | |
1639 * minimized. If this is the case, do not report activation | |
1640 * events or restore the focus. | |
1641 */ | |
1642 if (OS.HIWORD (wParam) !is 0) return result; | |
1643 Control control = display.findControl (cast(HWND)lParam); | |
1644 if (control is null || (null !is cast(Shell)control)) { | |
1645 if (cast(Shell)this) { | |
1646 sendEvent (SWT.Activate); | |
1647 if (isDisposed ()) return LRESULT.ZERO; | |
1648 } | |
1649 } | |
1650 if (restoreFocus ()) return LRESULT.ZERO; | |
1651 } else { | |
1652 Display display = this.display; | |
1653 bool lockWindow = display.isXMouseActive (); | |
1654 if (lockWindow) display.lockActiveWindow = true; | |
1655 Control control = display.findControl (cast(HWND)lParam); | |
1656 if (control is null || (null !is cast(Shell)control)) { | |
1657 if (cast(Shell)this) { | |
1658 sendEvent (SWT.Deactivate); | |
1659 if (!isDisposed ()) { | |
1660 Shell shell = getShell (); | |
1661 shell.setActiveControl (null); | |
1662 // widget could be disposed at this point | |
1663 } | |
1664 } | |
1665 } | |
1666 if (lockWindow) display.lockActiveWindow = false; | |
1667 if (isDisposed ()) return LRESULT.ZERO; | |
1668 saveFocus (); | |
1669 } | |
1670 return result; | |
1671 } | |
1672 | |
1673 override LRESULT WM_CLOSE (int wParam, int lParam) { | |
1674 LRESULT result = super.WM_CLOSE (wParam, lParam); | |
1675 if (result !is null) return result; | |
1676 if (isEnabled () && isActive ()) closeWidget (); | |
1677 return LRESULT.ZERO; | |
1678 } | |
1679 | |
1680 override LRESULT WM_HOTKEY (int wParam, int lParam) { | |
1681 LRESULT result = super.WM_HOTKEY (wParam, lParam); | |
1682 if (result !is null) return result; | |
1683 static if( OS.IsWinCE ){ | |
1684 if (OS.IsSP) { | |
1685 /* | |
1686 * Feature on WinCE SP. The Back key is either used to close | |
1687 * the foreground Dialog or used as a regular Back key in an EDIT | |
1688 * control. The article 'Back Key' in MSDN for Smartphone | |
1689 * describes how an application should handle it. The | |
1690 * workaround is to override the Back key when creating | |
1691 * the menubar and handle it based on the style of the Shell. | |
1692 * If the Shell has the SWT.CLOSE style, close the Shell. | |
1693 * Otherwise, send the Back key to the window with focus. | |
1694 */ | |
1695 if (OS.HIWORD (lParam) is OS.VK_ESCAPE) { | |
1696 if ((style & SWT.CLOSE) !is 0) { | |
1697 OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); | |
1698 } else { | |
1699 OS.SHSendBackToFocusWindow (OS.WM_HOTKEY, wParam, lParam); | |
1700 } | |
1701 return LRESULT.ZERO; | |
1702 } | |
1703 } | |
1704 } | |
1705 return result; | |
1706 } | |
1707 | |
1708 override LRESULT WM_KILLFOCUS (int wParam, int lParam) { | |
1709 LRESULT result = super.WM_KILLFOCUS (wParam, lParam); | |
1710 saveFocus (); | |
1711 return result; | |
1712 } | |
1713 | |
1714 override LRESULT WM_MOVE (int wParam, int lParam) { | |
1715 if (moved) { | |
1716 Point location = getLocation (); | |
1717 if (location.x is oldX && location.y is oldY) { | |
1718 return null; | |
1719 } | |
1720 oldX = location.x; | |
1721 oldY = location.y; | |
1722 } | |
1723 return super.WM_MOVE (wParam, lParam); | |
1724 } | |
1725 | |
1726 override LRESULT WM_NCACTIVATE (int wParam, int lParam) { | |
1727 LRESULT result = super.WM_NCACTIVATE (wParam, lParam); | |
1728 if (result !is null) return result; | |
1729 if (wParam is 0) { | |
1730 if (display.lockActiveWindow) return LRESULT.ZERO; | |
1731 Control control = display.findControl (cast(HANDLE)lParam); | |
1732 if (control !is null) { | |
1733 Shell shell = getShell (); | |
1734 Decorations decorations = control.menuShell (); | |
1735 if (decorations.getShell () is shell) { | |
1736 if (cast(Shell)this) return LRESULT.ONE; | |
1737 if (display.ignoreRestoreFocus) { | |
1738 if (display.lastHittest !is OS.HTCLIENT) { | |
1739 result = LRESULT.ONE; | |
1740 } | |
1741 } | |
1742 } | |
1743 } | |
1744 } | |
1745 if (!(cast(Shell)this)) { | |
1746 auto hwndShell = getShell().handle; | |
1747 OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam); | |
1748 } | |
1749 return result; | |
1750 } | |
1751 | |
1752 override LRESULT WM_QUERYOPEN (int wParam, int lParam) { | |
1753 LRESULT result = super.WM_QUERYOPEN (wParam, lParam); | |
1754 if (result !is null) return result; | |
1755 sendEvent (SWT.Deiconify); | |
1756 // widget could be disposed at this point | |
1757 return result; | |
1758 } | |
1759 | |
1760 override LRESULT WM_SETFOCUS (int wParam, int lParam) { | |
1761 LRESULT result = super.WM_SETFOCUS (wParam, lParam); | |
1762 if (savedFocus !is this) restoreFocus (); | |
1763 return result; | |
1764 } | |
1765 | |
1766 override LRESULT WM_SIZE (int wParam, int lParam) { | |
1767 LRESULT result = null; | |
1768 bool changed = true; | |
1769 if (resized) { | |
1770 int newWidth = 0, newHeight = 0; | |
1771 switch (wParam) { | |
1772 case OS.SIZE_RESTORED: | |
1773 case OS.SIZE_MAXIMIZED: | |
1774 newWidth = OS.LOWORD (lParam); | |
1775 newHeight = OS.HIWORD (lParam); | |
1776 break; | |
1777 case OS.SIZE_MINIMIZED: | |
1778 Rectangle rect = getClientArea (); | |
1779 newWidth = rect.width; | |
1780 newHeight = rect.height; | |
1781 break; | |
1782 default: | |
1783 } | |
1784 changed = newWidth !is oldWidth || newHeight !is oldHeight; | |
1785 if (changed) { | |
1786 oldWidth = newWidth; | |
1787 oldHeight = newHeight; | |
1788 } | |
1789 } | |
1790 if (changed) { | |
1791 result = super.WM_SIZE (wParam, lParam); | |
1792 if (isDisposed ()) return result; | |
1793 } | |
1794 if (wParam is OS.SIZE_MINIMIZED) { | |
1795 sendEvent (SWT.Iconify); | |
1796 // widget could be disposed at this point | |
1797 } | |
1798 return result; | |
1799 } | |
1800 | |
1801 override LRESULT WM_SYSCOMMAND (int wParam, int lParam) { | |
1802 LRESULT result = super.WM_SYSCOMMAND (wParam, lParam); | |
1803 if (result !is null) return result; | |
1804 if (!(cast(Shell)this)) { | |
1805 int cmd = wParam & 0xFFF0; | |
1806 switch (cmd) { | |
1807 case OS.SC_CLOSE: { | |
1808 OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); | |
1809 return LRESULT.ZERO; | |
1810 } | |
1811 case OS.SC_NEXTWINDOW: { | |
1812 traverseDecorations (true); | |
1813 return LRESULT.ZERO; | |
1814 } | |
1815 default: | |
1816 } | |
1817 } | |
1818 return result; | |
1819 } | |
1820 | |
1821 override LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { | |
1822 LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam); | |
1823 if (result !is null) return result; | |
1824 if (display.lockActiveWindow) { | |
1825 WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam; | |
1826 //OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof); | |
1827 lpwp.flags |= OS.SWP_NOZORDER; | |
1828 //OS.MoveMemory (lParam, &lpwp, WINDOWPOS.sizeof); | |
1829 } | |
1830 return result; | |
1831 } | |
1832 | |
1833 } |