nbb1967 Posted February 24 Posted February 24 The default selection in Windows 10-11 on the Desktop is a translucent blue rectangle with non-transparent border. Is it possible to do this in AutoIt? I wanted to use this effect for a screenshot utility. 1. Transparent window 2. Translucent rectangle (ARGB=0x460066CC) 3. Non-transparent border of rectangle (ARGB=0xFF0078D7) For example, at least a static...
Nine Posted February 24 Posted February 24 Yes of course it is possible and it is quite straightforward. I would suggest you create a first GUI with solid borders (you can use _WinAPI GDI functions or _GDIPlus graphic functions). Search the forum there is multiple examples how to perform this. Once your first GUI is working, you will need to create a second GUI with a transparent background. One easy way is to use WinSetTrans. Create the base code for this, if you need some more help, we will be glad to enhance your code to make it work. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy
ioa747 Posted February 24 Posted February 24 here is my approach SmartNote UWPOCR Edition I know that I know nothing
nbb1967 Posted February 25 Author Posted February 25 Thanks, ioa747, but I only see a semi-transparent yellow rectangle in your script. I don't see an opaque border. I can draw them separately, but I can't combine them together. Nine, my script that doesn't work: If I comment out $hRectangle_GUI and the Rectangle creation (left #cs-#ce for convenience) - then the Border is displayed. Both together are not displayed. I can't combine Border and Rectangle in one layer, they have different transparency. expandcollapse popup#Include <Misc.au3> #Include <ScreenCapture.au3> #include <WindowsConstants.au3> Global $iX1, $iY1, $iX2, $iY2, $aPos, $sBMP_Path, $bSuccess Mark_Rect() ; Capture selected area ;$sBMP_Path = @ScriptDir & "\tmp.png" ;_ScreenCapture_Capture($sBMP_Path, $iX1, $iY1, $iX2, $iY2, False) Exit Func Mark_Rect() ; based on Melba23 Local $aMouse_Pos, $hMask, $hMaster_Mask, $hMaster_Mask_2, $iTemp Local $UserDLL = DllOpen("user32.dll") ; Create transparent GUI with Cross cursor $hCross_GUI = GUICreate("Test", @DesktopWidth, @DesktopHeight - 20, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCross_GUI, "", 1) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) ; Create non-transparent GUI for Border of Rectangle Local $hBorder_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST) GUISetBkColor(0x0078D7) ;#cs ; Create translucent GUI for Rectangle Local $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST) WinSetTrans($hRectangle_GUI, "", 70) GUISetBkColor(0x0066CC) ;#ce ; Wait until mouse button pressed While Not _IsPressed("01", $UserDLL) Sleep(10) WEnd ; Get first mouse position $aMouse_Pos = MouseGetPos() $iX1 = $aMouse_Pos[0] $iY1 = $aMouse_Pos[1] ; Draw a selection, wait until the mouse button is released While _IsPressed("01", $UserDLL) $aMouse_Pos = MouseGetPos() ; Create Border $hMaster_Mask_2 = _WinAPI_CreateRectRgn(0, 0, 0, 0) $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $aMouse_Pos[0], $aMouse_Pos[1]) ; Internal Rect _WinAPI_CombineRgn($hMaster_Mask_2, $hMask, $hMaster_Mask_2, $RGN_OR ) _WinAPI_DeleteObject($hMask) $hMask = _WinAPI_CreateRectRgn($iX1, $iY1, $aMouse_Pos[0] + 1, $aMouse_Pos[1] + 1) ; External Rect _WinAPI_CombineRgn($hMaster_Mask_2, $hMask, $hMaster_Mask_2, $RGN_XOR) _WinAPI_DeleteObject($hMask) $bSuccess = _WinAPI_SetWindowRgn($hBorder_GUI, $hMaster_Mask_2, 1) ;ConsoleWrite("Border: " & $bSuccess & @CRLF) If WinGetState($hBorder_GUI) < 15 Then GUISetState() ;#cs ; Create Rectangle $hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0) $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $aMouse_Pos[0], $aMouse_Pos[1]) _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, $RGN_OR) _WinAPI_DeleteObject($hMask) $bSuccess = _WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask, 1) ;ConsoleWrite("Rectangle: " & $bSuccess & @CRLF) If WinGetState($hRectangle_GUI) < 15 Then GUISetState() ;#ce Sleep(10) WEnd ; Get second mouse position $iX2 = $aMouse_Pos[0] $iY2 = $aMouse_Pos[1] ; Set in correct order if required If $iX2 < $iX1 Then $iTemp = $iX1 $iX1 = $iX2 $iX2 = $iTemp EndIf If $iY2 < $iY1 Then $iTemp = $iY1 $iY1 = $iY2 $iY2 = $iTemp EndIf ;Cleaning ;#cs GUIDelete($hRectangle_GUI) ;#ce _WinAPI_DeleteObject($hMaster_Mask) _WinAPI_DeleteObject($hMaster_Mask_2) GUIDelete($hBorder_GUI) GUIDelete($hCross_GUI) DllClose($UserDLL) EndFunc ;==>Mark_Rect
Nine Posted February 25 Posted February 25 Thanks for the effort, here the basis of what you are looking for : expandcollapse popup#include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include <Misc.au3> #include <WinAPIGdi.au3> _ScreenRegion_GetRect(0x78D7, 0x66CC, 2, 46) Func _ScreenRegion_GetRect($iEdge = 0, $iBack = 0xFFFFFF, $iSize = 4, $iTransparency = 0) Local $hCursorGUI = GUICreate("Screen Capture", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCursorGUI, "", 1) GUISetState() GUISetCursor($MCID_CROSS, $GUI_CURSOR_OVERRIDE, $hCursorGUI) Local $hRectGUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST) GUISetBkColor($iEdge) Local $hFillGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW) GUISetBkColor($iBack) WinSetTrans($hFillGUI, "", $iTransparency) GUISetState() While Not _IsPressed("01") And Sleep(10) WEnd Local $iX1 = MouseGetPos(0), $iY1 = MouseGetPos(1) While _IsPressed("01") And Sleep(10) Rect($hRectGUI, $iX1, $iY1, MouseGetPos(0) - $iX1, MouseGetPos(1) - $iY1, $iSize, $hFillGUI) If WinGetState($hRectGUI) < 15 Then GUISetState(@SW_SHOW, $hRectGUI) WEnd GUIDelete($hFillGUI) GUIDelete($hRectGUI) GUIDelete($hCursorGUI) Local $aReturn = [$iX1, $iY1, MouseGetPos(0), MouseGetPos(1)] Return $aReturn EndFunc ;==>_ScreenRegion_GetRect Func Rect($hWnd, $iX, $iY, $iWidth, $iHeight, $iSize, $hFill) WinMove($hFill, "", $iX, $iY, $iWidth, $iHeight) Local $hMain = _WinAPI_CreateRectRgn($iX, $iY, $iX + $iWidth, $iY + $iHeight) Local $hMask = _WinAPI_CreateRectRgn($iX + $iSize, $iY + $iSize, $iX + $iWidth - $iSize, $iY + $iHeight - $iSize) _WinAPI_CombineRgn($hMain, $hMain, $hMask, $RGN_DIFF) _WinAPI_DeleteObject($hMask) _WinAPI_SetWindowRgn($hWnd, $hMain) EndFunc ;==>Rect “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy
nbb1967 Posted February 28 Author Posted February 28 Nine, formally, the problem is solved. In practice, this solution is useless. The WinMove function is too slow and runs with artifacts. Perhaps (this is a hypothesis), it uses animation of window movement or predictions... I added a bit of code to make the function work in any capture direction, not just down and right. If you hold down the left mouse button and move the cursor around the capture start point, you can clearly see WinMove artifacts. But thanks anyway. expandcollapse popup#include <GuiConstantsEx.au3> #include <WindowsConstants.au3> #include <Misc.au3> #include <WinAPIGdi.au3> _ScreenRegion_GetRect(0x78D7, 0x66CC, 1, 46) Func _ScreenRegion_GetRect($iEdge = 0, $iBack = 0xFFFFFF, $iSize = 4, $iTransparency = 0) ;by Nine Local $hCursorGUI = GUICreate("Screen Capture", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCursorGUI, "", 1) GUISetState() GUISetCursor($MCID_CROSS, $GUI_CURSOR_OVERRIDE, $hCursorGUI) Local $hRectGUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST) GUISetBkColor($iEdge) Local $hFillGUI = GUICreate("", 0, 0, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW) GUISetBkColor($iBack) WinSetTrans($hFillGUI, "", $iTransparency) GUISetState() While Not _IsPressed("01") And Sleep(10) WEnd Local $iX1 = MouseGetPos(0), $iY1 = MouseGetPos(1), $iX2, $iY2, $iStartX, $iStartY While _IsPressed("01") And Sleep(10) $iX2 = MouseGetPos(0) $iY2 = MouseGetPos(1) If $iX2 < $iX1 Then $iStartX = $iX2 $iWidth = $iX1 - $iX2 Else $iStartX = $iX1 $iWidth = $iX2 - $iX1 EndIf If $iY2 < $iY1 Then $iStartY = $iY2 $iHeight = $iY1 - $iY2 Else $iStartY = $iY1 $iHeight = $iY2 - $iY1 EndIf Rect($hRectGUI, $iStartX, $iStartY, $iWidth, $iHeight, $iSize, $hFillGUI) If WinGetState($hRectGUI) < 15 Then GUISetState(@SW_SHOW, $hRectGUI) WEnd GUIDelete($hFillGUI) GUIDelete($hRectGUI) GUIDelete($hCursorGUI) Local $aReturn = [$iX1, $iY1, MouseGetPos(0), MouseGetPos(1)] Return $aReturn EndFunc ;==>_ScreenRegion_GetRect Func Rect($hWnd, $iX, $iY, $iWidth, $iHeight, $iSize, $hFill) ;by Nine WinMove($hFill, "", $iX, $iY, $iWidth, $iHeight) Local $hMain = _WinAPI_CreateRectRgn($iX, $iY, $iX + $iWidth, $iY + $iHeight) Local $hMask = _WinAPI_CreateRectRgn($iX + $iSize, $iY + $iSize, $iX + $iWidth - $iSize, $iY + $iHeight - $iSize) _WinAPI_CombineRgn($hMain, $hMain, $hMask, $RGN_DIFF) _WinAPI_DeleteObject($hMask) _WinAPI_SetWindowRgn($hWnd, $hMain) EndFunc ;==>Rect
Solution Nine Posted February 28 Solution Posted February 28 (edited) 14 hours ago, nbb1967 said: you can clearly see WinMove artifacts Try this version : expandcollapse popup#include <GDIPlus.au3> #include <Misc.au3> #include <WinAPISysWin.au3> #include <GUIConstants.au3> Local $aPos = _ScreenRegion_GetRect(0xFF0078D7, 0x460066CC, 2) ConsoleWrite($aPos[0] & "/" & $aPos[1] & "/" & $aPos[2] & "/" & $aPos[3] & @CRLF) Func _ScreenRegion_GetRect($nEdge = 0xFF000000, $nFill = 0, $iSize = 3) _GDIPlus_Startup() Local $hCursorGUI = GUICreate("Screen Capture", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCursorGUI, "", 1) GUISetState() GUISetCursor($MCID_CROSS, $GUI_CURSOR_OVERRIDE, $hCursorGUI) Local $hCapture = GUICreate("", 0, 0, 0, 0, $WS_POPUPWINDOW, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST, $WS_EX_TOOLWINDOW), $hCursorGUI) GUISetState() While Not _IsPressed("01") And Sleep(10) WEnd Local $iX1 = MouseGetPos(0), $iY1 = MouseGetPos(1) While _IsPressed("01") Rect($hCapture, $iX1, $iY1, MouseGetPos(0) - $iX1, MouseGetPos(1) - $iY1, $nEdge, $nFill, $iSize) WEnd Local $aReturn = [$iX1, $iY1, MouseGetPos(0), MouseGetPos(1)] GUIDelete($hCursorGUI) GUIDelete($hCapture) _GDIPlus_Shutdown() Return $aReturn EndFunc ;==>_ScreenRegion_GetRect Func Rect($hWnd, $iPosX, $iPosY, $iWidth, $iHeight, $nEdge, $nFill, $iSize) Local $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight) Local $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage) Local $hPen = _GDIPlus_PenCreate($nEdge, $iSize) Local $hBrush = _GDIPlus_BrushCreateSolid($nFill) _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hBrush) _GDIPlus_GraphicsDrawRect($hGraphic, $iSize, $iSize, $iWidth - ($iSize * 2), $iHeight - ($iSize * 2), $hPen) _GDIPlus_PenDispose($hPen) _GDIPlus_BrushDispose($hBrush) Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) _GDIPlus_ImageDispose($hImage) _GDIPlus_GraphicsDispose($hGraphic) _WinAPI_SetWindowPos($hWnd, 0, $iPosX, $iPosY, $iWidth, $iHeight, $SWP_NOZORDER) _WinAPI_UpdateLayeredWindowEx($hWnd, -1, -1, $hBitmap, 255, True) EndFunc ;==>Rect Edited February 28 by Nine better code “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy
nbb1967 Posted March 1 Author Posted March 1 (edited) Thank you very much! This GDIPlus script looks so simple, so beautiful, so logical, that it makes me sad... But why does this script load one of the processor cores by 100%? Is GDIPlus itself so heavy? I wrote my own version in GDI. It works, but I am not sure about the legality of my actions and approaches. I will post it in the hope of criticism. expandcollapse popup#Include <Misc.au3> #Include <ScreenCapture.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Global $iX1, $iY1, $iX2, $iY2 Blue_Select() Exit Func Blue_Select() Local $aMouse_Pos, $hMask Local $UserDLL = DllOpen("user32.dll") ;Create transparent GUI with Cross cursor $hCross_GUI = GUICreate("Test", @DesktopWidth, @DesktopHeight - 20, 0, 0, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST)) WinSetTrans($hCross_GUI, "", 1) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) ;Creating an non-transparent GUI for initial Border forming Local $hBorder_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_LAYERED) ;Create transparament target layer for non-transparent Border Local $hTarget_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_LAYERED) GUISetBkColor(0xff8080) _WinAPI_SetLayeredWindowAttributes($hTarget_GUI,0xff8080) GUISetState(@SW_SHOW, $hTarget_GUI) ;Create translucent GUI for Rectangle Local $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST)) WinSetTrans($hRectangle_GUI, "", 70) GUISetBkColor(0x0066CC) Local $hDCDestTarget = _WinAPI_GetDC($hTarget_GUI) Local $hDCDestBorder = _WinAPI_GetDC($hBorder_GUI) Local $hDCSource = _WinAPI_CreateCompatibleDC($hDCDestBorder) Local $hHBitmap = _WinAPI_CreateSolidBitmap($hBorder_GUI, 0, @DesktopWidth, @DesktopHeight) Local $hBrush = _WinAPI_CreateSolidBrush(0x00d77800) Local $tRectLeft, $tRectTop, $tRectRight, $tRectBottom, $tRectCenter ;Wait until mouse button pressed While Not _IsPressed("01", $UserDLL) Sleep(10) WEnd ;Get first mouse position $aMouse_Pos = MouseGetPos() $iX1 = $aMouse_Pos[0] $iY1 = $aMouse_Pos[1] ;Draw a selection, wait until the mouse button is released While _IsPressed("01", $UserDLL) $aMouse_Pos = MouseGetPos() $iX2 = $aMouse_Pos[0] $iY2 = $aMouse_Pos[1] _WinAPI_InvalidateRect($hBorder_GUI) _WinAPI_InvalidateRect($hTarget_GUI) ;Create Border _WinAPI_SelectObject($hDCSource, $hHBitmap) $tRectTop = _WinAPI_CreateRect($iX1, $iY1, $iX2 + 1, $iY1 + 1) $tRectLeft = _WinAPI_CreateRect($iX1, $iY1, $iX1 + 1, $iY2 + 1) $tRectRight = _WinAPI_CreateRect($iX2, $iY1, $iX2 + 1, $iY2 + 1) $tRectBottom = _WinAPI_CreateRect($iX1, $iY2, $iX2 + 1, $iY2 + 1) _WinAPI_FillRect($hDCSource, $tRectTop, $hBrush) _WinAPI_FillRect($hDCSource, $tRectLeft, $hBrush) _WinAPI_FillRect($hDCSource, $tRectRight, $hBrush) _WinAPI_FillRect($hDCSource, $tRectBottom, $hBrush) ;Create Rectangle $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $iX2, $iY2) _WinAPI_SetWindowRgn($hRectangle_GUI, $hMask, 1) If WinGetState($hRectangle_GUI) < 15 Then GUISetState(@SW_SHOW, $hRectangle_GUI) ;Transferring a border to a transparent layer _WinAPI_BitBlt($hDCDestTarget, $iX1, $iY1, ($iX2 + 1) - $iX1, ($iY1 + 1) - $iY1, $hDCSource, $iX1, $iY1, $SRCCOPY) _WinAPI_BitBlt($hDCDestTarget, $iX1, $iY1, ($iX1 + 1) - $iX1, ($iY2 + 1) - $iY1, $hDCSource, $iX1, $iY1, $SRCCOPY) _WinAPI_BitBlt($hDCDestTarget, $iX2, $iY1, ($iX2 + 1) - $iX2, ($iY2 + 1) - $iY1, $hDCSource, $iX2, $iY1, $SRCCOPY) _WinAPI_BitBlt($hDCDestTarget, $iX1, $iY2, ($iX2 + 1) - $iX1, ($iY2 + 1) - $iY2, $hDCSource, $iX1, $iY2, $SRCCOPY) Sleep(20);less than 20: flickers WEnd ;Cleaning _WinAPI_ReleaseDC($hTarget_GUI, $hDCDestTarget) _WinAPI_ReleaseDC($hBorder_GUI, $hDCDestBorder) _WinAPI_DeleteDC($hDCSource) _WinAPI_DeleteObject($hHBitmap) _WinAPI_DeleteObject($hBrush) _WinAPI_DeleteObject($hMask) GUIDelete($hTarget_GUI) GUIDelete($hRectangle_GUI) GUIDelete($hBorder_GUI) GUIDelete($hCross_GUI) DllClose($UserDLL) EndFunc ;==>Blue_Select Edited March 1 by nbb1967
Nine Posted March 1 Posted March 1 (edited) 46 minutes ago, nbb1967 said: But why does this script load one of the processor cores by 100%? Forgot to put some sleep in...But who cares if one CPU is at 100% when you have 16 available. ps. not bad script of yours, however like you said before there are some artifacts. It is not as smooth as it can be... Edited March 1 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy
nbb1967 Posted March 2 Author Posted March 2 I turned on the 8x magnifying glass and yes, I see small artifacts in my script: sometimes the border breaks away from the light rectangle. Strange... Unfortunately, my script also flickers at low Sleep values in the loop. I'm using your script, Nine. Thanks!!!
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