package net.cakenet.jsaton.nativedef;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinGDI;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.W32APIOptions;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class WindowsWindowManager extends WindowManager {
private static final GDI32 GDI = GDI32.INSTANCE;
private static final User32 USER = User32.INSTANCE;
private static final Win32WindowReference DESKTOP = new Win32WindowReference(USER.GetDesktopWindow());
public WindowReference findWindowByPointImpl(Point loc) {
return new Win32WindowReference(USER.WindowFromPoint(loc.x, loc.y));
}
public WindowReference getDesktopImpl() {
return DESKTOP;
}
protected List<WindowReference> getTopLevelWindowsImpl() {
final List<WindowReference> refs = new ArrayList<>();
USER.EnumWindows(new WinUser.WNDENUMPROC() {
public boolean callback(WinDef.HWND hwnd, Pointer pointer) {
refs.add(new Win32WindowReference(hwnd));
return true;
}
}, null);
return refs;
}
static class Win32WindowReference extends WindowReference {
private WinDef.HWND hwnd;
public Win32WindowReference(WinDef.HWND hwnd) {
this.hwnd = hwnd;
}
public int[] capture(int x, int y, int width, int height) {
WinDef.HDC hdcWindow = USER.GetDC(hwnd);
WinDef.HDC hdcMemDC = GDI.CreateCompatibleDC(hdcWindow);
WinDef.HBITMAP hBitmap = GDI.CreateCompatibleBitmap(hdcWindow, width, height);
WinNT.HANDLE hOld = GDI.SelectObject(hdcMemDC, hBitmap);
GDI.BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, x, y, GDI32.SRCCOPY);
WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO();
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
Memory buffer = new Memory(width * height * 4);
GDI.GetDIBits(hdcMemDC, hBitmap, 0, height, buffer, bmi, WinGDI.DIB_RGB_COLORS);
int[] pixels = buffer.getIntArray(0, width * height);
GDI.SelectObject(hdcMemDC, hOld);
GDI.DeleteDC(hdcMemDC);
GDI.DeleteObject(hBitmap);
USER.ReleaseDC(hwnd, hdcWindow);
return pixels;
}
public String getTitle() {
int len = USER.GetWindowTextLength(hwnd);
if (len == 0)
return null;
char[] chars = new char[len+1];
USER.GetWindowText(hwnd, chars, len+1);
return new String(chars, 0, len);
}
public Rectangle getBounds() {
WinDef.RECT bounds = new WinDef.RECT();
USER.GetClientRect(hwnd, bounds);
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
WinUser.POINT p = new WinUser.POINT(bounds.left, bounds.top);
USER.ClientToScreen(hwnd, p);
return new Rectangle(p.x, p.y, width, height);
}
public List<WindowReference> children() {
final List<WindowReference> children = new LinkedList<>();
USER.EnumChildWindows(hwnd, new WinUser.WNDENUMPROC() {
public boolean callback(WinDef.HWND child, Pointer pointer) {
WinDef.HWND parent = USER.GetParent(child);
if (parent == hwnd || (parent != null && parent.equals(hwnd)))
children.add(new Win32WindowReference(child));
return true;
}
}, null);
return children;
}
public WindowReference parent() {
WinDef.HWND par = USER.GetParent(hwnd);
return par == null ? null : new Win32WindowReference(par);
}
public boolean equals(Object o) {
return o instanceof Win32WindowReference && equals((Win32WindowReference) o);
}
public boolean equals(Win32WindowReference o) {
return o == this || o.hwnd.equals(hwnd);
}
public String toString() {
String title = getTitle();
return Pointer.nativeValue(hwnd.getPointer()) + (title != null? String.format(" (%s)", title): "");
}
}
}
interface GDI32 extends com.sun.jna.platform.win32.GDI32,
com.sun.jna.platform.win32.WinGDI,
com.sun.jna.platform.win32.WinDef {
int SRCCOPY = 0xCC0020;
GDI32 INSTANCE =
(GDI32) Native.loadLibrary(GDI32.class);
boolean BitBlt(HDC hdcMemDC, int i, int i1, int width, int height, HDC hdcWindow, int i2, int i3, int srccopy);
}
interface User32 extends com.sun.jna.platform.win32.User32 {
User32 INSTANCE = (User32) Native.loadLibrary(User32.class, W32APIOptions.UNICODE_OPTIONS);
WinDef.HWND GetDesktopWindow();
HWND WindowFromPoint(int x, int y);
boolean GetClientRect(HWND hWnd, RECT bounds);
boolean ClientToScreen(HWND hwnd, POINT point);
HWND GetParent(HWND hwnd);
}