root/dwt/widgets/Combo.d

Revision 246:fd9c62a2998e, 93.0 kB (checked in by Frank Benoit <benoit@tionex.de>, 5 months ago)

Updater SWT 3.4M7 to 3.4

Line 
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 dwt.widgets.Combo;
14
15 import dwt.widgets.Composite;
16
17 import dwt.DWT;
18 import dwt.DWTException;
19 import dwt.events.ModifyListener;
20 import dwt.events.SelectionEvent;
21 import dwt.events.SelectionListener;
22 import dwt.events.VerifyListener;
23 import dwt.graphics.Font;
24 import dwt.graphics.Point;
25 import dwt.internal.win32.OS;
26
27 import dwt.widgets.TypedListener;
28 import dwt.widgets.Event;
29 import dwt.widgets.Composite;
30 import dwt.widgets.Shell;
31 import dwt.widgets.Display;
32
33 import dwt.dwthelper.utils;
34
35 /**
36  * Instances of this class are controls that allow the user
37  * to choose an item from a list of items, or optionally
38  * enter a new value by typing it into an editable text
39  * field. Often, <code>Combo</code>s are used in the same place
40  * where a single selection <code>List</code> widget could
41  * be used but space is limited. A <code>Combo</code> takes
42  * less space than a <code>List</code> widget and shows
43  * similar information.
44  * <p>
45  * Note: Since <code>Combo</code>s can contain both a list
46  * and an editable text field, it is possible to confuse methods
47  * which access one versus the other (compare for example,
48  * <code>clearSelection()</code> and <code>deselectAll()</code>).
49  * The API documentation is careful to indicate either "the
50  * receiver's list" or the "the receiver's text field" to
51  * distinguish between the two cases.
52  * </p><p>
53  * Note that although this class is a subclass of <code>Composite</code>,
54  * it does not make sense to add children to it, or set a layout on it.
55  * </p>
56  * <dl>
57  * <dt><b>Styles:</b></dt>
58  * <dd>DROP_DOWN, READ_ONLY, SIMPLE</dd>
59  * <dt><b>Events:</b></dt>
60  * <dd>DefaultSelection, Modify, Selection, Verify</dd>
61  * </dl>
62  * <p>
63  * Note: Only one of the styles DROP_DOWN and SIMPLE may be specified.
64  * </p><p>
65  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
66  * </p>
67  *
68  * @see List
69  * @see <a href="http://www.eclipse.org/swt/snippets/#combo">Combo snippets</a>
70  * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: ControlExample</a>
71  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
72  */
73
74 public class Combo : Composite {
75
76     alias Composite.computeSize computeSize;
77     alias Composite.dragDetect dragDetect;
78     alias Composite.sendKeyEvent sendKeyEvent;
79     alias Composite.setBackgroundImage setBackgroundImage;
80     alias Composite.setBounds setBounds;
81     alias Composite.setToolTipText setToolTipText;
82
83     private static Combo pThis;
84     bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize;
85     HHOOK cbtHook;
86     int scrollWidth, visibleCount = 5;
87
88     /**
89      * the operating system limit for the number of characters
90      * that the text field in an instance of this class can hold
91      */
92     private static int LIMIT_ = 0;
93
94     /*
95      * These values can be different on different platforms.
96      * Therefore they are not initialized in the declaration
97      * to stop the compiler from inlining.
98      */
99     public static int LIMIT(){
100         if( LIMIT_ is 0 ){
101             synchronized {
102                 LIMIT_ = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
103             }
104         }
105         return LIMIT_;
106     }
107     /*
108      * These are the undocumented control id's for the children of
109      * a combo box.  Since there are no constants for these values,
110      * they may change with different versions of Windows (but have
111      * been the same since Windows 3.0).
112      */
113     static const int CBID_LIST = 1000;
114     static const int CBID_EDIT = 1001;
115     static /*final*/ WNDPROC EditProc, ListProc;
116
117     static /+const+/ WNDPROC ComboProc;
118     static const TCHAR* ComboClass = "COMBOBOX\0";
119
120     private static bool static_this_completed = false;
121     private static void static_this() {
122         if( static_this_completed ){
123             return;
124         }
125         synchronized {
126             if( static_this_completed ){
127                 return;
128             }
129             WNDCLASS lpWndClass;
130             OS.GetClassInfo (null, ComboClass, &lpWndClass);
131             ComboProc = lpWndClass.lpfnWndProc;
132             static_this_completed = true;
133         }
134     }
135
136
137 /**
138  * Constructs a new instance of this class given its parent
139  * and a style value describing its behavior and appearance.
140  * <p>
141  * The style value is either one of the style constants defined in
142  * class <code>DWT</code> which is applicable to instances of this
143  * class, or must be built by <em>bitwise OR</em>'ing together
144  * (that is, using the <code>int</code> "|" operator) two or more
145  * of those <code>DWT</code> style constants. The class description
146  * lists the style constants that are applicable to the class.
147  * Style bits are also inherited from superclasses.
148  * </p>
149  *
150  * @param parent a composite control which will be the parent of the new instance (cannot be null)
151  * @param style the style of control to construct
152  *
153  * @exception IllegalArgumentException <ul>
154  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
155  * </ul>
156  * @exception DWTException <ul>
157  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
158  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
159  * </ul>
160  *
161  * @see DWT#DROP_DOWN
162  * @see DWT#READ_ONLY
163  * @see DWT#SIMPLE
164  * @see Widget#checkSubclass
165  * @see Widget#getStyle
166  */
167 public this (Composite parent, int style) {
168     static_this();
169     super (parent, checkStyle (style));
170     /* This code is intentionally commented */
171     //if ((style & DWT.H_SCROLL) !is 0) this.style |= DWT.H_SCROLL;
172     this.style |= DWT.H_SCROLL;
173 }
174
175 /**
176  * Adds the argument to the end of the receiver's list.
177  *
178  * @param string the new item
179  *
180  * @exception DWTException <ul>
181  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
182  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
183  * </ul>
184  *
185  * @see #add(String,int)
186  */
187 public void add (String string) {
188     checkWidget ();
189     // DWT extension: allow null string
190     //if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
191     auto buffer = StrToTCHARs( getCodePage(), string, true );
192     int result = OS.SendMessage (handle, OS.CB_ADDSTRING, 0, buffer.ptr );
193     if (result is OS.CB_ERR) error (DWT.ERROR_ITEM_NOT_ADDED);
194     if (result is OS.CB_ERRSPACE) error (DWT.ERROR_ITEM_NOT_ADDED);
195     if ((style & DWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
196 }
197
198 /**
199  * Adds the argument to the receiver's list at the given
200  * zero-relative index.
201  * <p>
202  * Note: To add an item at the end of the list, use the
203  * result of calling <code>getItemCount()</code> as the
204  * index or use <code>add(String)</code>.
205  * </p>
206  *
207  * @param string the new item
208  * @param index the index for the item
209  *
210  * @exception IllegalArgumentException <ul>
211  *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list (inclusive)</li>
212  * </ul>
213  * @exception DWTException <ul>
214  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
215  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
216  * </ul>
217  *
218  * @see #add(String)
219  */
220 public void add (String string, int index) {
221     checkWidget ();
222     // DWT extension: allow null string
223     //if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
224     int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
225     if (!(0 <= index && index <= count)) {
226         error (DWT.ERROR_INVALID_RANGE);
227     }
228     auto buffer = StrToTCHARs( getCodePage(), string, true );
229     int result = OS.SendMessage (handle, OS.CB_INSERTSTRING, index, buffer.ptr);
230     if (result is OS.CB_ERRSPACE || result is OS.CB_ERR) {
231         error (DWT.ERROR_ITEM_NOT_ADDED);
232     }
233     if ((style & DWT.H_SCROLL) !is 0) setScrollWidth (buffer, true);
234 }
235
236 /**
237  * Adds the listener to the collection of listeners who will
238  * be notified when the receiver's text is modified, by sending
239  * it one of the messages defined in the <code>ModifyListener</code>
240  * interface.
241  *
242  * @param listener the listener which should be notified
243  *
244  * @exception IllegalArgumentException <ul>
245  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
246  * </ul>
247  * @exception DWTException <ul>
248  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
249  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
250  * </ul>
251  *
252  * @see ModifyListener
253  * @see #removeModifyListener
254  */
255 public void addModifyListener (ModifyListener listener) {
256     checkWidget ();
257     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
258     TypedListener typedListener = new TypedListener (listener);
259     addListener (DWT.Modify, typedListener);
260 }
261
262 /**
263  * Adds the listener to the collection of listeners who will
264  * be notified when the user changes the receiver's selection, by sending
265  * it one of the messages defined in the <code>SelectionListener</code>
266  * interface.
267  * <p>
268  * <code>widgetSelected</code> is called when the user changes the combo's list selection.
269  * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed the combo's text area.
270  * </p>
271  *
272  * @param listener the listener which should be notified
273  *
274  * @exception IllegalArgumentException <ul>
275  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
276  * </ul>
277  * @exception DWTException <ul>
278  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
279  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
280  * </ul>
281  *
282  * @see SelectionListener
283  * @see #removeSelectionListener
284  * @see SelectionEvent
285  */
286 public void addSelectionListener(SelectionListener listener) {
287     checkWidget ();
288     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
289     TypedListener typedListener = new TypedListener (listener);
290     addListener (DWT.Selection,typedListener);
291     addListener (DWT.DefaultSelection,typedListener);
292 }
293
294 /**
295  * Adds the listener to the collection of listeners who will
296  * be notified when the receiver's text is verified, by sending
297  * it one of the messages defined in the <code>VerifyListener</code>
298  * interface.
299  *
300  * @param listener the listener which should be notified
301  *
302  * @exception IllegalArgumentException <ul>
303  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
304  * </ul>
305  * @exception DWTException <ul>
306  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
307  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
308  * </ul>
309  *
310  * @see VerifyListener
311  * @see #removeVerifyListener
312  *
313  * @since 3.1
314  */
315 public void addVerifyListener (VerifyListener listener) {
316     checkWidget ();
317     if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
318     TypedListener typedListener = new TypedListener (listener);
319     addListener (DWT.Verify, typedListener);
320 }
321
322 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
323     if (handle is null) return 0;
324     if (hwnd is handle) {
325         switch (msg) {
326             case OS.WM_SIZE: {
327                 ignoreResize = true;
328                 int /*long*/ result = OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam);
329                 ignoreResize = false;
330                 return result;
331             default:
332             }
333         }
334         return OS.CallWindowProc( ComboProc, hwnd, msg, wParam, lParam);
335     }
336     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
337     if (hwnd is hwndText) {
338         return OS.CallWindowProc( EditProc, hwnd, msg, wParam, lParam);
339     }
340     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
341     if (hwnd is hwndList) {
342         return OS.CallWindowProc( ListProc, hwnd, msg, wParam, lParam);
343     }
344     return OS.DefWindowProc (hwnd, msg, wParam, lParam);
345 }
346
347 private static extern(Windows) int CBTFunc (int nCode, uint wParam, int lParam) {
348     return pThis.CBTProc( nCode, wParam, lParam );
349 }
350
351 int CBTProc (int nCode, int wParam, int lParam) {
352     if (nCode is OS.HCBT_CREATEWND) {
353         TCHAR[128] buffer = 0;
354         OS.GetClassName (cast(HANDLE)wParam, buffer.ptr, buffer.length );
355         String className = TCHARzToStr(buffer.ptr);
356         if (className=="Edit" || className=="EDIT") { //$NON-NLS-1$  //$NON-NLS-2$
357             int bits = OS.GetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE);
358             OS.SetWindowLong (cast(HANDLE)wParam, OS.GWL_STYLE, bits & ~OS.ES_NOHIDESEL);
359         }
360     }
361     return OS.CallNextHookEx (cbtHook, nCode, wParam, lParam);
362 }
363
364 override bool checkHandle (HWND hwnd) {
365     return hwnd is handle || hwnd is OS.GetDlgItem (handle, CBID_EDIT) || hwnd is OS.GetDlgItem (handle, CBID_LIST);
366 }
367
368 override protected void checkSubclass () {
369     if (!isValidSubclass ()) error (DWT.ERROR_INVALID_SUBCLASS);
370 }
371
372 static int checkStyle (int style) {
373     /*
374      * Feature in Windows.  It is not possible to create
375      * a combo box that has a border using Windows style
376      * bits.  All combo boxes draw their own border and
377      * do not use the standard Windows border styles.
378      * Therefore, no matter what style bits are specified,
379      * clear the BORDER bits so that the DWT style will
380      * match the Windows widget.
381      *
382      * The Windows behavior is currently implemented on
383      * all platforms.
384      */
385     style &= ~DWT.BORDER;
386
387     /*
388      * Even though it is legal to create this widget
389      * with scroll bars, they serve no useful purpose
390      * because they do not automatically scroll the
391      * widget's client area.  The fix is to clear
392      * the DWT style.
393      */
394     style &= ~(DWT.H_SCROLL | DWT.V_SCROLL);
395     style = checkBits (style, DWT.DROP_DOWN, DWT.SIMPLE, 0, 0, 0, 0);
396     if ((style & DWT.SIMPLE) !is 0) return style & ~DWT.READ_ONLY;
397     return style;
398 }
399
400 /**
401  * Sets the selection in the receiver's text field to an empty
402  * selection starting just before the first character. If the
403  * text field is editable, this has the effect of placing the
404  * i-beam at the start of the text.
405  * <p>
406  * Note: To clear the selected items in the receiver's list,
407  * use <code>deselectAll()</code>.
408  * </p>
409  *
410  * @exception DWTException <ul>
411  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
412  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
413  * </ul>
414  *
415  * @see #deselectAll
416  */
417 public void clearSelection () {
418     checkWidget ();
419     OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, -1);
420 }
421
422 override public Point computeSize (int wHint, int hHint, bool changed) {
423     checkWidget ();
424     int width = 0, height = 0;
425     if (wHint is DWT.DEFAULT) {
426         HFONT newFont, oldFont;
427         auto hDC = OS.GetDC (handle);
428         newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
429         if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
430         int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
431         RECT rect;
432         int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
433         if ((style & DWT.READ_ONLY) is 0) flags |= OS.DT_EDITCONTROL;
434         int length_ = OS.GetWindowTextLength (handle);
435         int cp = getCodePage ();
436         TCHAR[] buffer = new TCHAR[ length_ + 1];
437         buffer[] = 0;
438         OS.GetWindowText (handle, buffer.ptr, length_ + 1);
439         OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
440         width = Math.max (width, rect.right - rect.left);
441         if ((style & DWT.H_SCROLL) !is 0) {
442             width = Math.max (width, scrollWidth);
443         } else {
444             for (int i=0; i<count; i++) {
445                 length_ = OS.SendMessage (handle, OS.CB_GETLBTEXTLEN, i, 0);
446                 if (length_ !is OS.CB_ERR) {
447                     if (length_ + 1 > buffer.length ) buffer = new TCHAR[ length_ + 1 ], buffer[] =0;
448                     int result = OS.SendMessage (handle, OS.CB_GETLBTEXT, i, buffer.ptr);
449                     if (result !is OS.CB_ERR) {
450                         OS.DrawText (hDC, buffer.ptr, length_, &rect, flags);
451                         width = Math.max (width, rect.right - rect.left);
452                     }
453                 }
454             }
455         }
456         if (newFont !is null) OS.SelectObject (hDC, oldFont);
457         OS.ReleaseDC (handle, hDC);
458     }
459     if (hHint is DWT.DEFAULT) {
460         if ((style & DWT.SIMPLE) !is 0) {
461             int count = OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0);
462             int itemHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, 0, 0);
463             height = count * itemHeight;
464         }
465     }
466     if (width is 0) width = DEFAULT_WIDTH;
467     if (height is 0) height = DEFAULT_HEIGHT;
468     if (wHint !is DWT.DEFAULT) width = wHint;
469     if (hHint !is DWT.DEFAULT) height = hHint;
470     if ((style & DWT.READ_ONLY) !is 0) {
471         width += 8;
472     } else {
473         auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
474         if (hwndText !is null) {
475             int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
476             int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
477             width += marginWidth + 3;
478         }
479     }
480     COMBOBOXINFO pcbi;
481     pcbi.cbSize = COMBOBOXINFO.sizeof;
482     if (((style & DWT.SIMPLE) is 0) && !OS.IsWinCE && OS.GetComboBoxInfo (handle, &pcbi)) {
483         width += pcbi.rcItem.left + (pcbi.rcButton.right - pcbi.rcButton.left);
484         height = (pcbi.rcButton.bottom - pcbi.rcButton.top) + pcbi.rcButton.top * 2;
485     } else {
486         int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
487         width += OS.GetSystemMetrics (OS.SM_CXVSCROLL) + border * 2;
488         int textHeight = OS.SendMessage (handle, OS.CB_GETITEMHEIGHT, -1, 0);
489         if ((style & DWT.DROP_DOWN) !is 0) {
490             height = textHeight + 6;
491         } else {
492             height += textHeight + 10;
493         }
494     }
495     if ((style & DWT.SIMPLE) !is 0 && (style & DWT.H_SCROLL) !is 0) {
496         height += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
497     }
498     return new Point (width, height);
499 }
500
501 /**
502  * Copies the selected text.
503  * <p>
504  * The current selection is copied to the clipboard.
505  * </p>
506  *
507  * @exception DWTException <ul>
508  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
509  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
510  * </ul>
511  *
512  * @since 2.1
513  */
514 public void copy () {
515     checkWidget ();
516     OS.SendMessage (handle, OS.WM_COPY, 0, 0);
517 }
518
519 override void createHandle () {
520     /*
521     * Feature in Windows.  When the selection changes in a combo box,
522     * Windows draws the selection, even when the combo box does not
523     * have focus.  Strictly speaking, this is the correct Windows
524     * behavior because the combo box sets ES_NOHIDESEL on the text
525     * control that it creates.  Despite this, it looks strange because
526     * Windows also clears the selection and selects all the text when
527     * the combo box gets focus.  The fix is use the CBT hook to clear
528     * the ES_NOHIDESEL style bit when the text control is created.
529     */
530     if (OS.IsWinCE || (style & (DWT.READ_ONLY | DWT.SIMPLE)) !is 0) {
531         super.createHandle ();
532     } else {
533         int threadId = OS.GetCurrentThreadId ();
534         //Callback cbtCallback = new Callback (this, "CBTProc", 3); //$NON-NLS-1$
535         //int cbtProc = cbtCallback.getAddress ();
536         //if (cbtProc is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
537         pThis = this;
538         cbtHook = OS.SetWindowsHookEx (OS.WH_CBT, &CBTFunc, null, threadId);
539         super.createHandle ();
540         if (cbtHook !is null) OS.UnhookWindowsHookEx (cbtHook);
541         pThis = null;
542         //cbtHook = 0;
543         //cbtCallback.dispose ();
544     }
545     state &= ~(CANVAS | THEME_BACKGROUND);
546
547     /* Get the text and list window procs */
548     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
549     if (hwndText !is null && EditProc is null) {
550         EditProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC);
551     }
552     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
553     if (hwndList !is null && ListProc is null) {
554         ListProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndList, OS.GWLP_WNDPROC);
555     }
556
557     /*
558     * Bug in Windows.  If the combo box has the CBS_SIMPLE style,
559     * the list portion of the combo box is not drawn correctly the
560     * first time, causing pixel corruption.  The fix is to ensure
561     * that the combo box has been resized more than once.
562     */
563     if ((style & DWT.SIMPLE) !is 0) {
564         int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
565         SetWindowPos (handle, null, 0, 0, 0x3FFF, 0x3FFF, flags);
566         SetWindowPos (handle, null, 0, 0, 0, 0, flags);
567     }
568 }
569
570 /**
571  * Cuts the selected text.
572  * <p>
573  * The current selection is first copied to the
574  * clipboard and then deleted from the widget.
575  * </p>
576  *
577  * @exception DWTException <ul>
578  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
579  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
580  * </ul>
581  *
582  * @since 2.1
583  */
584 public void cut () {
585     checkWidget ();
586     if ((style & DWT.READ_ONLY) !is 0) return;
587     OS.SendMessage (handle, OS.WM_CUT, 0, 0);
588 }
589
590 override int defaultBackground () {
591     return OS.GetSysColor (OS.COLOR_WINDOW);
592 }
593
594 override void deregister () {
595     super.deregister ();
596     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
597     if (hwndText !is null) display.removeControl (hwndText);
598     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
599     if (hwndList !is null) display.</