簡體   English   中英

在 Java 中提取光標圖像

[英]Extract cursor image in Java

我想知道是否有辦法從 Java 中的 Cursor 對象中提取 Image 對象。

例如:

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

然后您可以在工具欄按鈕上繪制它(這就是我想要它的目的)。

Cursor類非常抽象——所有重要的東西都委托給本機代碼,所以你不能只在 圖形上下文中繪制一個。 沒有一種立即明顯的方法可以繞過預定義圖標或在本機代碼中執行的需要。


你能幫我使用你提到的那個功能嗎?

下面是一些使用JNA庫繪制內置 Windows 光標的代碼。 如果可以使用 JNA,則可以避免使用 C++ 編譯器。

我可能進行了太多的本地調用,但是一次性圖標生成的成本並不高。

用 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);

}

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);
}

或許可以從 JRE 中找到系統光標圖像。 查看源代碼也可能很有趣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM