Mercurial > projects > dwt2
comparison org.eclipse.swt.win32.win32.x86/src/org/eclipse/swt/widgets/Label.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 | 0ecb2b338560 |
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.Label; | |
14 | |
15 | |
16 import org.eclipse.swt.SWT; | |
17 import org.eclipse.swt.SWTException; | |
18 import org.eclipse.swt.graphics.GC; | |
19 import org.eclipse.swt.graphics.GCData; | |
20 import org.eclipse.swt.graphics.Image; | |
21 import org.eclipse.swt.graphics.Point; | |
22 import org.eclipse.swt.graphics.Rectangle; | |
23 import org.eclipse.swt.internal.win32.OS; | |
24 | |
25 import org.eclipse.swt.widgets.Control; | |
26 import org.eclipse.swt.widgets.Composite; | |
27 import org.eclipse.swt.widgets.Display; | |
28 import org.eclipse.swt.widgets.Event; | |
29 | |
30 import java.lang.all; | |
31 | |
32 /** | |
33 * Instances of this class represent a non-selectable | |
34 * user interface object that displays a string or image. | |
35 * When SEPARATOR is specified, displays a single | |
36 * vertical or horizontal line. | |
37 * <p> | |
38 * Shadow styles are hints and may not be honoured | |
39 * by the platform. To create a separator label | |
40 * with the default shadow style for the platform, | |
41 * do not specify a shadow style. | |
42 * </p> | |
43 * <dl> | |
44 * <dt><b>Styles:</b></dt> | |
45 * <dd>SEPARATOR, HORIZONTAL, VERTICAL</dd> | |
46 * <dd>SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd> | |
47 * <dd>CENTER, LEFT, RIGHT, WRAP</dd> | |
48 * <dt><b>Events:</b></dt> | |
49 * <dd>(none)</dd> | |
50 * </dl> | |
51 * <p> | |
52 * Note: Only one of SHADOW_IN, SHADOW_OUT and SHADOW_NONE may be specified. | |
53 * SHADOW_NONE is a HINT. Only one of HORIZONTAL and VERTICAL may be specified. | |
54 * Only one of CENTER, LEFT and RIGHT may be specified. | |
55 * </p><p> | |
56 * IMPORTANT: This class is intended to be subclassed <em>only</em> | |
57 * within the SWT implementation. | |
58 * </p> | |
59 * | |
60 * @see <a href="http://www.eclipse.org/swt/snippets/#label">Label snippets</a> | |
61 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a> | |
62 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> | |
63 */ | |
64 public class Label : Control { | |
65 | |
66 alias Control.computeSize computeSize; | |
67 alias Control.windowProc windowProc; | |
68 | |
69 String text = ""; | |
70 Image image; | |
71 static const int MARGIN = 4; | |
72 static const bool IMAGE_AND_TEXT = false; | |
73 private static /+const+/ WNDPROC LabelProc; | |
74 static const TCHAR[] LabelClass = "STATIC\0"; | |
75 | |
76 private static bool static_this_completed = false; | |
77 private static void static_this() { | |
78 if( static_this_completed ){ | |
79 return; | |
80 } | |
81 synchronized { | |
82 if( static_this_completed ){ | |
83 return; | |
84 } | |
85 WNDCLASS lpWndClass; | |
86 OS.GetClassInfo (null, LabelClass.ptr, &lpWndClass); | |
87 LabelProc = lpWndClass.lpfnWndProc; | |
88 static_this_completed = true; | |
89 } | |
90 } | |
91 | |
92 | |
93 /** | |
94 * Constructs a new instance of this class given its parent | |
95 * and a style value describing its behavior and appearance. | |
96 * <p> | |
97 * The style value is either one of the style constants defined in | |
98 * class <code>SWT</code> which is applicable to instances of this | |
99 * class, or must be built by <em>bitwise OR</em>'ing together | |
100 * (that is, using the <code>int</code> "|" operator) two or more | |
101 * of those <code>SWT</code> style constants. The class description | |
102 * lists the style constants that are applicable to the class. | |
103 * Style bits are also inherited from superclasses. | |
104 * </p> | |
105 * | |
106 * @param parent a composite control which will be the parent of the new instance (cannot be null) | |
107 * @param style the style of control to construct | |
108 * | |
109 * @exception IllegalArgumentException <ul> | |
110 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
111 * </ul> | |
112 * @exception SWTException <ul> | |
113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
114 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
115 * </ul> | |
116 * | |
117 * @see SWT#SEPARATOR | |
118 * @see SWT#HORIZONTAL | |
119 * @see SWT#VERTICAL | |
120 * @see SWT#SHADOW_IN | |
121 * @see SWT#SHADOW_OUT | |
122 * @see SWT#SHADOW_NONE | |
123 * @see SWT#CENTER | |
124 * @see SWT#LEFT | |
125 * @see SWT#RIGHT | |
126 * @see SWT#WRAP | |
127 * @see Widget#checkSubclass | |
128 * @see Widget#getStyle | |
129 */ | |
130 public this (Composite parent, int style) { | |
131 static_this(); | |
132 super (parent, checkStyle (style)); | |
133 } | |
134 | |
135 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { | |
136 if (handle is null) return 0; | |
137 return OS.CallWindowProc (LabelProc, hwnd, msg, wParam, lParam); | |
138 } | |
139 | |
140 static int checkStyle (int style) { | |
141 style |= SWT.NO_FOCUS; | |
142 if ((style & SWT.SEPARATOR) !is 0) { | |
143 style = checkBits (style, SWT.VERTICAL, SWT.HORIZONTAL, 0, 0, 0, 0); | |
144 return checkBits (style, SWT.SHADOW_OUT, SWT.SHADOW_IN, SWT.SHADOW_NONE, 0, 0, 0); | |
145 } | |
146 return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0); | |
147 } | |
148 | |
149 override public Point computeSize (int wHint, int hHint, bool changed) { | |
150 checkWidget (); | |
151 int width = 0, height = 0, border = getBorderWidth (); | |
152 if ((style & SWT.SEPARATOR) !is 0) { | |
153 int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER); | |
154 if ((style & SWT.HORIZONTAL) !is 0) { | |
155 width = DEFAULT_WIDTH; height = lineWidth * 2; | |
156 } else { | |
157 width = lineWidth * 2; height = DEFAULT_HEIGHT; | |
158 } | |
159 if (wHint !is SWT.DEFAULT) width = wHint; | |
160 if (hHint !is SWT.DEFAULT) height = hHint; | |
161 width += border * 2; height += border * 2; | |
162 return new Point (width, height); | |
163 } | |
164 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
165 bool drawText = true; | |
166 bool drawImage = (bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW; | |
167 if (drawImage) { | |
168 if (image !is null) { | |
169 Rectangle rect = image.getBounds(); | |
170 width += rect.width; | |
171 height += rect.height; | |
172 if (IMAGE_AND_TEXT) { | |
173 if (text.length !is 0) width += MARGIN; | |
174 } else { | |
175 drawText = false; | |
176 } | |
177 } | |
178 } | |
179 if (drawText) { | |
180 auto hDC = OS.GetDC (handle); | |
181 auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); | |
182 auto oldFont = OS.SelectObject (hDC, newFont); | |
183 int length = OS.GetWindowTextLength (handle); | |
184 if (length is 0) { | |
185 TEXTMETRIC tm; | |
186 OS.GetTextMetrics (hDC, &tm); | |
187 height = Math.max (height, tm.tmHeight); | |
188 } else { | |
189 RECT rect; | |
190 int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS; | |
191 if ((style & SWT.WRAP) !is 0 && wHint !is SWT.DEFAULT) { | |
192 flags |= OS.DT_WORDBREAK; | |
193 rect.right = Math.max (0, wHint - width); | |
194 } | |
195 TCHAR[] buffer = new TCHAR [/+getCodePage (),+/ length + 1]; | |
196 OS.GetWindowText (handle, buffer.ptr, length + 1); | |
197 OS.DrawText (hDC, buffer.ptr, length, &rect, flags); | |
198 width += rect.right - rect.left; | |
199 height = Math.max (height, rect.bottom - rect.top); | |
200 } | |
201 if (newFont !is null) OS.SelectObject (hDC, oldFont); | |
202 OS.ReleaseDC (handle, hDC); | |
203 } | |
204 if (wHint !is SWT.DEFAULT) width = wHint; | |
205 if (hHint !is SWT.DEFAULT) height = hHint; | |
206 width += border * 2; | |
207 height += border * 2; | |
208 /* | |
209 * Feature in WinCE PPC. Text labels have a trim | |
210 * of one pixel wide on the right and left side. | |
211 * The fix is to increase the width to include | |
212 * this trim. | |
213 */ | |
214 if (OS.IsWinCE && !drawImage) width += 2; | |
215 return new Point (width, height); | |
216 } | |
217 | |
218 override void createHandle () { | |
219 super.createHandle (); | |
220 state |= THEME_BACKGROUND; | |
221 } | |
222 | |
223 /** | |
224 * Returns a value which describes the position of the | |
225 * text or image in the receiver. The value will be one of | |
226 * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code> | |
227 * unless the receiver is a <code>SEPARATOR</code> label, in | |
228 * which case, <code>NONE</code> is returned. | |
229 * | |
230 * @return the alignment | |
231 * | |
232 * @exception SWTException <ul> | |
233 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
234 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
235 * </ul> | |
236 */ | |
237 public int getAlignment () { | |
238 checkWidget (); | |
239 if ((style & SWT.SEPARATOR) !is 0) return 0; | |
240 if ((style & SWT.LEFT) !is 0) return SWT.LEFT; | |
241 if ((style & SWT.CENTER) !is 0) return SWT.CENTER; | |
242 if ((style & SWT.RIGHT) !is 0) return SWT.RIGHT; | |
243 return SWT.LEFT; | |
244 } | |
245 | |
246 /** | |
247 * Returns the receiver's image if it has one, or null | |
248 * if it does not. | |
249 * | |
250 * @return the receiver's image | |
251 * | |
252 * @exception SWTException <ul> | |
253 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
255 * </ul> | |
256 */ | |
257 public Image getImage () { | |
258 checkWidget (); | |
259 return image; | |
260 } | |
261 | |
262 override String getNameText () { | |
263 return getText (); | |
264 } | |
265 | |
266 /** | |
267 * Returns the receiver's text, which will be an empty | |
268 * string if it has never been set or if the receiver is | |
269 * a <code>SEPARATOR</code> label. | |
270 * | |
271 * @return the receiver's text | |
272 * | |
273 * @exception SWTException <ul> | |
274 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
275 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
276 * </ul> | |
277 */ | |
278 public String getText () { | |
279 checkWidget (); | |
280 if ((style & SWT.SEPARATOR) !is 0) return ""; | |
281 return text; | |
282 } | |
283 | |
284 override bool mnemonicHit (wchar key) { | |
285 Composite control = this.parent; | |
286 while (control !is null) { | |
287 Control [] children = control._getChildren (); | |
288 int index = 0; | |
289 while (index < children.length) { | |
290 if (children [index] is this) break; | |
291 index++; | |
292 } | |
293 index++; | |
294 if (index < children.length) { | |
295 if (children [index].setFocus ()) return true; | |
296 } | |
297 control = control.parent; | |
298 } | |
299 return false; | |
300 } | |
301 | |
302 override bool mnemonicMatch (wchar key) { | |
303 wchar mnemonic = findMnemonic (getText ()); | |
304 if (mnemonic is '\0') return false; | |
305 return CharacterToUpper (key) is CharacterToUpper (mnemonic); | |
306 } | |
307 | |
308 override void releaseWidget () { | |
309 super.releaseWidget (); | |
310 text = null; | |
311 image = null; | |
312 } | |
313 | |
314 /** | |
315 * Controls how text and images will be displayed in the receiver. | |
316 * The argument should be one of <code>LEFT</code>, <code>RIGHT</code> | |
317 * or <code>CENTER</code>. If the receiver is a <code>SEPARATOR</code> | |
318 * label, the argument is ignored and the alignment is not changed. | |
319 * | |
320 * @param alignment the new alignment | |
321 * | |
322 * @exception SWTException <ul> | |
323 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
324 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
325 * </ul> | |
326 */ | |
327 public void setAlignment (int alignment) { | |
328 checkWidget (); | |
329 if ((style & SWT.SEPARATOR) !is 0) return; | |
330 if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) is 0) return; | |
331 style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); | |
332 style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); | |
333 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
334 if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) { | |
335 bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT); | |
336 if ((style & SWT.LEFT) !is 0) { | |
337 if ((style & SWT.WRAP) !is 0) { | |
338 bits |= OS.SS_LEFT; | |
339 } else { | |
340 bits |= OS.SS_LEFTNOWORDWRAP; | |
341 } | |
342 } | |
343 if ((style & SWT.CENTER) !is 0) bits |= OS.SS_CENTER; | |
344 if ((style & SWT.RIGHT) !is 0) bits |= OS.SS_RIGHT; | |
345 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); | |
346 } | |
347 OS.InvalidateRect (handle, null, true); | |
348 } | |
349 | |
350 /** | |
351 * Sets the receiver's image to the argument, which may be | |
352 * null indicating that no image should be displayed. | |
353 * | |
354 * @param image the image to display on the receiver (may be null) | |
355 * | |
356 * @exception IllegalArgumentException <ul> | |
357 * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li> | |
358 * </ul> | |
359 * @exception SWTException <ul> | |
360 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
361 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
362 * </ul> | |
363 */ | |
364 public void setImage (Image image) { | |
365 checkWidget (); | |
366 if ((style & SWT.SEPARATOR) !is 0) return; | |
367 if (image !is null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); | |
368 this.image = image; | |
369 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
370 if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) { | |
371 bits &= ~(OS.SS_LEFTNOWORDWRAP | OS.SS_CENTER | OS.SS_RIGHT); | |
372 bits |= OS.SS_OWNERDRAW; | |
373 OS.SetWindowLong (handle, OS.GWL_STYLE, bits); | |
374 } | |
375 OS.InvalidateRect (handle, null, true); | |
376 } | |
377 | |
378 /** | |
379 * Sets the receiver's text. | |
380 * <p> | |
381 * This method sets the widget label. The label may include | |
382 * the mnemonic character and line delimiters. | |
383 * </p> | |
384 * <p> | |
385 * Mnemonics are indicated by an '&' that causes the next | |
386 * character to be the mnemonic. When the user presses a | |
387 * key sequence that matches the mnemonic, focus is assigned | |
388 * to the control that follows the label. On most platforms, | |
389 * the mnemonic appears underlined but may be emphasised in a | |
390 * platform specific manner. The mnemonic indicator character | |
391 * '&' can be escaped by doubling it in the string, causing | |
392 * a single '&' to be displayed. | |
393 * </p> | |
394 * | |
395 * @param string the new text | |
396 * | |
397 * @exception SWTException <ul> | |
398 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
399 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
400 * </ul> | |
401 */ | |
402 public void setText (String string) { | |
403 checkWidget (); | |
404 // SWT extensions allow null argument | |
405 //if (string is null) error (SWT.ERROR_NULL_ARGUMENT); | |
406 if ((style & SWT.SEPARATOR) !is 0) return; | |
407 /* | |
408 * Feature in Windows. For some reason, SetWindowText() for | |
409 * static controls redraws the control, even when the text has | |
410 * has not changed. The fix is to check for this case and do | |
411 * nothing. | |
412 */ | |
413 if (string.equals(text)) return; | |
414 text = string; | |
415 if (image is null || !IMAGE_AND_TEXT) { | |
416 int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE), newBits = oldBits; | |
417 newBits &= ~OS.SS_OWNERDRAW; | |
418 if ((style & SWT.LEFT) !is 0) { | |
419 if ((style & SWT.WRAP) !is 0) { | |
420 newBits |= OS.SS_LEFT; | |
421 } else { | |
422 newBits |= OS.SS_LEFTNOWORDWRAP; | |
423 } | |
424 } | |
425 if ((style & SWT.CENTER) !is 0) newBits |= OS.SS_CENTER; | |
426 if ((style & SWT.RIGHT) !is 0) newBits |= OS.SS_RIGHT; | |
427 if (oldBits !is newBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits); | |
428 } | |
429 string = Display.withCrLf (string); | |
430 TCHAR* buffer = StrToTCHARz ( getCodePage (), string); | |
431 OS.SetWindowText (handle, buffer); | |
432 /* | |
433 * Bug in Windows. For some reason, the HBRUSH that | |
434 * is returned from WM_CTRLCOLOR is misaligned when | |
435 * the label uses it to draw. If the brush is a solid | |
436 * color, this does not matter. However, if the brush | |
437 * contains an image, the image is misaligned. The | |
438 * fix is to draw the background in WM_ERASEBKGND. | |
439 */ | |
440 if (OS.COMCTL32_MAJOR < 6) { | |
441 if (findImageControl () !is null) OS.InvalidateRect (handle, null, true); | |
442 } | |
443 } | |
444 | |
445 override int widgetExtStyle () { | |
446 int bits = super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE; | |
447 if ((style & SWT.BORDER) !is 0) return bits | OS.WS_EX_STATICEDGE; | |
448 return bits; | |
449 } | |
450 | |
451 override int widgetStyle () { | |
452 int bits = super.widgetStyle () | OS.SS_NOTIFY; | |
453 if ((style & SWT.SEPARATOR) !is 0) return bits | OS.SS_OWNERDRAW; | |
454 if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) { | |
455 if ((style & SWT.WRAP) !is 0) bits |= OS.SS_EDITCONTROL; | |
456 } | |
457 if ((style & SWT.CENTER) !is 0) return bits | OS.SS_CENTER; | |
458 if ((style & SWT.RIGHT) !is 0) return bits | OS.SS_RIGHT; | |
459 if ((style & SWT.WRAP) !is 0) return bits | OS.SS_LEFT; | |
460 return bits | OS.SS_LEFTNOWORDWRAP; | |
461 } | |
462 | |
463 override String windowClass () { | |
464 return TCHARsToStr( LabelClass ); | |
465 } | |
466 | |
467 override int windowProc () { | |
468 return cast(int) LabelProc; | |
469 } | |
470 | |
471 override LRESULT WM_ERASEBKGND (int wParam, int lParam) { | |
472 LRESULT result = super.WM_ERASEBKGND (wParam, lParam); | |
473 if (result !is null) return result; | |
474 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
475 if ((bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW) { | |
476 return LRESULT.ONE; | |
477 } | |
478 /* | |
479 * Bug in Windows. For some reason, the HBRUSH that | |
480 * is returned from WM_CTRLCOLOR is misaligned when | |
481 * the label uses it to draw. If the brush is a solid | |
482 * color, this does not matter. However, if the brush | |
483 * contains an image, the image is misaligned. The | |
484 * fix is to draw the background in WM_ERASEBKGND. | |
485 */ | |
486 if (OS.COMCTL32_MAJOR < 6) { | |
487 if (findImageControl () !is null) { | |
488 drawBackground (cast(HANDLE)wParam); | |
489 return LRESULT.ONE; | |
490 } | |
491 } | |
492 return result; | |
493 } | |
494 | |
495 override LRESULT WM_SIZE (int wParam, int lParam) { | |
496 LRESULT result = super.WM_SIZE (wParam, lParam); | |
497 if (isDisposed ()) return result; | |
498 if ((style & SWT.SEPARATOR) !is 0) { | |
499 OS.InvalidateRect (handle, null, true); | |
500 return result; | |
501 } | |
502 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
503 if ((bits & OS.SS_OWNERDRAW) is OS.SS_OWNERDRAW) { | |
504 OS.InvalidateRect (handle, null, true); | |
505 return result; | |
506 } | |
507 /* | |
508 * Bug in Windows. For some reason, a label with | |
509 * style SS_LEFT, SS_CENTER or SS_RIGHT does not | |
510 * redraw the text in the new position when resized. | |
511 * Note that SS_LEFTNOWORDWRAP does not have the | |
512 * problem. The fix is to force the redraw. | |
513 */ | |
514 if ((bits & OS.SS_LEFTNOWORDWRAP) !is OS.SS_LEFTNOWORDWRAP) { | |
515 OS.InvalidateRect (handle, null, true); | |
516 return result; | |
517 } | |
518 return result; | |
519 } | |
520 | |
521 override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) { | |
522 LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam); | |
523 if (result !is null) return result; | |
524 /* | |
525 * Feature in Windows. When WM_UPDATEUISTATE is sent to | |
526 * a static control, it sends WM_CTLCOLORSTATIC to get the | |
527 * foreground and background. If any drawing happens in | |
528 * WM_CTLCOLORSTATIC, it overwrites the contents of the control. | |
529 * The fix is draw the static without drawing the background | |
530 * and avoid the static window proc. | |
531 */ | |
532 bool redraw = findImageControl () !is null; | |
533 if (!redraw) { | |
534 if ((state & THEME_BACKGROUND) !is 0) { | |
535 if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { | |
536 redraw = findThemeControl () !is null; | |
537 } | |
538 } | |
539 } | |
540 if (redraw) { | |
541 OS.InvalidateRect (handle, null, false); | |
542 int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); | |
543 return new LRESULT (code); | |
544 } | |
545 return result; | |
546 } | |
547 | |
548 override LRESULT wmColorChild (int wParam, int lParam) { | |
549 /* | |
550 * Bug in Windows. For some reason, the HBRUSH that | |
551 * is returned from WM_CTRLCOLOR is misaligned when | |
552 * the label uses it to draw. If the brush is a solid | |
553 * color, this does not matter. However, if the brush | |
554 * contains an image, the image is misaligned. The | |
555 * fix is to draw the background in WM_ERASEBKGND. | |
556 */ | |
557 LRESULT result = super.wmColorChild (wParam, lParam); | |
558 if (OS.COMCTL32_MAJOR < 6) { | |
559 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); | |
560 if ((bits & OS.SS_OWNERDRAW) !is OS.SS_OWNERDRAW) { | |
561 if (findImageControl () !is null) { | |
562 OS.SetBkMode ( cast(HANDLE) wParam, OS.TRANSPARENT); | |
563 return new LRESULT ( cast(int)OS.GetStockObject (OS.NULL_BRUSH)); | |
564 } | |
565 } | |
566 } | |
567 return result; | |
568 } | |
569 | |
570 override LRESULT WM_PAINT (int wParam, int lParam) { | |
571 static if (OS.IsWinCE) { | |
572 bool drawImage = image !is null; | |
573 bool drawSeparator = (style & SWT.SEPARATOR) !is 0 && (style & SWT.SHADOW_NONE) is 0; | |
574 if (drawImage || drawSeparator) { | |
575 LRESULT result = null; | |
576 PAINTSTRUCT ps; | |
577 GCData data = new GCData (); | |
578 data.ps = &ps; | |
579 data.hwnd = handle; | |
580 GC gc = new_GC (data); | |
581 if (gc !is null) { | |
582 drawBackground (gc.handle); | |
583 RECT clientRect; | |
584 OS.GetClientRect (handle, &clientRect); | |
585 if (drawSeparator) { | |
586 RECT rect; | |
587 int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER); | |
588 int flags = (style & SWT.SHADOW_IN) !is 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED; | |
589 if ((style & SWT.HORIZONTAL) !is 0) { | |
590 int bottom = clientRect.top + Math.max (lineWidth * 2, (clientRect.bottom - clientRect.top) / 2); | |
591 OS.SetRect (&rect, clientRect.left, clientRect.top, clientRect.right, bottom); | |
592 OS.DrawEdge (gc.handle, &rect, flags, OS.BF_BOTTOM); | |
593 } else { | |
594 int right = clientRect.left + Math.max (lineWidth * 2, (clientRect.right - clientRect.left) / 2); | |
595 OS.SetRect (&rect, clientRect.left, clientRect.top, right, clientRect.bottom); | |
596 OS.DrawEdge (gc.handle, &rect, flags, OS.BF_RIGHT); | |
597 } | |
598 result = LRESULT.ONE; | |
599 } | |
600 if (drawImage) { | |
601 Rectangle imageBounds = image.getBounds (); | |
602 int x = 0; | |
603 if ((style & SWT.CENTER) !is 0) { | |
604 x = Math.max (0, (clientRect.right - imageBounds.width) / 2); | |
605 } else { | |
606 if ((style & SWT.RIGHT) !is 0) { | |
607 x = Math.max (0, (clientRect.right - imageBounds.width)); | |
608 } | |
609 } | |
610 gc.drawImage (image, x, Math.max (0, (clientRect.bottom - imageBounds.height) / 2)); | |
611 result = LRESULT.ONE; | |
612 } | |
613 int width = ps.rcPaint.right - ps.rcPaint.left; | |
614 int height = ps.rcPaint.bottom - ps.rcPaint.top; | |
615 if (width !is 0 && height !is 0) { | |
616 Event event = new Event (); | |
617 event.gc = gc; | |
618 event.x = ps.rcPaint.left; | |
619 event.y = ps.rcPaint.top; | |
620 event.width = width; | |
621 event.height = height; | |
622 sendEvent (SWT.Paint, event); | |
623 // widget could be disposed at this point | |
624 event.gc = null; | |
625 } | |
626 gc.dispose (); | |
627 } | |
628 return result; | |
629 } | |
630 } | |
631 return super.WM_PAINT(wParam, lParam); | |
632 } | |
633 | |
634 override LRESULT wmDrawChild (int wParam, int lParam) { | |
635 DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam; | |
636 drawBackground (struct_.hDC); | |
637 if ((style & SWT.SEPARATOR) !is 0) { | |
638 if ((style & SWT.SHADOW_NONE) !is 0) return null; | |
639 RECT rect; | |
640 int lineWidth = OS.GetSystemMetrics (OS.SM_CXBORDER); | |
641 int flags = (style & SWT.SHADOW_IN) !is 0 ? OS.EDGE_SUNKEN : OS.EDGE_ETCHED; | |
642 if ((style & SWT.HORIZONTAL) !is 0) { | |
643 int bottom = struct_.rcItem.top + Math.max (lineWidth * 2, (struct_.rcItem.bottom - struct_.rcItem.top) / 2); | |
644 OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, struct_.rcItem.right, bottom); | |
645 OS.DrawEdge (struct_.hDC, &rect, flags, OS.BF_BOTTOM); | |
646 } else { | |
647 int right = struct_.rcItem.left + Math.max (lineWidth * 2, (struct_.rcItem.right - struct_.rcItem.left) / 2); | |
648 OS.SetRect (&rect, struct_.rcItem.left, struct_.rcItem.top, right, struct_.rcItem.bottom); | |
649 OS.DrawEdge (struct_.hDC, &rect, flags, OS.BF_RIGHT); | |
650 } | |
651 } else { | |
652 int width = struct_.rcItem.right - struct_.rcItem.left; | |
653 int height = struct_.rcItem.bottom - struct_.rcItem.top; | |
654 if (width !is 0 && height !is 0) { | |
655 bool drawImage = image !is null; | |
656 bool drawText = IMAGE_AND_TEXT && text.length !is 0; | |
657 int margin = drawText && drawImage ? MARGIN : 0; | |
658 int imageWidth = 0, imageHeight = 0; | |
659 if (drawImage) { | |
660 Rectangle rect = image.getBounds (); | |
661 imageWidth = rect.width; | |
662 imageHeight = rect.height; | |
663 } | |
664 RECT rect; | |
665 TCHAR* buffer = null; | |
666 int textWidth = 0, textHeight = 0, flags = 0; | |
667 if (drawText) { | |
668 //rect = new RECT (); | |
669 flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_EXPANDTABS; | |
670 if ((style & SWT.LEFT) !is 0) flags |= OS.DT_LEFT; | |
671 if ((style & SWT.CENTER) !is 0) flags |= OS.DT_CENTER; | |
672 if ((style & SWT.RIGHT) !is 0) flags |= OS.DT_RIGHT; | |
673 if ((style & SWT.WRAP) !is 0) { | |
674 flags |= OS.DT_WORDBREAK; | |
675 rect.right = Math.max (0, width - imageWidth - margin); | |
676 } | |
677 buffer = StrToTCHARz (/+getCodePage (),+/ text); | |
678 OS.DrawText (struct_.hDC, buffer, -1, &rect, flags); | |
679 textWidth = rect.right - rect.left; | |
680 textHeight = rect.bottom - rect.top; | |
681 } | |
682 int x = 0; | |
683 if ((style & SWT.CENTER) !is 0) { | |
684 x = Math.max (0, (width - imageWidth - textWidth - margin) / 2); | |
685 } else { | |
686 if ((style & SWT.RIGHT) !is 0) { | |
687 x = width - imageWidth - textWidth - margin; | |
688 } | |
689 } | |
690 if (drawImage) { | |
691 GCData data = new GCData(); | |
692 data.device = display; | |
693 GC gc = GC.win32_new (struct_.hDC, data); | |
694 Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE); | |
695 gc.drawImage (image, x, Math.max (0, (height - imageHeight) / 2)); | |
696 if (image !is this.image) image.dispose (); | |
697 gc.dispose (); | |
698 x += imageWidth + margin; | |
699 } | |
700 if (drawText) { | |
701 flags &= ~OS.DT_CALCRECT; | |
702 rect.left = x; | |
703 rect.right += rect.left; | |
704 rect.top = Math.max (0, (height - textHeight) / 2); | |
705 rect.bottom += rect.top; | |
706 OS.DrawText (struct_.hDC, buffer, -1, &rect, flags); | |
707 } | |
708 } | |
709 } | |
710 return null; | |
711 } | |
712 | |
713 } | |
714 |