/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.widgets;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
/**
* Instances of this class support the layout of selectable
* tool bar items.
*
* The item children that may be added to instances of this class
* must be of type ToolItem
.
*
* Note that although this class is a subclass of Composite
,
* it does not make sense to add Control
children to it,
* or set a layout on it.
*
*
* - Styles:
* - FLAT, WRAP, RIGHT, HORIZONTAL, VERTICAL, SHADOW_OUT
* - Events:
* - (none)
*
*
* Note: Only one of the styles HORIZONTAL and VERTICAL may be specified.
*
* IMPORTANT: This class is not intended to be subclassed.
*
*
* @see ToolBar, ToolItem snippets
* @see SWT Example: ControlExample
* @see Sample code and further information
*/
public class ToolBar extends Composite {
int lastFocusId;
ToolItem [] items;
boolean ignoreResize, ignoreMouse;
ImageList imageList, disabledImageList, hotImageList;
static final int /*long*/ ToolBarProc;
static final TCHAR ToolBarClass = new TCHAR (0, OS.TOOLBARCLASSNAME, true);
static {
WNDCLASS lpWndClass = new WNDCLASS ();
OS.GetClassInfo (0, ToolBarClass, lpWndClass);
ToolBarProc = lpWndClass.lpfnWndProc;
}
/*
* From the Windows SDK for TB_SETBUTTONSIZE:
*
* "If an application does not explicitly
* set the button size, the size defaults
* to 24 by 22 pixels".
*/
static final int DEFAULT_WIDTH = 24;
static final int DEFAULT_HEIGHT = 22;
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
*
* The style value is either one of the style constants defined in
* class SWT
which is applicable to instances of this
* class, or must be built by bitwise OR'ing together
* (that is, using the int
"|" operator) two or more
* of those SWT
style constants. The class description
* lists the style constants that are applicable to the class.
* Style bits are also inherited from superclasses.
*
*
* @param parent a composite control which will be the parent of the new instance (cannot be null)
* @param style the style of control to construct
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the parent is null
*
* @exception SWTException
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
* - ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
*
*
* @see SWT#FLAT
* @see SWT#WRAP
* @see SWT#RIGHT
* @see SWT#HORIZONTAL
* @see SWT#SHADOW_OUT
* @see SWT#VERTICAL
* @see Widget#checkSubclass()
* @see Widget#getStyle()
*/
public ToolBar (Composite parent, int style) {
super (parent, checkStyle (style));
/*
* Ensure that either of HORIZONTAL or VERTICAL is set.
* NOTE: HORIZONTAL and VERTICAL have the same values
* as H_SCROLL and V_SCROLL so it is necessary to first
* clear these bits to avoid scroll bars and then reset
* the bits using the original style supplied by the
* programmer.
*
* NOTE: The CCS_VERT style cannot be applied when the
* widget is created because of this conflict.
*/
if ((style & SWT.VERTICAL) != 0) {
this.style |= SWT.VERTICAL;
int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
/*
* Feature in Windows. When a tool bar has the style
* TBSTYLE_LIST and has a drop down item, Window leaves
* too much padding around the button. This affects
* every button in the tool bar and makes the preferred
* height too big. The fix is to set the TBSTYLE_LIST
* when the tool bar contains both text and images.
*
* NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
* set before any item is added or the tool bar does
* not lay out properly. The work around does not run
* in this case.
*/
if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
if ((style & SWT.RIGHT) != 0) bits |= OS.TBSTYLE_LIST;
}
OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.CCS_VERT);
} else {
this.style |= SWT.HORIZONTAL;
}
}
int /*long*/ callWindowProc (int /*long*/ hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) {
if (handle == 0) return 0;
/*
* Bug in Windows. For some reason, during the processing
* of WM_SYSCHAR, the tool bar window proc does not call the
* default window proc causing mnemonics for the menu bar
* to be ignored. The fix is to always call the default
* window proc for WM_SYSCHAR.
*/
if (msg == OS.WM_SYSCHAR) {
return OS.DefWindowProc (hwnd, msg, wParam, lParam);
}
return OS.CallWindowProc (ToolBarProc, hwnd, msg, wParam, lParam);
}
static int checkStyle (int style) {
/*
* On Windows, only flat tool bars can be traversed.
*/
if ((style & SWT.FLAT) == 0) style |= SWT.NO_FOCUS;
/*
* A vertical tool bar cannot wrap because TB_SETROWS
* fails when the toolbar has TBSTYLE_WRAPABLE.
*/
if ((style & SWT.VERTICAL) != 0) style &= ~SWT.WRAP;
/*
* Even though it is legal to create this widget
* with scroll bars, they serve no useful purpose
* because they do not automatically scroll the
* widget's client area. The fix is to clear
* the SWT style.
*/
return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
}
void checkBuffered () {
super.checkBuffered ();
if (OS.COMCTL32_MAJOR >= 6) style |= SWT.DOUBLE_BUFFERED;
}
protected void checkSubclass () {
if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}
public Point computeSize (int wHint, int hHint, boolean changed) {
checkWidget ();
int width = 0, height = 0;
if ((style & SWT.VERTICAL) != 0) {
RECT rect = new RECT ();
TBBUTTON lpButton = new TBBUTTON ();
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
for (int i=0; i= 6) bits |= OS.TBSTYLE_EX_DOUBLEBUFFER;
OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
}
void createItem (ToolItem item, int index) {
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
if (!(0 <= index && index <= count)) error (SWT.ERROR_INVALID_RANGE);
int id = 0;
while (id < items.length && items [id] != null) id++;
if (id == items.length) {
ToolItem [] newItems = new ToolItem [items.length + 4];
System.arraycopy (items, 0, newItems, 0, items.length);
items = newItems;
}
int bits = item.widgetStyle ();
TBBUTTON lpButton = new TBBUTTON ();
lpButton.idCommand = id;
lpButton.fsStyle = (byte) bits;
lpButton.fsState = (byte) OS.TBSTATE_ENABLED;
/*
* Bug in Windows. Despite the fact that the image list
* index has never been set for the item, Windows always
* assumes that the image index for the item is valid.
* When an item is inserted, the image index is zero.
* Therefore, when the first image is inserted and is
* assigned image index zero, every item draws with this
* image. The fix is to set the image index to none
* when the item is created. This is not necessary in
* the case when the item has the BTNS_SEP style because
* separators cannot show images.
*/
if ((bits & OS.BTNS_SEP) == 0) lpButton.iBitmap = OS.I_IMAGENONE;
if (OS.SendMessage (handle, OS.TB_INSERTBUTTON, index, lpButton) == 0) {
error (SWT.ERROR_ITEM_NOT_ADDED);
}
items [item.id = id] = item;
if ((style & SWT.VERTICAL) != 0) setRowCount (count + 1);
layoutItems ();
}
void createWidget () {
super.createWidget ();
items = new ToolItem [4];
lastFocusId = -1;
}
int defaultBackground () {
if (OS.IsWinCE) return OS.GetSysColor (OS.COLOR_BTNFACE);
return super.defaultBackground ();
}
void destroyItem (ToolItem item) {
TBBUTTONINFO info = new TBBUTTONINFO ();
info.cbSize = TBBUTTONINFO.sizeof;
info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE;
int index = (int)/*64*/OS.SendMessage (handle, OS.TB_GETBUTTONINFO, item.id, info);
/*
* Feature in Windows. For some reason, a tool item that has
* the style BTNS_SEP does not return I_IMAGENONE when queried
* for an image index, despite the fact that no attempt has been
* made to assign an image to the item. As a result, operations
* on an image list that use the wrong index cause random results.
* The fix is to ensure that the tool item is not a separator
* before using the image index. Since separators cannot have
* an image and one is never assigned, this is not a problem.
*/
if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) {
if (imageList != null) imageList.put (info.iImage, null);
if (hotImageList != null) hotImageList.put (info.iImage, null);
if (disabledImageList != null) disabledImageList.put (info.iImage, null);
}
OS.SendMessage (handle, OS.TB_DELETEBUTTON, index, 0);
if (item.id == lastFocusId) lastFocusId = -1;
items [item.id] = null;
item.id = -1;
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
if (count == 0) {
if (imageList != null) {
OS.SendMessage (handle, OS.TB_SETIMAGELIST, 0, 0);
display.releaseToolImageList (imageList);
}
if (hotImageList != null) {
OS.SendMessage (handle, OS.TB_SETHOTIMAGELIST, 0, 0);
display.releaseToolHotImageList (hotImageList);
}
if (disabledImageList != null) {
OS.SendMessage (handle, OS.TB_SETDISABLEDIMAGELIST, 0, 0);
display.releaseToolDisabledImageList (disabledImageList);
}
imageList = hotImageList = disabledImageList = null;
items = new ToolItem [4];
}
if ((style & SWT.VERTICAL) != 0) setRowCount (count - 1);
layoutItems ();
}
void enableWidget (boolean enabled) {
super.enableWidget (enabled);
/*
* Bug in Windows. When a tool item with the style
* BTNS_CHECK or BTNS_CHECKGROUP is selected and then
* disabled, the item does not draw using the disabled
* image. The fix is to use the disabled image in all
* image lists for the item.
*
* Feature in Windows. When a tool bar is disabled,
* the text draws disabled but the images do not.
* The fix is to use the disabled image in all image
* lists for all items.
*/
for (int i=0; i
* ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public ToolItem getItem (int index) {
checkWidget ();
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
if (!(0 <= index && index < count)) error (SWT.ERROR_INVALID_RANGE);
TBBUTTON lpButton = new TBBUTTON ();
int /*long*/ result = OS.SendMessage (handle, OS.TB_GETBUTTON, index, lpButton);
if (result == 0) error (SWT.ERROR_CANNOT_GET_ITEM);
return items [lpButton.idCommand];
}
/**
* Returns the item at the given point in the receiver
* or null if no such item exists. The point is in the
* coordinate system of the receiver.
*
* @param point the point used to locate the item
* @return the item at the given point
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the point is null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public ToolItem getItem (Point point) {
checkWidget ();
if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
ToolItem [] items = getItems ();
for (int i=0; i
* ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public int getItemCount () {
checkWidget ();
return (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
}
/**
* Returns an array of ToolItem
s which are the items
* in the receiver.
*
* Note: This is not the actual structure used by the receiver
* to maintain its list of items, so modifying the array will
* not affect the receiver.
*
*
* @return the items in the receiver
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public ToolItem [] getItems () {
checkWidget ();
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
TBBUTTON lpButton = new TBBUTTON ();
ToolItem [] result = new ToolItem [count];
for (int i=0; iWRAP style, the
* number of rows can be greater than one. Otherwise,
* the number of rows is always one.
*
* @return the number of items
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public int getRowCount () {
checkWidget ();
if ((style & SWT.VERTICAL) != 0) {
return (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
}
return (int)/*64*/OS.SendMessage (handle, OS.TB_GETROWS, 0, 0);
}
/**
* Searches the receiver's list starting at the first item
* (index 0) until an item is found that is equal to the
* argument, and returns the index of that item. If no item
* is found, returns -1.
*
* @param item the search item
* @return the index of the item
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the tool item is null
* - ERROR_INVALID_ARGUMENT - if the tool item has been disposed
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public int indexOf (ToolItem item) {
checkWidget ();
if (item == null) error (SWT.ERROR_NULL_ARGUMENT);
if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
return (int)/*64*/OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, item.id, 0);
}
void layoutItems () {
/*
* Feature in Windows. When a tool bar has the style
* TBSTYLE_LIST and has a drop down item, Window leaves
* too much padding around the button. This affects
* every button in the tool bar and makes the preferred
* height too big. The fix is to set the TBSTYLE_LIST
* when the tool bar contains both text and images.
*
* NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
* set before any item is added or the tool bar does
* not lay out properly. The work around does not run
* in this case.
*/
if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
if ((style & SWT.RIGHT) != 0 && (style & SWT.VERTICAL) == 0) {
boolean hasText = false, hasImage = false;
for (int i=0; i= 6 && OS.IsAppThemed ()) {
boolean hasText = false, hasImage = false;
for (int i=0; i= 6 && OS.IsAppThemed ()) bits |= OS.TBSTYLE_TRANSPARENT;
if ((style & SWT.SHADOW_OUT) == 0) bits |= OS.CCS_NODIVIDER;
if ((style & SWT.WRAP) != 0) bits |= OS.TBSTYLE_WRAPABLE;
if ((style & SWT.FLAT) != 0) bits |= OS.TBSTYLE_FLAT;
/*
* Feature in Windows. When a tool bar has the style
* TBSTYLE_LIST and has a drop down item, Window leaves
* too much padding around the button. This affects
* every button in the tool bar and makes the preferred
* height too big. The fix is to set the TBSTYLE_LIST
* when the tool bar contains both text and images.
*
* NOTE: Tool bars with CCS_VERT must have TBSTYLE_LIST
* set before any item is added or the tool bar does
* not lay out properly. The work around does not run
* in this case.
*/
if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
if ((style & SWT.RIGHT) != 0) bits |= OS.TBSTYLE_LIST;
}
return bits;
}
TCHAR windowClass () {
return ToolBarClass;
}
int /*long*/ windowProc () {
return ToolBarProc;
}
LRESULT WM_CAPTURECHANGED (int /*long*/ wParam, int /*long*/ lParam) {
LRESULT result = super.WM_CAPTURECHANGED (wParam, lParam);
if (result != null) return result;
/*
* Bug in Windows. When the tool bar loses capture while an
* item is pressed, the item remains pressed. The fix is
* unpress all items using TB_SETSTATE and TBSTATE_PRESSED.
*/
for (int i=0; i= 6) {
TOOLINFO lpti = new TOOLINFO ();
lpti.cbSize = TOOLINFO.sizeof;
int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) {
OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
}
}
}
return result;
}
LRESULT WM_NOTIFY (int /*long*/ wParam, int /*long*/ lParam) {
/*
* Feature in Windows. When the toolbar window
* proc processes WM_NOTIFY, it forwards this
* message to its parent. This is done so that
* children of this control that send this message
* type to their parent will notify not only
* this control but also the parent of this control,
* which is typically the application window and
* the window that is looking for the message.
* If the control did not forward the message,
* applications would have to subclass the control
* window to see the message. Because the control
* window is subclassed by SWT, the message
* is delivered twice, once by SWT and once when
* the message is forwarded by the window proc.
* The fix is to avoid calling the window proc
* for this control.
*/
LRESULT result = super.WM_NOTIFY (wParam, lParam);
if (result != null) return result;
return LRESULT.ZERO;
}
LRESULT WM_SETFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
LRESULT result = super.WM_SETFOCUS (wParam, lParam);
if (lastFocusId != -1 && handle == OS.GetFocus ()) {
int index = (int)/*64*/OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lastFocusId, 0);
OS.SendMessage (handle, OS.TB_SETHOTITEM, index, 0);
}
return result;
}
LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) {
if (ignoreResize) {
int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
if (code == 0) return LRESULT.ZERO;
return new LRESULT (code);
}
LRESULT result = super.WM_SIZE (wParam, lParam);
if (isDisposed ()) return result;
/*
* Bug in Windows. The code in Windows that determines
* when tool items should wrap seems to use the window
* bounds rather than the client area. Unfortunately,
* tool bars with the style TBSTYLE_EX_HIDECLIPPEDBUTTONS
* use the client area. This means that buttons which
* overlap the border are hidden before they are wrapped.
* The fix is to compute TBSTYLE_EX_HIDECLIPPEDBUTTONS
* and set it each time the tool bar is resized.
*/
if ((style & SWT.BORDER) != 0 && (style & SWT.WRAP) != 0) {
RECT windowRect = new RECT ();
OS.GetWindowRect (handle, windowRect);
int index = 0, border = getBorderWidth () * 2;
RECT rect = new RECT ();
int count = (int)/*64*/OS.SendMessage (handle, OS.TB_BUTTONCOUNT, 0, 0);
while (index < count) {
OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
OS.MapWindowPoints (handle, 0, rect, 2);
if (rect.right > windowRect.right - border * 2) break;
index++;
}
int bits = (int)/*64*/OS.SendMessage (handle, OS.TB_GETEXTENDEDSTYLE, 0, 0);
if (index == count) {
bits |= OS.TBSTYLE_EX_HIDECLIPPEDBUTTONS;
} else {
bits &= ~OS.TBSTYLE_EX_HIDECLIPPEDBUTTONS;
}
OS.SendMessage (handle, OS.TB_SETEXTENDEDSTYLE, 0, bits);
}
layoutItems ();
return result;
}
LRESULT WM_WINDOWPOSCHANGING (int /*long*/ wParam, int /*long*/ lParam) {
LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
if (result != null) return result;
if (ignoreResize) return result;
/*
* Bug in Windows. When a flat tool bar is wrapped,
* Windows draws a horizontal separator between the
* rows. The tool bar does not draw the first or
* the last two pixels of this separator. When the
* toolbar is resized to be bigger, only the new
* area is drawn and the last two pixels, which are
* blank are drawn over by separator. This leaves
* garbage on the screen. The fix is to damage the
* pixels.
*/
if (drawCount != 0) return result;
if ((style & SWT.WRAP) == 0) return result;
if (!OS.IsWindowVisible (handle)) return result;
if (OS.SendMessage (handle, OS.TB_GETROWS, 0, 0) == 1) {
return result;
}
WINDOWPOS lpwp = new WINDOWPOS ();
OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
if ((lpwp.flags & (OS.SWP_NOSIZE | OS.SWP_NOREDRAW)) != 0) {
return result;
}
RECT oldRect = new RECT ();
OS.GetClientRect (handle, oldRect);
RECT newRect = new RECT ();
OS.SetRect (newRect, 0, 0, lpwp.cx, lpwp.cy);
OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, newRect);
int oldWidth = oldRect.right - oldRect.left;
int newWidth = newRect.right - newRect.left;
if (newWidth > oldWidth) {
RECT rect = new RECT ();
int newHeight = newRect.bottom - newRect.top;
OS.SetRect (rect, oldWidth - 2, 0, oldWidth, newHeight);
OS.InvalidateRect (handle, rect, false);
}
return result;
}
LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
ToolItem child = items [OS.LOWORD (wParam)];
if (child == null) return null;
return child.wmCommandChild (wParam, lParam);
}
LRESULT wmNotifyChild (NMHDR hdr, int /*long*/ wParam, int /*long*/ lParam) {
switch (hdr.code) {
case OS.TBN_DROPDOWN:
NMTOOLBAR lpnmtb = new NMTOOLBAR ();
OS.MoveMemory (lpnmtb, lParam, NMTOOLBAR.sizeof);
ToolItem child = items [lpnmtb.iItem];
if (child != null) {
Event event = new Event ();
event.detail = SWT.ARROW;
int index = (int)/*64*/OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmtb.iItem, 0);
RECT rect = new RECT ();
OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
event.x = rect.left;
event.y = rect.bottom;
child.postEvent (SWT.Selection, event);
}
break;
case OS.NM_CUSTOMDRAW:
if (OS.COMCTL32_MAJOR < 6) break;
/*
* Bug in Windows. For some reason, under the XP Silver
* theme, tool bars continue to draw using the gray color
* from the default Blue theme. The fix is to draw the
* background.
*/
NMCUSTOMDRAW nmcd = new NMCUSTOMDRAW ();
OS.MoveMemory (nmcd, lParam, NMCUSTOMDRAW.sizeof);
// if (drawCount != 0 || !OS.IsWindowVisible (handle)) {
// if (!OS.IsWinCE && OS.WindowFromDC (nmcd.hdc) == handle) break;
// }
switch (nmcd.dwDrawStage) {
case OS.CDDS_PREERASE: {
/*
* Bug in Windows. When a tool bar does not have the style
* TBSTYLE_FLAT, the rectangle to be erased in CDDS_PREERASE
* is empty. The fix is to draw the whole client area.
*/
int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
if ((bits & OS.TBSTYLE_FLAT) == 0) {
drawBackground (nmcd.hdc);
} else {
RECT rect = new RECT ();
OS.SetRect (rect, nmcd.left, nmcd.top, nmcd.right, nmcd.bottom);
drawBackground (nmcd.hdc, rect);
}
return new LRESULT (OS.CDRF_SKIPDEFAULT);
}
}
break;
case OS.TBN_HOTITEMCHANGE:
if (!OS.IsWinCE) {
NMTBHOTITEM lpnmhi = new NMTBHOTITEM ();
OS.MoveMemory (lpnmhi, lParam, NMTBHOTITEM.sizeof);
switch (lpnmhi.dwFlags) {
case OS.HICF_ARROWKEYS:
RECT client = new RECT ();
OS.GetClientRect (handle, client);
int index = (int)/*64*/OS.SendMessage (handle, OS.TB_COMMANDTOINDEX, lpnmhi.idNew, 0);
RECT rect = new RECT ();
OS.SendMessage (handle, OS.TB_GETITEMRECT, index, rect);
if (rect.right > client.right || rect.bottom > client.bottom) {
return LRESULT.ONE;
}
break;
}
}
break;
}
return super.wmNotifyChild (hdr, wParam, lParam);
}
}