package org.eclipse.swt.widgets;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved
 */

import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * Instances of this class are controls which are capable
 * of containing other controls.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * <p>
 * This class may be subclassed by custom control implementors
 * who are building controls that are constructed from aggregates
 * of other controls.
 * </p>
 *
 * @see Canvas
 */

public class Composite extends Scrollable {
	Layout layout;
	int font, hdwp;
	Control [] tabList;
	
/**
 * Prevents uninitialized instances from being created outside the package.
 */
Composite () {
}

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together 
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * for all SWT widget classes should include a comment which
 * describes the style constants which are applicable to the class.
 * </p>
 *
 * @param parent a widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Composite (Composite parent, int style) {
	super (parent, style);
}
Control [] _getChildren () {
	int count = 0;
	int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
	if (hwndChild == 0) return new Control [0];
	while (hwndChild != 0) {
		count++;
		hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
	}
	Control [] children = new Control [count];
	int index = 0;
	hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
	while (hwndChild != 0) {
		Control control = WidgetTable.get (hwndChild);
		if (control != null && control != this) {
			children [index++] = control;
		}
		hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
	}
	if (count == index) return children;
	Control [] newChildren = new Control [index];
	System.arraycopy (children, 0, newChildren, 0, index);
	return newChildren;
}

Control [] _getTabList () {
	if (tabList == null) return tabList;
	int index = 0, count = 0;
	while (index < tabList.length) {
		if (!tabList [index].isDisposed ()) count++;
		index++;
	}
	if (index == count) return tabList;
	Control [] newList = new Control [count];
	index = 0;
	for (int i=0; i<tabList.length; i++) {
		if (!tabList [index].isDisposed ()) {
			newList [index++] = tabList [i];
		}
	}
	tabList = newList;
	return tabList;
}

protected void checkSubclass () {
	/* Do nothing - Subclassing is allowed */
}

Control [] computeTabList () {
	Control result [] = super.computeTabList ();
	if (result.length == 0) return result;
	Control [] list = tabList != null ? _getTabList () : _getChildren ();
	for (int i=0; i<list.length; i++) {
		Control child = list [i];
		Control [] childList = child.computeTabList ();
		if (childList.length != 0) {
			Control [] newResult = new Control [result.length + childList.length];
			System.arraycopy (result, 0, newResult, 0, result.length);
			System.arraycopy (childList, 0, newResult, result.length, childList.length);
			result = newResult;
		}
	}
	return result;
}

public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	Point size;
	if (layout != null) {
		if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
			size = layout.computeSize (this, wHint, hHint, changed);
		} else {
			size = new Point (wHint, hHint);
		}
	} else {
		size = minimumSize ();
	}
	if (size.x == 0) size.x = DEFAULT_WIDTH;
	if (size.y == 0) size.y = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) size.x = wHint;
	if (hHint != SWT.DEFAULT) size.y = hHint;
	Rectangle trim = computeTrim (0, 0, size.x, size.y);
	return new Point (trim.width, trim.height);
}

void createHandle () {
	super.createHandle ();
	state |= CANVAS;
}
void drawBackground (int hDC, RECT rect) {
	if ((state & CANVAS) != 0) {
		if ((style & SWT.NO_BACKGROUND) != 0) return;
	}
	super.drawBackground (hDC, rect);
}

/**
 * Returns an array containing the receiver's children.
 * <p>
 * Note: This is not the actual structure used by the receiver
 * to maintain its list of children, so modifying the array will
 * not affect the receiver. 
 * </p>
 *
 * @return an array of children
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Control [] getChildren () {
	checkWidget ();
	return _getChildren ();
}

int getChildrenCount () {
	/*
	* NOTE: The current implementation will count
	* non-registered children.
	*/
	int count = 0;
	int hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
	while (hwndChild != 0) {
		count++;
		hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
	}
	return count;
}

/**
 * Returns layout which is associated with the receiver, or
 * null if one has not been set.
 *
 * @return the receiver's layout or null
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Layout getLayout () {
	checkWidget ();
	return layout;
}

/**
 * Gets the last specified tabbing order for the control.
 *
 * @return tabList the ordered list of controls representing the tab order
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 * 
 * @see #setTabList
 */
