WildByDesign Posted Sunday at 03:02 PM Posted Sunday at 03:02 PM I'm doing some testing right now with applying WS_EX_LAYERED to a "Scrollbar" window that is being used as a SBS_SIZEBOX / SBS_SIZEGRIP for the GUI. I am using _WinAPI_SetLayeredWindowAttributes() to remove the background color of the "Scrollbar" window, leaving only the dots. That part is working successfully. But the problem is that it seems using WS_EX_LAYERED makes it so that the "Scrollbar" window is no longer clickable to resize the GUI and makes the hover cursor fail to show directly over it. If anybody has any ideas for making a layered window clickable, please let me know. This is mostly just for testing and seeing what other possibilities there are for this type of thing. I appreciate your time. Thank you. expandcollapse popup#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <GuiStatusBar.au3> #include <StaticConstants.au3> #include <WinAPIGdi.au3> #include <WinAPIRes.au3> #include <WinAPISysWin.au3> #include <WinAPITheme.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) Global $g_hGui, $g_hSizebox, $g_hOldProc, $g_hStatus, $g_iHeight, $g_aText, $g_aRatioW, $g_iBkColor, $g_iTextColor, $g_hDots Example() ;============================================== Func Example() _GDIPlus_Startup() Local Const $SBS_SIZEBOX = 0x08, $SBS_SIZEGRIP = 0x10 $g_hGui = GUICreate("SBS_SIZEBOX / SBS_SIZEGRIP Testing", 400, 200, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)) GUISetBkColor(0x202020) $g_hSizebox = _WinAPI_CreateWindowEx(0, "Scrollbar", "", $WS_CHILD + $WS_VISIBLE + $SBS_SIZEBOX, 400 - 15, 200 - 15, 15, 15, $g_hGui) ; $SBS_SIZEBOX or $SBS_SIZEGRIP ;$g_hSizebox = _WinAPI_CreateWindowEx($WS_EX_TOPMOST, "Scrollbar", "", $WS_CHILD + $WS_VISIBLE + $SBS_SIZEBOX, 300 - 15, 200 - 15, 15, 15, $g_hGui) ; $SBS_SIZEBOX or $SBS_SIZEGRIP ; Add WS_EX_LAYERED extended style _WinAPI_SetWindowLong($g_hSizebox, $GWL_EXSTYLE, BitOR(_WinAPI_GetWindowLong($g_hSizebox, $GWL_EXSTYLE), $WS_EX_LAYERED)) _WinAPI_SetWindowPos($g_hSizebox, 0, 0, 0, 0, 0, BitOR($SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER, $SWP_FRAMECHANGED)) ;_WinAPI_SetWindowPos($g_hSizebox, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_NOMOVE, $SWP_NOREDRAW, $SWP_NOSIZE)) ; Subclass the sizebox (by changing the window procedure associated with the Scrollbar class) ;Local $hProc = DllCallbackRegister('ScrollbarProc', 'lresult', 'hwnd;uint;wparam;lparam') ;$g_hOldProc = _WinAPI_SetWindowLong($g_hSizebox, $GWL_WNDPROC, DllCallbackGetPtr($hProc)) _WinAPI_SetWindowTheme($g_hSizebox, "DarkMode_Explorer", "ScrollBar") Local $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZENWSE) _WinAPI_SetClassLongEx($g_hSizebox, -12, $hCursor) ; $GCL_HCURSOR = -12 SizeboxResize() GUISetState() Sleep(2000) ; Make surrounding background color around dots transparent Local $iColor = 0x383838 _WinAPI_SetLayeredWindowAttributes($g_hSizebox, $iColor, 255) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _GDIPlus_BitmapDispose($g_hDots) _GUICtrlStatusBar_Destroy($g_hStatus) _WinAPI_DestroyCursor($hCursor) ; _WinAPI_DeleteObject($g_hBrush) ;_WinAPI_SetWindowLong($g_hSizebox, $GWL_WNDPROC, $g_hOldProc) ;DllCallbackFree($hProc) _GDIPlus_Shutdown() EndFunc ;==>Example Func SizeboxResize() Local $aSize = WinGetClientSize($g_hGui) WinMove($g_hSizebox, "", $aSize[0] - 15, $aSize[1] - 15) EndFunc ;==>SizeboxResize ;============================================== Func ScrollbarProc($hWnd, $iMsg, $wParam, $lParam) ; Andreik If $iMsg = $WM_PAINT Then Local $tPAINTSTRUCT Local $hDC = _WinAPI_BeginPaint($hWnd, $tPAINTSTRUCT) Local $iWidth = DllStructGetData($tPAINTSTRUCT, 'rPaint', 3) - DllStructGetData($tPAINTSTRUCT, 'rPaint', 1) Local $iHeight = DllStructGetData($tPAINTSTRUCT, 'rPaint', 4) - DllStructGetData($tPAINTSTRUCT, 'rPaint', 2) Local $hGraphics = _GDIPlus_GraphicsCreateFromHDC($hDC) _GDIPlus_GraphicsDrawImageRect($hGraphics, $g_hDots, 0, 0, $iWidth, $iHeight) _GDIPlus_GraphicsDispose($hGraphics) _WinAPI_EndPaint($hWnd, $tPAINTSTRUCT) Return 0 EndIf Return _WinAPI_CallWindowProc($g_hOldProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>ScrollbarProc
genius257 Posted Sunday at 07:46 PM Posted Sunday at 07:46 PM The WM_NCHITTEST message could be what you want. For a basic implementation, check the position and return HTCLIENT (1) ( to accept a click, and HTTRANSPARENT (-1) to pass it along. You get the X and Y from the lParam. You can read more here: https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest WildByDesign 1 To show your appreciation My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser
Solution WildByDesign Posted Monday at 12:09 AM Author Solution Posted Monday at 12:09 AM (edited) 4 hours ago, genius257 said: The WM_NCHITTEST message could be what you want. For a basic implementation, check the position and return HTCLIENT (1) ( to accept a click, and HTTRANSPARENT (-1) to pass it along. You get the X and Y from the lParam. Thank you. I ended up learning a lot from your suggestion. I hadn't done anything with _WinAPI_LoWord() or _WinAPI_HiWord() before and had zero understanding of it. So I spent some time learning it and was able to get this working successfully with your idea to use the WM_NCHITTEST message. So this was a great learning experience for me and I appreciate it. However, unfortunately, I found the WM_NCHITTEST message to be too expensive on resources for this purpose. So not only did I learn from your suggestion, but I also pushed on further to see if I could achieve this in a more efficient way. For clarification, the intent here is for something like that Control Viewer script which does not have a Statusbar, but does have a Scrollbar (grip) window. I needed to find a way to make the background of it transparent. Anyway, I did find a way to achieve the goal in WM_PAINT by keeping the background transparent, having reasonable efficiency and matching DPI scale as well. I did a 2 second Sleep just to show the Before and After. expandcollapse popup#include <WinAPIGdi.au3> #include <WinAPISysWin.au3> #include <WinAPIRes.au3> #include <WindowsStylesConstants.au3> #include <APIResConstants.au3> #include <APIThemeConstants.au3> #include <AutoItConstants.au3> #include <WindowsNotifsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPITheme.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> ; Initialize System DPI awareness DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) Opt("MustDeclareVars", 1) Global $g_hGui, $g_hSizebox, $g_hOldProc, $g_iGripSize Global Const $SP_GRIPPER = 3 Example() ;============================================== Func Example() Local Const $SBS_SIZEBOX = 0x08, $SBS_SIZEGRIP = 0x10 $g_hGui = GUICreate("SBS_SIZEBOX / SBS_SIZEGRIP Testing", 500, 300, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX)) GUISetBkColor(0x191919) ; Get gripper size (different size per DPI) Local $hTheme = _WinAPI_OpenThemeData($g_hGui, 'Status') Local $tSIZE = _WinAPI_GetThemePartSize($hTheme, $SP_GRIPPER, 0, Null, Null, $TS_TRUE) $g_iGripSize = $tSIZE.X _WinAPI_CloseThemeData($hTheme) ; Create SizeBox window $g_hSizebox = _WinAPI_CreateWindowEx(0, "Scrollbar", "", $WS_CHILD + $WS_VISIBLE + $SBS_SIZEBOX, 400 - $g_iGripSize, 200 - $g_iGripSize, $g_iGripSize, $g_iGripSize, $g_hGui) ; $SBS_SIZEBOX or $SBS_SIZEGRIP ; Set dark theme _WinAPI_SetWindowTheme($g_hSizebox, "DarkMode_Explorer") ; Set cursor Local $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZENWSE) _WinAPI_SetClassLongEx($g_hSizebox, -12, $hCursor) ; $GCL_HCURSOR = -12 GUIRegisterMsg($WM_SIZE, _WM_SIZE) SizeboxResize() GUISetState() Sleep(2000) ; Subclass the sizebox (by changing the window procedure associated with the Scrollbar class) Local $hProc = DllCallbackRegister('ScrollbarProc', 'lresult', 'hwnd;uint;wparam;lparam') $g_hOldProc = _WinAPI_SetWindowLong($g_hSizebox, $GWL_WNDPROC, DllCallbackGetPtr($hProc)) _WinAPI_RedrawWindow($g_hGui) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_DestroyCursor($hCursor) _WinAPI_SetWindowLong($g_hSizebox, $GWL_WNDPROC, $g_hOldProc) DllCallbackFree($hProc) EndFunc ;==>Example Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam) SizeboxResize() EndFunc Func SizeboxResize() Local $aSize = WinGetClientSize($g_hGui) WinMove($g_hSizebox, "", $aSize[0] - $g_iGripSize, $aSize[1] - $g_iGripSize) EndFunc ;==>SizeboxResize ;============================================== Func ScrollbarProc($hWnd, $iMsg, $wParam, $lParam) Switch $iMsg Case $WM_ERASEBKGND Return 1 ; Prevent background erasing to avoid flickering Case $WM_PAINT Local $tPAINTSTRUCT Local $hDC = _WinAPI_BeginPaint($hWnd, $tPAINTSTRUCT) Local $iWidth = DllStructGetData($tPAINTSTRUCT, 'rPaint', 3) - DllStructGetData($tPAINTSTRUCT, 'rPaint', 1) Local $iHeight = DllStructGetData($tPAINTSTRUCT, 'rPaint', 4) - DllStructGetData($tPAINTSTRUCT, 'rPaint', 2) ; Paint SizeGrip only when window is not maximized Local $hTheme = _WinAPI_OpenThemeData(_WinAPI_GetParent($hWnd), 'Status') Local $tRectGrip = _WinAPI_CreateRectEx(0, 0, $iWidth, $iHeight) If Not BitAND(WinGetState(_WinAPI_GetParent($hWnd)), $WIN_STATE_MAXIMIZED) Then _WinAPI_DrawThemeBackground($hTheme, $SP_GRIPPER, 0, $hDC, $tRectGrip) EndIf _WinAPI_CloseThemeData($hTheme) _WinAPI_EndPaint($hWnd, $tPAINTSTRUCT) Return 0 EndSwitch Return _WinAPI_CallWindowProc($g_hOldProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>ScrollbarProc Edited Monday at 12:10 AM by WildByDesign genius257 and argumentum 2
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now