用Java提取光标图像

时间:2009-04-11 11:01:55

标签: java c++ winapi

我想知道是否有办法从Java中的Cursor对象中提取Image对象。

用于此目的的是:

Image img = extractCursorImage(Cursor.getDefaultCursor());

然后你可以在工具栏上绘制按钮(这就是我想要的目的)。

3 个答案:

答案 0 :(得分:7)

Cursor类非常抽象 - 所有重要的东西都被委托给本机代码,所以你不能只在graphics上下文中绘制一个。没有一种明显的方法来满足预定义图标或在本机代码中执行此操作的需要。


  你可以帮助我使用你提到的那个功能吗?

下面是一些使用JNA库绘制内置Windows游标的代码。如果可以使用JNA,则可以避免使用C ++编译器。

我可能会拨打过多的原生电话,但一次性图标生成的成本并不高。

hand cursor drawn in Java http://f.imagehost.org/0709/hand.png

将光标显示为Java图像的代码:

public class LoadCursor {

  public static void draw(BufferedImage image, int cursor,
      int diFlags) {
    int width = image.getWidth();
    int height = image.getHeight();

    User32 user32 = User32.INSTANCE;
    Gdi32 gdi32 = Gdi32.INSTANCE;

    Pointer hIcon = user32
        .LoadCursorW(Pointer.NULL, cursor);
    Pointer hdc = gdi32.CreateCompatibleDC(Pointer.NULL);
    Pointer bitmap = gdi32.CreateCompatibleBitmap(hdc,
        width, height);

    gdi32.SelectObject(hdc, bitmap);
    user32.DrawIconEx(hdc, 0, 0, hIcon, width, height, 0,
        Pointer.NULL, diFlags);

    for (int x = 0; x < width; x++) {
      for (int y = 0; y < width; y++) {
        int rgb = gdi32.GetPixel(hdc, x, y);
        image.setRGB(x, y, rgb);
      }
    }

    gdi32.DeleteObject(bitmap);
    gdi32.DeleteDC(hdc);
  }

  public static void main(String[] args) {
    final int width = 128;
    final int height = 128;

    BufferedImage image = new BufferedImage(width, height,
        BufferedImage.TYPE_INT_ARGB);
    draw(image, User32.IDC_HAND, User32.DI_NORMAL);
    BufferedImage mask = new BufferedImage(width, height,
        BufferedImage.TYPE_INT_RGB);
    draw(mask, User32.IDC_HAND, User32.DI_MASK);
    applyMask(image, mask);

    JLabel icon = new JLabel();
    icon.setIcon(new ImageIcon(image));

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(icon);
    frame.pack();
    frame.setVisible(true);
  }

  private static void applyMask(BufferedImage image,
      BufferedImage mask) {
    int width = image.getWidth();
    int height = image.getHeight();
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        int masked = mask.getRGB(x, y);
        if ((masked & 0x00FFFFFF) == 0) {
          int rgb = image.getRGB(x, y);
          rgb = 0xFF000000 | rgb;
          image.setRGB(x, y, rgb);
        }
      }
    }
  }

}

User32.dll接口:

public interface User32 extends Library {

  public static User32 INSTANCE = (User32) Native
      .loadLibrary("User32", User32.class);

  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_ARROW = 32512;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_IBEAM = 32513;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_WAIT = 32514;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_CROSS = 32515;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_UPARROW = 32516;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZENWSE = 32642;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZENESW = 32643;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZEWE = 32644;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZENS = 32645;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZEALL = 32646;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_NO = 32648;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_HAND = 32649;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_APPSTARTING = 32650;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_HELP = 32651;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_ICON = 32641;
  /** @see #LoadCursorW(Pointer, int) */
  public static final int IDC_SIZE = 32640;

  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_COMPAT = 4;
  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_DEFAULTSIZE = 8;
  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_IMAGE = 2;
  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_MASK = 1;
  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_NORMAL = 3;
  /** @see #DrawIconEx(Pointer, int, int, Pointer, int, int, int, Pointer, int) */
  public static final int DI_APPBANDING = 1;