public Control [] getTabList () {
	checkWidget ();
	Control [] tabList = _getTabList ();
	if (tabList == null) {
		int count = 0;
		Control [] list =_getChildren ();
		for (int i=0; i<list.length; i++) {
			if (list [i].isTabGroup ()) count++;
		}
		tabList = new Control [count];
		int index = 0;
		for (int i=0; i<list.length; i++) {
			if (list [i].isTabGroup ()) {
				tabList [index++] = list [i];
			}
		}
	}
	return tabList;
}

/**
 * If the receiver has a layout, asks the layout to <em>lay out</em>
 * (that is, set the size and location of) the receiver's children. 
 * If the receiver does not have a layout, do nothing.
 * <p>
 * This is equivalent to calling <code>layout(true)</code>.
 * </p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void layout () {
	checkWidget ();
	layout (true);
}

/**
 * If the receiver has a layout, asks the layout to <em>lay out</em>
 * (that is, set the size and location of) the receiver's children. 
 * If the the argument is <code>true</code> the layout must not rely
 * on any cached information it is keeping about the children. If it
 * is <code>false</code> the layout may (potentially) simplify the
 * work it is doing by assuming that the state of the none of the
 * receiver's children has changed since the last layout.
 * If the receiver does not have a layout, do nothing.
 *
 * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void layout (boolean changed) {
	checkWidget ();
	if (layout == null) return;
	int count = getChildrenCount ();
	if (count == 0) return;
	if (count > 1 && hdwp == 0) {
		hdwp = OS.BeginDeferWindowPos (count);
	}
	layout.layout (this, changed);
	int oldHdwp = hdwp;
	hdwp = 0;
	if (oldHdwp != 0) OS.EndDeferWindowPos (oldHdwp);
}

Point minimumSize () {
	Control [] children = _getChildren ();
	int width = 0, height = 0;
	for (int i=0; i<children.length; i++) {
		Rectangle rect = children [i].getBounds ();
		width = Math.max (width, rect.x + rect.width);
		height = Math.max (height, rect.y + rect.height);
	}
	return new Point (width, height);
}

void releaseChildren () {
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (!child.isDisposed ()) {
			child.releaseWidget ();
			child.releaseHandle ();
		}
	}
}

void releaseWidget () {
	releaseChildren ();
	super.releaseWidget ();
	layout = null;
	tabList = null;
	int oldHdwp = hdwp;
	hdwp = 0;
	if (oldHdwp != 0) OS.EndDeferWindowPos (oldHdwp);
}

public boolean setFocus () {
	checkWidget ();
	if ((style & SWT.NO_FOCUS) != 0) return false;
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.setRadioFocus ()) return true;
	}
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.setFocus ()) return true;
	}
	return super.setFocus ();
}

/**
 * Sets the layout which is associated with the receiver to be
 * the argument which may be null.
 *
 * @param layout the receiver's new layout or null
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setLayout (Layout layout) {
	checkWidget ();
	this.layout = layout;
}

/**
 * Sets the tabbing order for the specified controls to
 * match the order that they occur in the argument list.
 *
 * @param tabList the ordered list of controls representing the tab order; must not be null
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the tabList is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li> 
 *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setTabList (Control [] tabList) {
	checkWidget ();
	if (tabList == null) error (SWT.ERROR_NULL_ARGUMENT);
	for (int i=0; i<tabList.length; i++) {
		Control control = tabList [i];
		if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
		if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
//		Shell shell = control.getShell ();
//		while (control != shell && control != this) {
//			control = control.parent;
//		}
//		if (control != this) error (SWT.ERROR_INVALID_PARENT);
		if (control.parent != this) error (SWT.ERROR_INVALID_PARENT);
	}
	/*
	* This code is intentionally commented.  It is
	* not yet clear whether setting the tab list 
	* should force the widget to be a tab group
	* instead of a tab item or non-traversable.
	*/
