Java 中使用 UTF-8 的 User32 GetWindowTextA?

User32 GetWindowTextA with UTF-8 in Java?

以下是为了尝试获取活动window的标题并存储到title

byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
String title = Native.toString(buffer);

title中应该存储类似于"猫の動画 - YouTube - Google Chrome"的内容;因为假设我在 Chrome 浏览器上打开了一个 YouTube 标签,它的标题有 non-alphabetical 个字符但兼容 UTF-8。

然而,出乎我意料的是,title居然有类似于"??????? - YouTube - Google Chrome"的东西。

我还尝试了一些变体,例如以下;但是他们并没有解决乱码问题

String title = new String( buffer, java.nio.charset.StandardCharsets.UTF_8 );

我该如何解决这个问题?谢谢。

补充信息

以下是整个Java脚本:


package Main;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.imageio.ImageIO;

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;

public class windowcapture {
    public static void main(String[] args) throws AWTException, IOException {
        int hWnd = User32.instance.GetForegroundWindow();
        WindowInfo window = getWindowInfo(hWnd);
    }

    public static WindowInfo getWindowInfo(int hWnd) {
        RECT r = new RECT();
        User32.instance.GetWindowRect(hWnd, r);
        byte[] buffer = new byte[1024];
        User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
        String title = Native.toString(buffer);
        WindowInfo info = new WindowInfo(hWnd, r, title);
        return info;
    }

    public static interface WndEnumProc extends StdCallLibrary.StdCallCallback {
        boolean callback(int hWnd, int lParam);
    }

    public static interface User32 extends StdCallLibrary {
        public static final String SHELL_TRAY_WND = "Shell_TrayWnd";
        public static final int WM_COMMAND = 0x111;
        public static final int MIN_ALL = 0x1a3;
        public static final int MIN_ALL_UNDO = 0x1a0;

        final User32 instance = (User32) Native.loadLibrary("user32", User32.class);

        boolean EnumWindows(WndEnumProc wndenumproc, int lParam);

        boolean IsWindowVisible(int hWnd);

        int GetWindowRect(int hWnd, RECT r);

        void GetWindowTextA(int hWnd, byte[] buffer, int buflen);

        int GetTopWindow(int hWnd);

        int GetWindow(int hWnd, int flag);

        boolean ShowWindow(int hWnd);

        boolean BringWindowToTop(int hWnd);

        int GetActiveWindow();

        boolean SetForegroundWindow(int hWnd);
        
        // HWND GetForegroundWindow();
        int GetForegroundWindow();

        int FindWindowA(String winClass, String title);

        long SendMessageA(int hWnd, int msg, int num1, int num2);

        final int GW_HWNDNEXT = 2;
    }

    public static class RECT extends Structure {
        public int left, top, right, bottom;

        @Override
        protected List<String> getFieldOrder() {
            List<String> order = new ArrayList<>();
            order.add("left");
            order.add("top");
            order.add("right");
            order.add("bottom");
            return order;
        }
    }

    public static class WindowInfo {
        int hwnd;
        RECT rect;
        String title;

        public WindowInfo(int hwnd, RECT rect, String title) {
            this.hwnd = hwnd;
            this.rect = rect;
            this.title = title;
        }

        public String toString() {
            return String.format("(%d,%d)-(%d,%d) : \"%s\"", rect.left, rect.top, rect.right, rect.bottom, title);
        }
    }
}

最新(当前)版本


package Main;

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.imageio.ImageIO;

import com.sun.jna.Native;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary;

public class windowcapture {
    public static void main(String[] args) throws AWTException, IOException {
        int hWnd = User32.instance.GetForegroundWindow();
        WindowInfo window = getWindowInfo(hWnd);
    }

    public static WindowInfo getWindowInfo(int hWnd) {
        RECT r = new RECT();
        User32.instance.GetWindowRect(hWnd, r);
        byte[] buffer = new byte[1024];
        // User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
        User32.instance.GetWindowTextW(hWnd, buffer, buffer.length);

        // FileOutputStream fos = null;
        // try {
        //     fos = new FileOutputStream(new File("./out/hoge.txt"), true);
        //     fos.write(buffer);
        //     fos.flush();
        //     System.out.println("File Written Successfully");
        // } catch (IOException ioe) {
        //     ioe.printStackTrace();
        // } finally {
        //     try {
        //         if (fos != null) {
        //             fos.close();
        //         }
        //     } catch (IOException ioe) {
        //         System.out.println("Error in closing the Stream");
        //     }
        // }

        String title = Native.toString(buffer);
        // String title = new String( buffer, Charset.forName("x-MS950-HKSCS") );
        // String title = new String( buffer, Charset.forName("UTF_16BE") );
        // String title = new String( buffer, Charset.forName("UTF-8") );
        // String title = Native.toString(buffer, StandardCharsets.UTF_16BE);
        WindowInfo info = new WindowInfo(hWnd, r, title);
        return info;
    }

    public static interface WndEnumProc extends StdCallLibrary.StdCallCallback {
        boolean callback(int hWnd, int lParam);
    }

    public static interface User32 extends StdCallLibrary {
        public static final String SHELL_TRAY_WND = "Shell_TrayWnd";
        public static final int WM_COMMAND = 0x111;
        public static final int MIN_ALL = 0x1a3;
        public static final int MIN_ALL_UNDO = 0x1a0;

        final User32 instance = (User32) Native.loadLibrary("user32", User32.class);

        boolean EnumWindows(WndEnumProc wndenumproc, int lParam);

        boolean IsWindowVisible(int hWnd);

        int GetWindowRect(int hWnd, RECT r);

        void GetWindowTextA(int hWnd, byte[] buffer, int buflen);
        void GetWindowTextW(int hWnd, byte[] buffer, int buflen);

        int GetTopWindow(int hWnd);

        int GetWindow(int hWnd, int flag);

        boolean ShowWindow(int hWnd);

        boolean BringWindowToTop(int hWnd);

        int GetActiveWindow();

        boolean SetForegroundWindow(int hWnd);
        
        // HWND GetForegroundWindow();
        int GetForegroundWindow();

        int FindWindowA(String winClass, String title);

        long SendMessageA(int hWnd, int msg, int num1, int num2);

        final int GW_HWNDNEXT = 2;
    }

    public static class RECT extends Structure {
        public int left, top, right, bottom;

        @Override
        protected List<String> getFieldOrder() {
            List<String> order = new ArrayList<>();
            order.add("left");
            order.add("top");
            order.add("right");
            order.add("bottom");
            return order;
        }
    }

    public static class WindowInfo {
        int hwnd;
        RECT rect;
        String title;

        public WindowInfo(int hwnd, RECT rect, String title) {
            this.hwnd = hwnd;
            this.rect = rect;
            this.title = title;
        }

        public String toString() {
            return String.format("(%d,%d)-(%d,%d) : \"%s\"", rect.left, rect.top, rect.right, rect.bottom, title);
        }
    }
}

GetWindowTextA 中的“A”代表 ANSI,对吗? ANSI 没有这些字符,因此 GetWindowTextA 不可能在这里给你你想要的东西,因此再多的 java 代码也无法解决这个问题。

你想要GetWindowTextW。我认为可能 return UTF16LE,你可能需要尝试不同的编码,但至少你从 windows 得到的数据仍然有你想要的(与 A它已经删除了汉字,因为 ANSI 不支持它们。