  /** http://msdn.microsoft.com/en-us/library/ms648391(VS.85).aspx */
  public Pointer LoadCursorW(Pointer hInstance,
      int lpCursorName);

  /** http://msdn.microsoft.com/en-us/library/ms648065(VS.85).aspx */
  public boolean DrawIconEx(Pointer hdc, int xLeft,
      int yTop, Pointer hIcon, int cxWidth, int cyWidth,
      int istepIfAniCur, Pointer hbrFlickerFreeDraw,
      int diFlags);

}

Gdi32.dll接口:

public interface Gdi32 extends Library {

  public static Gdi32 INSTANCE = (Gdi32) Native
      .loadLibrary("Gdi32", Gdi32.class);

  /** http://msdn.microsoft.com/en-us/library/dd183489(VS.85).aspx */
  public Pointer CreateCompatibleDC(Pointer hdc);

  /** http://msdn.microsoft.com/en-us/library/dd183488(VS.85).aspx */
  public Pointer CreateCompatibleBitmap(Pointer hdc,
      int nWidth, int nHeight);

  /** http://msdn.microsoft.com/en-us/library/dd162957(VS.85).aspx */
  public Pointer SelectObject(Pointer hdc, Pointer hgdiobj);

  /** http://msdn.microsoft.com/en-us/library/dd145078(VS.85).aspx */
  public int SetPixel(Pointer hdc, int X, int Y, int crColor);

  /** http://msdn.microsoft.com/en-us/library/dd144909(VS.85).aspx */
  public int GetPixel(Pointer hdc, int nXPos, int nYPos);

  /** http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx */
  public boolean DeleteObject(Pointer hObject);

  /** http://msdn.microsoft.com/en-us/library/dd183533(VS.85).aspx */
  public boolean DeleteDC(Pointer hdc);

}

答案 1 :(得分:0)

可以从JRE中找到系统光标图像。查看源代码也可能很有趣。

答案 2 :(得分:0)

Linux解决方案:

private BufferedImage getCursorImage(){
    X11 x11 = X11.INSTANCE;
    Xfixes xfixes = Xfixes.INSTANCE;

    X11.Display display = x11.XOpenDisplay(null);

    Xfixes.XFixesCursorImage cursorImage = xfixes.XFixesGetCursorImage(display);

    ByteBuffer buf = cursorImage.pixels.getPointer().getByteBuffer(0,
            cursorImage.width * cursorImage.height * NativeLong.SIZE);
    buf.order(ByteOrder.LITTLE_ENDIAN);
    BufferedImage bim = new BufferedImage(cursorImage.width, cursorImage.height, BufferedImage.TYPE_INT_ARGB);
    WritableRaster raster = bim.getRaster();
    for (int y = 0; y < cursorImage.height; y++) {
        for (int x = 0; x < cursorImage.width; x++) {
            long z = NativeLong.SIZE == 8 ? buf.getLong() : buf.getInt();
            int b = (int) ((z >> 24) & 0xFF);
            int a = (int) ((z >> 16) & 0xFF);
            int g = (int) ((z >> 8) & 0xFF);
            int r = (int) (z & 0xFF);
            raster.setPixel(x, y, new int[] { a, r, g, b });
        }
    }

    x11.XCloseDisplay(display);
    return bim;
}

JNA接口:

public interface Xfixes extends Library {

    Xfixes INSTANCE = Native.load("Xfixes", Xfixes.class);

    @Structure.FieldOrder({ "x", "y", "width", "height", "xhot", "yhot", "cursor_serial", "pixels", "atom", "name"})
    class XFixesCursorImage extends Structure {
        public short x;
        public short y;
        public short width;
        public short height;
        public short xhot;
        public short yhot;
        public NativeLong cursor_serial;

        public NativeLongByReference pixels;

        public NativeLong atom;
        public Pointer name;

        public XFixesCursorImage() {
            super();
        }
    }

    XFixesCursorImage XFixesGetCursorImage(X11.Display dpy);
}