//	Control [] children = _getChildren ();
//	for (int i=0; i<children.length; i++) {
//		Control control = children [i];
//		if (control != null) {
//			if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
//			int index = 0;
//			while (index < tabList.length) {
//				if (tabList [index] == control) break;
//				index++;
//			}
//			int hwnd = control.handle;
//			int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
//			if (index == tabList.length) {
//				bits &= ~OS.WS_TABSTOP;
//			} else {
//				bits |= OS.WS_TABSTOP;
//			}
//			OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits);
//		}
//	}
	this.tabList = tabList;
}

boolean setTabGroupFocus () {
	if (isTabItem ()) return setTabItemFocus ();
	if ((style & SWT.NO_FOCUS) == 0) {
		boolean takeFocus = true;
		if ((state & CANVAS) != 0) {
			takeFocus = hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
		}
		if (takeFocus && setTabItemFocus ()) return true;
	}
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.isVisible () && child.setRadioFocus ()) return true;
	}
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.isTabItem () && child.setTabItemFocus ()) return true;
	}
	return false;
}

boolean setTabItemFocus () {
	if ((style & SWT.NO_FOCUS) == 0) {
		boolean takeFocus = true;
		if ((state & CANVAS) != 0) {
			takeFocus = hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
		}
		if (takeFocus) {
			if (!isShowing ()) return false;
			if (forceFocus ()) return true;
		}
	}
	return super.setTabItemFocus ();
}

String toolTipText (NMTTDISPINFO hdr) {
	if ((hdr.uFlags & OS.TTF_IDISHWND) == 0) {
		return null;
	}
	int hwnd = hdr.idFrom;
	if (hwnd == 0) return null;
	Control control = WidgetTable.get (hwnd);
	if (control == null) return null;
	return control.toolTipText;
}

boolean translateMnemonic (char key) {
	if (super.translateMnemonic (key)) return true;
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.translateMnemonic (key)) return true;
	}
	return false;
}

void updateFont (Font oldFont, Font newFont) {
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control control = children [i];
		if (!control.isDisposed ()) {
			control.updateFont (oldFont, newFont);
		}
	}
	super.updateFont (oldFont, newFont);
	layout (true);
}

int widgetStyle () {
	/* Temporary code to force SWT.CLIP_SIBLINGS */
	return super.widgetStyle () | OS.WS_CLIPCHILDREN;
}

LRESULT WM_ERASEBKGND (int wParam, int lParam) {
	if ((state & CANVAS) != 0) {
		return super.WM_ERASEBKGND (wParam, lParam);
	}
	drawBackground (wParam);
	return LRESULT.ONE;
}

LRESULT WM_GETDLGCODE (int wParam, int lParam) {
	LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
	if (result != null) return result;
	if ((state & CANVAS) != 0) {
		if ((style & SWT.NO_FOCUS) != 0) return new LRESULT (OS.DLGC_STATIC);
		if (hooks (SWT.KeyDown) || hooks (SWT.KeyUp)) {
			int flags = OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
			return new LRESULT (flags);
		}
		int count = getChildrenCount ();
		if (count != 0) return new LRESULT (OS.DLGC_STATIC);
	}
	return result;
}

LRESULT WM_GETFONT (int wParam, int lParam) {
	LRESULT result = super.WM_GETFONT (wParam, lParam);
	if (result != null) return result;
	int code = callWindowProc (OS.WM_GETFONT, wParam, lParam);
	if (code != 0) return new LRESULT (code);
	if (font == 0) font = defaultFont ();
	return new LRESULT (font);
}

LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
	LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);

	/* Set focus for a canvas with no children */
	if ((state & CANVAS) != 0) {
		if ((style & SWT.NO_FOCUS) != 0) return result;
		if (OS.GetWindow (handle, OS.GW_CHILD) == 0) setFocus ();
	}
	return result;
}

LRESULT WM_NOTIFY (int wParam, int lParam) {
	if (!OS.IsWinCE) {
		NMHDR hdr = new NMHDR ();
		OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
		switch (hdr.code) {
			/*
			* Bug in Windows 98.  For some reason, the tool bar control
			* sends both TTN_GETDISPINFOW and TTN_GETDISPINFOA to get
			* the tool tip text and the tab folder control sends only 
			* TTN_GETDISPINFOW.  The fix is to handle only TTN_GETDISPINFOW,
			* even though it should never be sent on Windows 98.
			*
			* NOTE:  Because the size of NMTTDISPINFO differs between
			* Windows 98 and NT, guard against the case where the wrong
			* kind of message occurs by copy inlining the memory moves
			* and UNICODE conversion code.
			*/
			case OS.TTN_GETDISPINFOA: {
				NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
				OS.MoveMemoryA (lpnmtdi, lParam, NMTTDISPINFO.sizeofA);
				String string = toolTipText (lpnmtdi);
				if (string != null && string.length () != 0) {
					Shell shell = getShell ();
					string = Display.withCrLf (string);
					int length = string.length ();
					char [] chars = new char [length];
					string.getChars (0, length, chars, 0);
					byte [] bytes = new byte [chars.length * 2 + 1];
					OS.WideCharToMultiByte (OS.CP_ACP, 0, chars, chars.length, bytes, bytes.length, null, null);
					shell.setToolTipText (lpnmtdi, bytes);
					OS.MoveMemoryA (lParam, lpnmtdi, NMTTDISPINFO.sizeofA);
					return LRESULT.ZERO;
				}
				break;
			}
			case OS.TTN_GETDISPINFOW: {
				NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
				OS.MoveMemoryW (lpnmtdi, lParam, NMTTDISPINFO.sizeofW);
				String string = toolTipText (lpnmtdi);
				if (string != null && string.length () != 0) {
					Shell shell = getShell ();
					string = Display.withCrLf (string);
					int length = string.length ();
					char [] buffer = new char [length + 1];
					string.getChars (0, length, buffer, 0);
					shell.setToolTipText (lpnmtdi, buffer);
					OS.MoveMemoryW (lParam, lpnmtdi, NMTTDISPINFO.sizeofW);
					return LRESULT.ZERO;
				}
				break;
			}
		}
	}
	return super.WM_NOTIFY (wParam, lParam);
}

LRESULT WM_PAINT (int wParam, int lParam) {
	if ((state & CANVAS) == 0) {
		return super.WM_PAINT (wParam, lParam);
	}
	
	/*
	* This code is intentionally commented.  Don't exit
	* early because the background must still be painted,
	* even though no application code will be painting
	* the widget.
	*
	* Do not uncomment this code.
	*/
//	if (!hooks (SWT.Paint)) return null;

	/* Get the damage */
	int [] lpRgnData = null;
	boolean isComplex = false;
	boolean exposeRegion = false;
	if ((style & SWT.NO_MERGE_PAINTS) != 0) {
		int rgn = OS.CreateRectRgn (0, 0, 0, 0);
		isComplex = OS.GetUpdateRgn (handle, rgn, false) == OS.COMPLEXREGION;
		if (isComplex) {
			int nBytes = OS.GetRegionData (rgn, 0, null);
			lpRgnData = new int [nBytes / 4];
			exposeRegion = OS.GetRegionData (rgn, nBytes, lpRgnData) != 0;
		}
		OS.DeleteObject (rgn);
	}

	/* Set the clipping bits */
	int oldBits = 0;
	if (!OS.IsWinCE) {
		oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
		int newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;	
		OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
	}

	/* Create the paint GC */
	PAINTSTRUCT ps = new PAINTSTRUCT ();
	GCData data = new GCData ();
	data.ps = ps;
	GC gc = GC.win32_new (this, data);
	int hDC = gc.handle;
	
	/* Send the paint event */
	Event event = new Event ();
	event.gc = gc;
	if (isComplex && exposeRegion) {
		RECT rect = new RECT ();
		int nCount = lpRgnData [2];
		for (int i=0; i<nCount; i++) {
			OS.SetRect (rect,
				lpRgnData [8 + (i << 2)],
				lpRgnData [8 + (i << 2) + 1],
				lpRgnData [8 + (i << 2) + 2],
				lpRgnData [8 + (i << 2) + 3]);
			drawBackground (hDC, rect);	
			event.x = rect.left;
			event.y = rect.top;
			event.width = rect.right - rect.left;
			event.height = rect.bottom - rect.top;
			event.count = nCount - 1 - i;
			/*
			* It is possible (but unlikely), that application
			* code could have disposed the widget in the paint
			* event.  If this happens, attempt to give back the
			* paint GC anyways because this is a scarce Windows
			* resource.
			*/
			sendEvent (SWT.Paint, event);
			if (isDisposed ()) break;
		}
	} else {
		RECT rect = new RECT ();
		OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
		drawBackground (hDC, rect);
		event.x = ps.left;
		event.y = ps.top;
		event.width = ps.right - ps.left;
		event.height = ps.bottom - ps.top;
		sendEvent (SWT.Paint, event);
	}
	// widget could be disposed at this point

	/* Dispose the paint GC */
	event.gc = null;
	gc.dispose ();

	if (!OS.IsWinCE) { 
		/*
		* It is possible (but unlikely), that application
		* code could have disposed the widget in the paint
		* event.  If this happens, don't attempt to restore
		* the style.
		*/
		if (!isDisposed ()) {
			OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
		}
	}
	return LRESULT.ZERO;
}

