public void setImage(Image image) {
   checkWidget();
   if ((style & SWT.SEPARATOR) != 0) return;
   if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
   super.setImage(image);
   updateImages(getEnabled() && parent.getEnabled());
 }
 void releaseWidget() {
   super.releaseWidget();
   releaseImages();
   control = null;
   toolTipText = null;
   disabledImage = hotImage = null;
   if (disabledImage2 != null) disabledImage2.dispose();
   disabledImage2 = null;
 }
 LRESULT wmDrawChild(long /*int*/ wParam, long /*int*/ lParam) {
   DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT();
   OS.MoveMemory(struct, lParam, DRAWITEMSTRUCT.sizeof);
   if (image != null) {
     GCData data = new GCData();
     data.device = display;
     GC gc = GC.win32_new(struct.hDC, data);
     /*
      * Bug in Windows.  When a bitmap is included in the
      * menu bar, the HDC seems to already include the left
      * coordinate.  The fix is to ignore this value when
      * the item is in a menu bar.
      */
     int x = (parent.style & SWT.BAR) != 0 ? MARGIN_WIDTH * 2 : struct.left;
     Image image = getEnabled() ? this.image : new Image(display, this.image, SWT.IMAGE_DISABLE);
     gc.drawImage(image, x, struct.top + MARGIN_HEIGHT);
     if (this.image != image) image.dispose();
     gc.dispose();
   }
   if (parent.foreground != -1) OS.SetTextColor(struct.hDC, parent.foreground);
   return null;
 }
  void updateImages(boolean enabled) {
    if ((style & SWT.SEPARATOR) != 0) return;
    long /*int*/ hwnd = parent.handle;
    TBBUTTONINFO info = new TBBUTTONINFO();
    info.cbSize = TBBUTTONINFO.sizeof;
    info.dwMask = OS.TBIF_IMAGE;
    OS.SendMessage(hwnd, OS.TB_GETBUTTONINFO, id, info);
    if (info.iImage == OS.I_IMAGENONE && image == null) return;
    ImageList imageList = parent.getImageList();
    ImageList hotImageList = parent.getHotImageList();
    ImageList disabledImageList = parent.getDisabledImageList();
    if (info.iImage == OS.I_IMAGENONE) {
      Rectangle bounds = image.getBounds();
      int listStyle = parent.style & SWT.RIGHT_TO_LEFT;
      if (imageList == null) {
        imageList = display.getImageListToolBar(listStyle, bounds.width, bounds.height);
      }
      if (disabledImageList == null) {
        disabledImageList =
            display.getImageListToolBarDisabled(listStyle, bounds.width, bounds.height);
      }
      if (hotImageList == null) {
        hotImageList = display.getImageListToolBarHot(listStyle, bounds.width, bounds.height);
      }
      Image disabled = disabledImage;
      if (disabledImage == null) {
        if (disabledImage2 != null) disabledImage2.dispose();
        disabledImage2 = null;
        disabled = image;
        if (!enabled) {
          disabled = disabledImage2 = new Image(display, image, SWT.IMAGE_DISABLE);
        }
      }
      /*
       * 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 assign the disabled image in
       * all image lists.
       */
      Image image2 = image, hot = hotImage;
      if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
        if (!enabled) image2 = hot = disabled;
      }
      info.iImage = imageList.add(image2);
      disabledImageList.add(disabled);
      hotImageList.add(hot != null ? hot : image2);
      parent.setImageList(imageList);
      parent.setDisabledImageList(disabledImageList);
      parent.setHotImageList(hotImageList);
    } else {
      Image disabled = null;
      if (disabledImageList != null) {
        if (image != null) {
          if (disabledImage2 != null) disabledImage2.dispose();
          disabledImage2 = null;
          disabled = disabledImage;
          if (disabledImage == null) {
            disabled = image;
            if (!enabled) {
              disabled = disabledImage2 = new Image(display, image, SWT.IMAGE_DISABLE);
            }
          }
        }
        disabledImageList.put(info.iImage, disabled);
      }
      /*
       * 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.
       */
      Image image2 = image, hot = hotImage;
      if ((style & (SWT.CHECK | SWT.RADIO)) != 0) {
        if (!enabled) image2 = hot = disabled;
      }
      if (imageList != null) imageList.put(info.iImage, image2);
      if (hotImageList != null) {
        hotImageList.put(info.iImage, hot != null ? hot : image2);
      }
      if (image == null) info.iImage = OS.I_IMAGENONE;
    }

    /*
     * Bug in Windows.  If the width of an item has already been
     * calculated, the tool bar control will not recalculate it to
     * include the space for the image.  The fix is to set the width
     * to zero, forcing the control recalculate the width for the item.
     */
    info.dwMask |= OS.TBIF_SIZE;
    info.cx = 0;
    OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info);
    long /*int*/ hFont = OS.SendMessage(hwnd, OS.WM_GETFONT, 0, 0);
    OS.SendMessage(hwnd, OS.WM_SETFONT, hFont, 0);
    parent.layoutItems();
  }
  private void drag(Event dragEvent) {
    DNDEvent event = new DNDEvent();
    event.widget = this;
    event.x = dragEvent.x;
    event.y = dragEvent.y;
    event.time = OS.GetMessageTime();
    event.doit = true;
    notifyListeners(DND.DragStart, event);
    if (!event.doit || transferAgents == null || transferAgents.length == 0) return;

    int[] pdwEffect = new int[1];
    int operations = opToOs(getStyle());
    Display display = control.getDisplay();
    String key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; // $NON-NLS-1$
    Object oldValue = display.getData(key);
    display.setData(key, Boolean.TRUE);
    ImageList imagelist = null;
    Image image = event.image;
    hwndDrag = 0;
    topControl = null;
    if (image != null) {
      imagelist = new ImageList(SWT.NONE);
      imagelist.add(image);
      topControl = control.getShell();
      /*
       * Bug in Windows. The image is inverted if the shell is RIGHT_TO_LEFT.
       * The fix is to create a transparent window that covers the shell client
       * area and use it during the drag to prevent the image from being inverted.
       * On XP if the shell is RTL, the image is not displayed.
       */
      int offsetX = event.offsetX;
      hwndDrag = topControl.handle;
      if ((topControl.getStyle() & SWT.RIGHT_TO_LEFT) != 0) {
        offsetX = image.getBounds().width - offsetX;
        RECT rect = new RECT();
        OS.GetClientRect(topControl.handle, rect);
        hwndDrag =
            OS.CreateWindowEx(
                OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT,
                WindowClass,
                null,
                OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
                0,
                0,
                rect.right - rect.left,
                rect.bottom - rect.top,
                topControl.handle,
                0,
                OS.GetModuleHandle(null),
                null);
        OS.ShowWindow(hwndDrag, OS.SW_SHOW);
      }
      OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offsetX, event.offsetY);
      /*
       * Feature in Windows. When ImageList_DragEnter() is called,
       * it takes a snapshot of the screen  If a drag is started
       * when another window is in front, then the snapshot will
       * contain part of the other window, causing pixel corruption.
       * The fix is to force all paints to be delivered before
       * calling ImageList_DragEnter().
       */
      if (OS.IsWinCE) {
        OS.UpdateWindow(topControl.handle);
      } else {
        int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
        OS.RedrawWindow(topControl.handle, null, 0, flags);
      }
      POINT pt = new POINT();
      pt.x = dragEvent.x;
      pt.y = dragEvent.y;
      OS.MapWindowPoints(control.handle, 0, pt, 1);
      RECT rect = new RECT();
      OS.GetWindowRect(hwndDrag, rect);
      OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top);
    }
    int result = COM.DRAGDROP_S_CANCEL;
    try {
      result =
          COM.DoDragDrop(iDataObject.getAddress(), iDropSource.getAddress(), operations, pdwEffect);
    } finally {
      // ensure that we don't leave transparent window around
      if (hwndDrag != 0) {
        OS.ImageList_DragLeave(hwndDrag);
        OS.ImageList_EndDrag();
        imagelist.dispose();
        if (hwndDrag != topControl.handle) OS.DestroyWindow(hwndDrag);
        hwndDrag = 0;
        topControl = null;
      }
      display.setData(key, oldValue);
    }
    int operation = osToOp(pdwEffect[0]);
    if (dataEffect == DND.DROP_MOVE) {
      operation =
          (operation == DND.DROP_NONE || operation == DND.DROP_COPY)
              ? DND.DROP_TARGET_MOVE
              : DND.DROP_MOVE;
    } else {
      if (dataEffect != DND.DROP_NONE) {
        operation = dataEffect;
      }
    }
    event = new DNDEvent();
    event.widget = this;
    event.time = OS.GetMessageTime();
    event.doit = (result == COM.DRAGDROP_S_DROP);
    event.detail = operation;
    notifyListeners(DND.DragEnd, event);
    dataEffect = DND.DROP_NONE;
  }