The following is intended to try to get the active window's title and stores to title
.
byte[] buffer = new byte[1024];
User32.instance.GetWindowTextA(hWnd, buffer, buffer.length);
String title = Native.toString(buffer);
In title
it is supposed to be stored something similar to "猫の動画 - YouTube - Google Chrome"
; since let's say I was opening a YouTube tab on the Chrome browser, where its title has non-alphabetical characters but UTF-8 compatible.
However, on contrary to my expectation, title
actually has something similar to "??????? - YouTube - Google Chrome"
.
I also tried some variants such as the following; But they didn't solve the garbled character issue.
String title = new String( buffer, java.nio.charset.StandardCharsets.UTF_8 );
How can I solve the issue? Thanks.
additional information
The following is the entire Java script:
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);
}
}
}
the latest (current) version
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);
}
}
}
CodePudding user response:
The "A" in GetWindowTextA
stands for ANSI, no? ANSI doesn't have those characters, hence trivially GetWindowTextA
cannot possibly give you what you want here, and thus no amount of java code is going to fix this.
You want GetWindowTextW
. I think that might return UTF16BE, you may have to play around a bit with trying different encodings, but at least the data you get back from windows still has what you want (vs A
which has already deleted the chinese characters, given that ANSI does not support them).