LRESULT WM_SETFONT (int wParam, int lParam) {
	return super.WM_SETFONT (font = wParam, lParam);
}

LRESULT WM_SIZE (int wParam, int lParam) {
	/*
	* Begin deferred window positioning
	*/
	int count = getChildrenCount ();
	if (count > 1 && hdwp == 0) {
		hdwp = OS.BeginDeferWindowPos (count);
	}
	
	/* Layout and resize */
	if (layout != null) layout.layout (this, false);
	LRESULT result = super.WM_SIZE (wParam, lParam);
	
	/*
	* It is possible (but unlikely), that application
	* code could have disposed the widget in the resize
	* event.  If this happens, end the processing of the
	* Windows message by returning the result of the
	* WM_SIZE message.
	*/
	if (isDisposed ()) return result;
	
	/* End deferred window positioning */
	int oldHdwp = hdwp;
	hdwp = 0;
	if (oldHdwp != 0) OS.EndDeferWindowPos (oldHdwp);
	
	/* Damage the widget to cause a repaint */
	if ((state & CANVAS) != 0) {
		if ((style & SWT.NO_REDRAW_RESIZE) == 0) {
			if (hooks (SWT.Paint)) {
				OS.InvalidateRect (handle, null, true);
			}
		}
	}
	return result;
}

LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		int hwndChild = children [i].handle;
		OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
	}
	return null;
}

LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
	LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
	if (result != null) return result;
		
	/*
	* Check to see if the command is a system command or
	* a user menu item that was added to the system menu.
	*/
	if ((wParam & 0xF000) == 0) return result;

	/*
	* Bug in Windows.  When a vertical or horizontal scroll bar is
	* hidden or shown while the opposite scroll bar is being scrolled
	* by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
	* does not redraw properly.  The fix is to detect this case and
	* redraw the non-client area.
	*/
	if (!OS.IsWinCE) {
		int cmd = wParam & 0xFFF0;
		switch (cmd) {
			case OS.SC_HSCROLL:
			case OS.SC_VSCROLL:
				boolean showHBar = horizontalBar != null && horizontalBar.getVisible ();
				boolean showVBar = verticalBar != null && verticalBar.getVisible ();
				int code = callWindowProc (OS.WM_SYSCOMMAND, wParam, lParam);
				if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) ||
					(showVBar != (verticalBar != null && verticalBar.getVisible ()))) {
						int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
						OS.RedrawWindow (handle, null, 0, flags);
					}		
				if (code == 0) return LRESULT.ZERO;
				return new LRESULT (code);
		}
	}
	/* Return the result */
	return result;
}

}
