From ec7cc40d0254b31ace511f11d7313f6a34f9c7ad Mon Sep 17 00:00:00 2001 From: DaniTheSkunk Date: Tue, 27 Sep 2022 14:42:14 +0200 Subject: [PATCH] added debug printing of window styles, implemented Window.setBorderRounded, and fixed move resizing --- Test.java | 5 + com/danitheskunk/skunkworks/windows/Dwm.java | 9 + .../skunkworks/windows/MARGINS.java | 19 ++ .../skunkworks/windows/Window.java | 164 ++++++++++++++++-- 4 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 com/danitheskunk/skunkworks/windows/MARGINS.java diff --git a/Test.java b/Test.java index e695f0f..55b1e52 100644 --- a/Test.java +++ b/Test.java @@ -15,6 +15,11 @@ public class Test { for(var window: windows) { System.out.printf("%s -- %s -- %s\n", window.getTitle(), window.getClassName(), window.getExecutableName()); } + windows.get(0).setBorder(true); + windows.get(0).setBorderRounded(false); + windows.get(0).move(new Vec2i(1280, 720), new Vec2i(2560, 1440)); + windows.get(0).debugPrintStyles(); + windows.get(0).debugPrintStylesEx(); /* var engine = new Engine(); var window = engine.openWindow(new Vec2i(1280, 720), "Skunkworks"); diff --git a/com/danitheskunk/skunkworks/windows/Dwm.java b/com/danitheskunk/skunkworks/windows/Dwm.java index 6614d90..fbf5c3b 100644 --- a/com/danitheskunk/skunkworks/windows/Dwm.java +++ b/com/danitheskunk/skunkworks/windows/Dwm.java @@ -27,6 +27,15 @@ public interface Dwm extends Library { WinDef.DWORD DWMWA_CLOAKED = new WinDef.DWORD(14); WinDef.DWORD DWMWA_FREEZE_REPRESENTATION = new WinDef.DWORD(15); WinDef.DWORD DWMWA_LAST = new WinDef.DWORD(16); + WinDef.DWORD DWMWA_WINDOW_CORNER_PREFERENCE = new WinDef.DWORD(33); + //todo: fix/complete DWMWA list + WinDef.DWORD DWMWCP_DEFAULT = new WinDef.DWORD(0); + WinDef.DWORD DWMWCP_DONOTROUND = new WinDef.DWORD(1); + WinDef.DWORD DWMWCP_ROUND = new WinDef.DWORD(2); + WinDef.DWORD DWMWCP_ROUNDSMALL = new WinDef.DWORD(3); + + WinNT.HRESULT DwmExtendFrameIntoClientArea(WinDef.HWND hwnd, MARGINS pMarInset); WinNT.HRESULT DwmGetWindowAttribute(WinDef.HWND hwnd, WinDef.DWORD dwAttribute, Pointer pvAttribute, WinDef.DWORD cbAttribute); + WinNT.HRESULT DwmSetWindowAttribute(WinDef.HWND hwnd, WinDef.DWORD dwAttribute, Pointer pvAttribute, WinDef.DWORD cbAttribute); } diff --git a/com/danitheskunk/skunkworks/windows/MARGINS.java b/com/danitheskunk/skunkworks/windows/MARGINS.java new file mode 100644 index 0000000..0fadca3 --- /dev/null +++ b/com/danitheskunk/skunkworks/windows/MARGINS.java @@ -0,0 +1,19 @@ +package com.danitheskunk.skunkworks.windows; + +import com.sun.jna.Structure; + +import java.util.Arrays; +import java.util.List; + +public class MARGINS extends Structure implements Structure.ByReference { + + public int cxLeftWidth; + public int cxRightWidth; + public int cyTopHeight; + public int cyBottomHeight; + + @Override + protected List getFieldOrder() { + return Arrays.asList("cxLeftWidth", "cxRightWidth", "cyTopHeight", "cyBottomHeight"); + } +} diff --git a/com/danitheskunk/skunkworks/windows/Window.java b/com/danitheskunk/skunkworks/windows/Window.java index af00a7c..c6f9712 100644 --- a/com/danitheskunk/skunkworks/windows/Window.java +++ b/com/danitheskunk/skunkworks/windows/Window.java @@ -2,6 +2,7 @@ package com.danitheskunk.skunkworks.windows; import com.danitheskunk.skunkworks.Util; +import com.danitheskunk.skunkworks.Vec2i; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.IntByReference; @@ -17,6 +18,105 @@ public class Window { this.hwnd = hwnd; } + + public void debugPrintStyles() { + var str = new StringBuilder(); + var style = getStyle(); + str.append("Window Styles: "); + if((style & User32.WS_BORDER) != 0) str.append("ws_border, "); + if((style & User32.WS_CAPTION) != 0) str.append("ws_caption, "); + if((style & User32.WS_CHILD) != 0) str.append("ws_child, "); + if((style & User32.WS_CHILDWINDOW) != 0) str.append("ws_childwindow, "); + if((style & User32.WS_CLIPCHILDREN) != 0) str.append("ws_clipchildren, "); + if((style & User32.WS_CLIPSIBLINGS) != 0) str.append("ws_clipsiblings, "); + if((style & User32.WS_DISABLED) != 0) str.append("ws_disabled, "); + if((style & User32.WS_DLGFRAME) != 0) str.append("ws_dlgframe, "); + if((style & User32.WS_GROUP) != 0) str.append("ws_group, "); + if((style & User32.WS_HSCROLL) != 0) str.append("ws_hscroll, "); + if((style & User32.WS_ICONIC) != 0) str.append("ws_iconic, "); + if((style & User32.WS_MAXIMIZE) != 0) str.append("ws_maximize, "); + if((style & User32.WS_MAXIMIZEBOX) != 0) str.append("ws_maximizebox, "); + if((style & User32.WS_MINIMIZE) != 0) str.append("ws_minimize, "); + if((style & User32.WS_MINIMIZEBOX) != 0) str.append("ws_minimizebox, "); + if((style & User32.WS_OVERLAPPED) != 0) str.append("ws_overlapped, "); + if((style & User32.WS_POPUP) != 0) str.append("ws_popup, "); + if((style & User32.WS_SIZEBOX) != 0) str.append("ws_sizebox, "); + if((style & User32.WS_SYSMENU) != 0) str.append("ws_sysmenu, "); + if((style & User32.WS_TABSTOP) != 0) str.append("ws_tabstop, "); + if((style & User32.WS_THICKFRAME) != 0) str.append("ws_thickframe, "); + if((style & User32.WS_TILED) != 0) str.append("ws_tiled, "); + if((style & User32.WS_VISIBLE) != 0) str.append("ws_visible, "); + if((style & User32.WS_VSCROLL) != 0) str.append("ws_vscroll, "); + System.out.println(str.toString()); + } + + public void debugPrintStylesEx() { + var str = new StringBuilder(); + var style = getStyleEx(); + str.append("Window Styles EX: "); + if((style & User32Extra.WS_EX_ACCEPTFILES) != 0) str.append("ws_ex_acceptfiles, "); + if((style & User32Extra.WS_EX_APPWINDOW) != 0) str.append("ws_ex_appwindow, "); + if((style & User32Extra.WS_EX_CLIENTEDGE) != 0) str.append("ws_ex_clientedge, "); + if((style & User32Extra.WS_EX_COMPOSITED) != 0) str.append("ws_ex_composited, "); + if((style & User32Extra.WS_EX_CONTEXTHELP) != 0) str.append("ws_ex_contexthelp, "); + if((style & User32Extra.WS_EX_CONTROLPARENT) != 0) str.append("ws_ex_controlparent, "); + if((style & User32Extra.WS_EX_DLGMODALFRAME) != 0) str.append("ws_ex_dlgmodalframe, "); + if((style & User32Extra.WS_EX_LAYERED) != 0) str.append("ws_ex_layered, "); + if((style & User32Extra.WS_EX_LAYOUTRTL) != 0) str.append("ws_ex_layoutrtl, "); + if((style & User32Extra.WS_EX_LEFT) != 0) str.append("ws_ex_left, "); + if((style & User32Extra.WS_EX_LEFTSCROLLBAR) != 0) str.append("ws_ex_leftscrollbar, "); + if((style & User32Extra.WS_EX_LTRREADING) != 0) str.append("ws_ex_ltrreading, "); + if((style & User32Extra.WS_EX_MDICHILD) != 0) str.append("ws_ex_mdichild, "); + if((style & User32Extra.WS_EX_NOACTIVATE) != 0) str.append("ws_ex_noactivate, "); + if((style & User32Extra.WS_EX_NOINHERITLAYOUT) != 0) str.append("ws_ex_noinheritedlayout, "); + if((style & User32Extra.WS_EX_NOPARENTNOTIFY) != 0) str.append("ws_ex_noparentnotify, "); + if((style & User32Extra.WS_EX_NOREDIRECTIONBITMAP) != 0) str.append("ws_ex_noredirectionbitmap, "); + if((style & User32Extra.WS_EX_RIGHT) != 0) str.append("ws_ex_right, "); + if((style & User32Extra.WS_EX_RIGHTSCROLLBAR) != 0) str.append("ws_ex_rightscrollbar, "); + if((style & User32Extra.WS_EX_RTLREADING) != 0) str.append("ws_ex_rtlreading, "); + if((style & User32Extra.WS_EX_STATICEDGE) != 0) str.append("ws_ex_staticedge, "); + if((style & User32Extra.WS_EX_TOOLWINDOW) != 0) str.append("ws_ex_toolwindow, "); + if((style & User32Extra.WS_EX_TOPMOST) != 0) str.append("ws_ex_topmost, "); + if((style & User32Extra.WS_EX_TRANSPARENT) != 0) str.append("ws_ex_transparent, "); + if((style & User32Extra.WS_EX_WINDOWEDGE) != 0) str.append("ws_ex_windowedge, "); + System.out.println(str.toString()); + } + + public void setBorder(boolean border) { + + var STYLES = User32Extra.WS_CAPTION | User32Extra.WS_THICKFRAME | User32Extra.WS_MINIMIZEBOX | User32Extra.WS_SYSMENU; + //var STYLES = User32Extra.WS_THICKFRAME | User32Extra.WS_MINIMIZEBOX | User32Extra.WS_SYSMENU; + var STYLESEX = User32Extra.WS_EX_DLGMODALFRAME | User32Extra.WS_EX_CLIENTEDGE | User32Extra.WS_EX_STATICEDGE; + //var STYLES = User32Extra.WS_POPUP; + + var style = getStyle(); + var styleex = getStyleEx(); + if(border) { + style |= STYLES; + styleex |= STYLESEX; + } else { + style &= ~STYLES; + styleex &= ~STYLESEX; + } + setStyle(style); + setStyleEx(styleex); + + + var dwm = Dwm.INSTANCE; + var margins = new MARGINS(); + margins.cxLeftWidth = 0; + margins.cxRightWidth = 0; + margins.cyTopHeight = 0; + margins.cyBottomHeight = 0; + dwm.DwmExtendFrameIntoClientArea(hwnd, margins); + } + + public void setBorderRounded(boolean rounded) { + var round = rounded ? Dwm.DWMWCP_ROUND : Dwm.DWMWCP_DONOTROUND; + var roundref = new WinDef.DWORDByReference(round); + Dwm.INSTANCE.DwmSetWindowAttribute(hwnd, Dwm.DWMWA_WINDOW_CORNER_PREFERENCE, roundref.getPointer(), new WinDef.DWORD(WinDef.DWORD.SIZE)); + } + public String getClassName() { var user32 = User32Extra.INSTANCE; char[] chars = new char[1024]; @@ -42,6 +142,21 @@ public class Window { return user32.GetWindowLong(hwnd, WinUser.GWL_STYLE); } + private void setStyle(int style) { + var user32 = User32Extra.INSTANCE; + user32.SetWindowLong(hwnd, WinUser.GWL_STYLE, style); + } + + private int getStyleEx() { + var user32 = User32Extra.INSTANCE; + return user32.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE); + } + + private void setStyleEx(int style) { + var user32 = User32Extra.INSTANCE; + user32.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, style); + } + private boolean isTitleBarVisible() { var tb = getTitleBarInfo(); return (tb.rgstate[0] & User32Extra.STATE_SYSTEM_INVISIBLE) == 0; @@ -73,18 +188,18 @@ public class Window { var user32 = User32Extra.INSTANCE; var dwm = Dwm.INSTANCE; var out = new IntByReference(); - dwm.DwmGetWindowAttribute(hwnd, Dwm.DWMWA_CLOAKED, out.getPointer(), new WinDef.DWORD(WinDef.DWORD.SIZE)); + //dwm.DwmGetWindowAttribute(hwnd, Dwm.DWMWA_CLOAKED, out.getPointer(), new WinDef.DWORD(WinDef.DWORD.SIZE)); var val = out.getValue(); return val != 0; } + public boolean isInAltTabList() { var user32 = User32Extra.INSTANCE; var walk = user32.GetAncestor(hwnd, WinUser.GA_ROOTOWNER); WinDef.HWND test; while(!(test = user32.GetLastActivePopup(walk)).equals(test)) { - if(user32.IsWindowVisible(test)) - break; + if(user32.IsWindowVisible(test)) break; walk = test; } var window = new Window(hwnd); @@ -95,6 +210,41 @@ public class Window { return (getStyle() & User32Extra.WS_EX_TOOLWINDOW) != 0; } + public void move(Vec2i pos, Vec2i size) { + var user32 = User32Extra.INSTANCE; + var dwm = Dwm.INSTANCE; + + var rect_with_shadow = new WinDef.RECT(); + var rect_without_shadow = new WinDef.RECT(); + var rect = new WinDef.RECT(); + + user32.GetWindowRect(hwnd, rect_with_shadow); + dwm.DwmGetWindowAttribute(hwnd, Dwm.DWMWA_EXTENDED_FRAME_BOUNDS, rect_without_shadow.getPointer(), new WinDef.DWORD(rect_without_shadow.size())); + rect_without_shadow.read(); + var left_shadow = rect_without_shadow.left - rect_with_shadow.left; + var right_shadow = rect_with_shadow.right - rect_without_shadow.right; + var top_shadow = rect_without_shadow.top - rect_with_shadow.top; + var bottom_shaddow = rect_with_shadow.bottom - rect_without_shadow.bottom; + + + + rect.left = pos.getX() - left_shadow; + rect.top = pos.getY() - top_shadow; + rect.right = pos.getX() + size.getX() + right_shadow; + rect.bottom = pos.getY() + size.getY() + bottom_shaddow; + //user32.AdjustWindowRect(rect, new WinDef.DWORD(WinUser.WS_OVERLAPPEDWINDOW), new WinDef.BOOL(false)); + //var style = getStyle(); + //var styleex = getStyleEx(); + //style &= ~(User32Extra.WS_CAPTION | User32Extra.WS_MINIMIZEBOX | User32Extra.WS_SYSMENU); + //styleex &= ~(User32Extra.WS_EX_DLGMODALFRAME | User32Extra.WS_EX_CLIENTEDGE | User32Extra.WS_EX_STATICEDGE); + //style |= User32Extra.WS_POPUP; + //user32.AdjustWindowRectEx(rect, new WinDef.DWORD(style), new WinDef.BOOL(false), new WinDef.DWORD(styleex)); + user32.MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, true); + //user32.MoveWindow(hwnd, pos.getX(), pos.getY(), size.getX(), size.getY(), true); + + user32.SetWindowPos(hwnd, null, 0, 0, 0, 0, WinUser.SWP_FRAMECHANGED | WinUser.SWP_NOZORDER | WinUser.SWP_NOOWNERZORDER | WinUser.SWP_NOMOVE | WinUser.SWP_NOSIZE | WinUser.SWP_NOACTIVATE); + } + //static functions public static List getAllVisible() { var user32 = User32Extra.INSTANCE; @@ -104,13 +254,7 @@ public class Window { @Override public boolean callback(WinDef.HWND hwnd, Pointer pointer) { var window = new Window(hwnd); - //if(user32.IsWindowVisible(hwnd) && user32.GetWindow(hwnd, new WinDef.DWORD(User32.GW_OWNER)) == null) { - if(window.isInAltTabList()) { - //if(title.length() > 0) { - //windows.add(window.getTitle() + " -- " + window.getClassName()); - windows.add(window); - //} - } + if(window.isInAltTabList()) windows.add(window); return true; } }, null);