Trong Posted 17 hours ago Posted 17 hours ago (edited) Because working with multiple monitors was required during the development of ImageSearchUDF , this UDF was created UDF: expandcollapse popup#include-once #include <WinAPIGdi.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> ; =============================================================================================================================== ; Title .........: Monitor UDF ; Description ...: Provides advanced monitor management and multi-monitor utilities. ; Author ........: Dao Van Trong - TRONG.PRO ; <MonitorUDF.au3> ; =============================================================================================================================== ; FUNCTIONS SUMMARY ; =============================================================================================================================== ; _Monitor_GetList() - Enumerate connected monitors and fill global info. ; _Monitor_GetCount() - Return total number of monitors. ; _Monitor_GetPrimary() - Get index of the primary monitor. ; _Monitor_GetInfo($iMonitor) - Get detailed info about a monitor. ; _Monitor_GetBounds($iMonitor, ...) - Get full monitor rectangle (including taskbar). ; _Monitor_GetWorkArea($iMonitor, ...) - Get working area of a monitor (excluding taskbar). ; _Monitor_GetDisplaySettings($iMonitor) - Get current display mode. ; _Monitor_GetResolution($iMonitor) - Get monitor resolution. ; _Monitor_GetFromPoint([$x, $y]) - Get monitor from screen point or mouse. ; _Monitor_GetFromWindow($hWnd) - Get monitor containing a specific window. ; _Monitor_GetFromRect(...) - Get monitor overlapping a given rectangle. ; _Monitor_GetVirtualBounds() - Get bounding rectangle of the entire virtual screen. ; _Monitor_ToVirtual($iMonitor, $x, $y) - Convert local monitor coordinates to virtual coordinates. ; _Monitor_FromVirtual($iMonitor, $x, $y)- Convert from virtual to local monitor coordinates. ; _Monitor_IsVisibleWindow($hWnd) - Check if a window is top-level visible. ; _Monitor_MoveWindowToScreen(...) - Move a window to specific monitor (center if unspecified). ; _Monitor_MoveWindowToAll(...) - Move a visible window across all monitors. ; _Monitor_EnumAllDisplayModes($iMonitor)- Enumerate all available display modes. ; _Monitor_ShowInfo() - Show all monitor information in MsgBox. ; =============================================================================================================================== #Region --- Global Variables --- ; =============================================================================================================================== ; Global Monitor Information Array ; =============================================================================================================================== ; $__g_aMonitorList[][] structure: ; ; [0][0] = Number of monitors detected ; [0][1] = Virtual desktop Left coordinate (combined area) ; [0][2] = Virtual desktop Top coordinate ; [0][3] = Virtual desktop Right coordinate ; [0][4] = Virtual desktop Bottom coordinate ; [0][5] = Virtual desktop Width ; [0][6] = Virtual desktop Height ; ; For each monitor index i (1..$__g_aMonitorList[0][0]): ; [i][0] = Monitor handle (HMONITOR) ; [i][1] = Left coordinate of monitor ; [i][2] = Top coordinate of monitor ; [i][3] = Right coordinate of monitor ; [i][4] = Bottom coordinate of monitor ; [i][5] = IsPrimary (1 if primary, 0 otherwise) ; [i][6] = Device name string (e.g. "\\.\DISPLAY1") ; ; Example: ; ;If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() ; $__g_aMonitorList[0][0] = 2 ; $__g_aMonitorList[1] = [0x00010001, 0, 0, 1920, 1080, 1, "\\.\DISPLAY1"] ; $__g_aMonitorList[2] = [0x00020002, 1920, 0, 3840, 1080, 0, "\\.\DISPLAY2"] ; ; =============================================================================================================================== Global $__g_aMonitorList[1][7] = [[0, 0, 0, 0, 0, 0, ""]] #EndRegion --- Global Variables --- ; =============================================================================================================================== ; FUNCTION: _Monitor_GetFromPoint([$iX = -1[, $iY = -1]]) ; PURPOSE : Get the monitor index from a screen coordinate or current mouse position ; RETURN : Monitor index (1..N) or 0 if not found ; =============================================================================================================================== Func _Monitor_GetFromPoint($iX = -1, $iY = -1) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() ; Use WinAPI function if available If $iX = -1 Or $iY = -1 Then Local $aMouse = MouseGetPos() $iX = $aMouse[0] $iY = $aMouse[1] EndIf Local $tPoint = DllStructCreate($tagPOINT) DllStructSetData($tPoint, "X", $iX) DllStructSetData($tPoint, "Y", $iY) Local $hMonitor = _WinAPI_MonitorFromPoint($tPoint, $MONITOR_DEFAULTTONEAREST) ; Find index in our list For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next ; Fallback to coordinate checking For $i = 1 To $__g_aMonitorList[0][0] If $iX >= $__g_aMonitorList[$i][1] _ And $iX < $__g_aMonitorList[$i][3] _ And $iY >= $__g_aMonitorList[$i][2] _ And $iY < $__g_aMonitorList[$i][4] Then Return $i EndIf Next Return 0 EndFunc ;==>_Monitor_GetFromPoint ; =============================================================================================================================== ; FUNCTION: _Monitor_GetFromWindow($hWnd[, $iFlag = $MONITOR_DEFAULTTONEAREST]) ; PURPOSE : Get the monitor index that contains the specified window ; RETURN : Monitor index (1..N) or 0 if not found ; =============================================================================================================================== Func _Monitor_GetFromWindow($hWnd, $iFlag = $MONITOR_DEFAULTTONEAREST) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd) If Not $hWnd Then Return SetError(1, 0, 0) Local $hMonitor = _WinAPI_MonitorFromWindow($hWnd, $iFlag) If Not $hMonitor Then Return SetError(2, 0, 0) For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next Return 0 EndFunc ;==>_Monitor_GetFromWindow ; =============================================================================================================================== ; FUNCTION: _Monitor_GetFromRect($iLeft, $iTop, $iRight, $iBottom[, $iFlag = $MONITOR_DEFAULTTONEAREST]) ; PURPOSE : Get the monitor index that has the largest intersection with the specified rectangle ; RETURN : Monitor index (1..N) or 0 if not found ; =============================================================================================================================== Func _Monitor_GetFromRect($iLeft, $iTop, $iRight, $iBottom, $iFlag = $MONITOR_DEFAULTTONEAREST) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() Local $tRect = DllStructCreate($tagRECT) DllStructSetData($tRect, "Left", $iLeft) DllStructSetData($tRect, "Top", $iTop) DllStructSetData($tRect, "Right", $iRight) DllStructSetData($tRect, "Bottom", $iBottom) Local $hMonitor = _WinAPI_MonitorFromRect($tRect, $iFlag) If Not $hMonitor Then Return SetError(1, 0, 0) For $i = 1 To $__g_aMonitorList[0][0] If $__g_aMonitorList[$i][0] = $hMonitor Then Return $i Next Return 0 EndFunc ;==>_Monitor_GetFromRect ; =============================================================================================================================== ; FUNCTION: _Monitor_GetWorkArea($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) ; PURPOSE : Get working area of a specific monitor (excluding taskbar) ; RETURN : 1 on success, 0 on failure ; =============================================================================================================================== Func _Monitor_GetWorkArea($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $hMonitor = $__g_aMonitorList[$iMonitor][0] Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If @error Then Return SetError(2, 0, 0) Local $tWorkArea = $aInfo[1] $left = DllStructGetData($tWorkArea, "Left") $top = DllStructGetData($tWorkArea, "Top") $right = DllStructGetData($tWorkArea, "Right") $bottom = DllStructGetData($tWorkArea, "Bottom") Return 1 EndFunc ;==>_Monitor_GetWorkArea ; =============================================================================================================================== ; FUNCTION: _Monitor_GetBounds($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) ; PURPOSE : Get full bounds of a specific monitor (including taskbar) ; RETURN : 1 on success, 0 on failure ; =============================================================================================================================== Func _Monitor_GetBounds($iMonitor, ByRef $left, ByRef $top, ByRef $right, ByRef $bottom) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) $left = $__g_aMonitorList[$iMonitor][1] $top = $__g_aMonitorList[$iMonitor][2] $right = $__g_aMonitorList[$iMonitor][3] $bottom = $__g_aMonitorList[$iMonitor][4] Return 1 EndFunc ;==>_Monitor_GetBounds ; =============================================================================================================================== ; FUNCTION: _Monitor_GetInfo($iMonitor) ; PURPOSE : Get detailed information about a monitor ; RETURN : Array [Handle, Left, Top, Right, Bottom, WorkLeft, WorkTop, WorkRight, WorkBottom, IsPrimary, DeviceName] ; =============================================================================================================================== Func _Monitor_GetInfo($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $hMonitor = $__g_aMonitorList[$iMonitor][0] Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If @error Then Return SetError(2, 0, 0) Local $tMonitorRect = $aInfo[0] Local $tWorkRect = $aInfo[1] Local $aResult[11] $aResult[0] = $hMonitor $aResult[1] = DllStructGetData($tMonitorRect, "Left") $aResult[2] = DllStructGetData($tMonitorRect, "Top") $aResult[3] = DllStructGetData($tMonitorRect, "Right") $aResult[4] = DllStructGetData($tMonitorRect, "Bottom") $aResult[5] = DllStructGetData($tWorkRect, "Left") $aResult[6] = DllStructGetData($tWorkRect, "Top") $aResult[7] = DllStructGetData($tWorkRect, "Right") $aResult[8] = DllStructGetData($tWorkRect, "Bottom") $aResult[9] = ($aInfo[2] <> 0) ; IsPrimary $aResult[10] = $aInfo[3] ; DeviceName Return $aResult EndFunc ;==>_Monitor_GetInfo ; =============================================================================================================================== ; FUNCTION: _Monitor_GetDisplaySettings($iMonitor[, $iMode = $ENUM_CURRENT_SETTINGS]) ; PURPOSE : Get display settings for a monitor ; RETURN : Array [Width, Height, BitsPerPixel, Frequency, DisplayMode] ; =============================================================================================================================== Func _Monitor_GetDisplaySettings($iMonitor, $iMode = $ENUM_CURRENT_SETTINGS) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $sDevice = $__g_aMonitorList[$iMonitor][6] If $sDevice = "" Then Local $aInfo = _Monitor_GetInfo($iMonitor) If @error Then Return SetError(2, 0, 0) $sDevice = $aInfo[10] EndIf Local $aSettings = _WinAPI_EnumDisplaySettings($sDevice, $iMode) If @error Then Return SetError(3, 0, 0) Return $aSettings EndFunc ;==>_Monitor_GetDisplaySettings ; =============================================================================================================================== ; FUNCTION: _Monitor_GetResolution($iMonitor) ; PURPOSE : Get resolution of a monitor ; RETURN : Array [Width, Height] ; =============================================================================================================================== Func _Monitor_GetResolution($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aSettings = _Monitor_GetDisplaySettings($iMonitor) If @error Then Return SetError(2, 0, 0) Local $aResult[2] = [$aSettings[0], $aSettings[1]] Return $aResult EndFunc ;==>_Monitor_GetResolution ; =============================================================================================================================== ; FUNCTION: _Monitor_GetPrimary() ; PURPOSE : Get the index of the primary monitor ; RETURN : Monitor index (1..N) or 0 if not found ; =============================================================================================================================== Func _Monitor_GetPrimary() If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() For $i = 1 To $__g_aMonitorList[0][0] Local $aInfo = _Monitor_GetInfo($i) If Not @error And $aInfo[9] = 1 Then Return $i Next Return 0 EndFunc ;==>_Monitor_GetPrimary ; =============================================================================================================================== ; FUNCTION: _Monitor_GetCount() ; PURPOSE : Returns total number of monitors ; =============================================================================================================================== Func _Monitor_GetCount() Local $aRet = DllCall("user32.dll", "int", "GetSystemMetrics", "int", $SM_CMONITORS) If @error Or Not IsArray($aRet) Then If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() Return $__g_aMonitorList[0][0] Else Return $aRet[0] EndIf EndFunc ;==>_Monitor_GetCount ; =============================================================================================================================== ; FUNCTION: _Monitor_GetVirtualBounds() ; PURPOSE : Get bounding rectangle of all monitors (the "virtual screen") ; RETURN : Array [Left, Top, Width, Height] ; =============================================================================================================================== Func _Monitor_GetVirtualBounds() Local $aL = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 76) ; SM_XVIRTUALSCREEN Local $aT = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 77) ; SM_YVIRTUALSCREEN Local $aW = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 78) ; SM_CXVIRTUALSCREEN Local $aH = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 79) ; SM_CYVIRTUALSCREEN Local $a[4] = [$aL[0], $aT[0], $aW[0], $aH[0]] Return $a EndFunc ;==>_Monitor_GetVirtualBounds ; =============================================================================================================================== ; FUNCTION: _Monitor_ToVirtual($iMonitor, $x, $y) ; PURPOSE : Convert local monitor coordinates to virtual screen coordinates ; =============================================================================================================================== Func _Monitor_ToVirtual($iMonitor, $x, $y) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aRet[2] = [$__g_aMonitorList[$iMonitor][1] + $x, $__g_aMonitorList[$iMonitor][2] + $y] Return $aRet EndFunc ;==>_Monitor_ToVirtual ; =============================================================================================================================== ; FUNCTION: _Monitor_FromVirtual($iMonitor, $x, $y) ; PURPOSE : Convert virtual coordinates back to local monitor coordinates ; =============================================================================================================================== Func _Monitor_FromVirtual($iMonitor, $x, $y) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aRet[2] = [$x - $__g_aMonitorList[$iMonitor][1], $y - $__g_aMonitorList[$iMonitor][2]] Return $aRet EndFunc ;==>_Monitor_FromVirtual ; =============================================================================================================================== ; FUNCTION: _Monitor_IsVisibleWindow($hWnd) ; PURPOSE : Check if window is visible and top-level ; RETURN : True / False ; =============================================================================================================================== Func _Monitor_IsVisibleWindow($hWnd) If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd) If Not $hWnd Or Not WinExists($hWnd) Then Return False Local $style = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE) If BitAND($style, $WS_VISIBLE) = 0 Then Return False If BitAND($style, $WS_CHILD) <> 0 Then Return False Local $ex = _WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE) If BitAND($ex, $WS_EX_TOOLWINDOW) <> 0 Then Return False Return True EndFunc ;==>_Monitor_IsVisibleWindow ; =============================================================================================================================== ; FUNCTION: _Monitor_MoveWindowToScreen($vTitle, $sText = "", $iMonitor = -1, $x = -1, $y = -1, $bUseWorkArea = True) ; PURPOSE : Move visible window to a monitor (centered if $x=$y=-1) ; =============================================================================================================================== Func _Monitor_MoveWindowToScreen($vTitle, $sText = "", $iMonitor = -1, $x = -1, $y = -1, $bUseWorkArea = True) Local $hWnd = IsHWnd($vTitle) ? $vTitle : WinGetHandle($vTitle, $sText) If Not _Monitor_IsVisibleWindow($hWnd) Then Return SetError(1, 0, 0) If $iMonitor = -1 Then $iMonitor = 1 If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(2, 0, 0) Local $aWinPos = WinGetPos($hWnd) If @error Or Not IsArray($aWinPos) Then Return SetError(3, 0, 0) Local $iLeft, $iTop, $iRight, $iBottom If $bUseWorkArea Then _Monitor_GetWorkArea($iMonitor, $iLeft, $iTop, $iRight, $iBottom) Else _Monitor_GetBounds($iMonitor, $iLeft, $iTop, $iRight, $iBottom) EndIf Local $iWidth = $iRight - $iLeft Local $iHeight = $iBottom - $iTop If $x = -1 Or $y = -1 Then $x = $iLeft + ($iWidth - $aWinPos[2]) / 2 $y = $iTop + ($iHeight - $aWinPos[3]) / 2 Else $x += $iLeft $y += $iTop EndIf WinMove($hWnd, "", $x, $y) Return 1 EndFunc ;==>_Monitor_MoveWindowToScreen ; =============================================================================================================================== ; FUNCTION: _Monitor_MoveWindowToAll($vTitle, $sText = "", $bCenter = True, $iDelay = 1000) ; PURPOSE : Move a visible window sequentially across all monitors ; =============================================================================================================================== Func _Monitor_MoveWindowToAll($vTitle, $sText = "", $bCenter = True, $iDelay = 1000) Local $hWnd = IsHWnd($vTitle) ? $vTitle : WinGetHandle($vTitle, $sText) If Not _Monitor_IsVisibleWindow($hWnd) Then Return SetError(1, 0, 0) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() For $i = 1 To $__g_aMonitorList[0][0] If $bCenter Then _Monitor_MoveWindowToScreen($hWnd, "", $i) Else _Monitor_MoveWindowToScreen($hWnd, "", $i, 50, 50) EndIf Sleep($iDelay) Next Return 1 EndFunc ;==>_Monitor_MoveWindowToAll ; =============================================================================================================================== ; FUNCTION: _Monitor_EnumAllDisplayModes($iMonitor) ; PURPOSE : Enumerate all available display modes for a monitor ; RETURN : 2D array [[Width, Height, BitsPerPixel, Frequency, DisplayMode], ...] ; =============================================================================================================================== Func _Monitor_EnumAllDisplayModes($iMonitor) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() If $iMonitor < 1 Or $iMonitor > $__g_aMonitorList[0][0] Then Return SetError(1, 0, 0) Local $aInfo = _Monitor_GetInfo($iMonitor) If @error Then Return SetError(2, 0, 0) Local $sDevice = $aInfo[10] Local $aModes[1][5] $aModes[0][0] = 0 Local $iIndex = 0 While True Local $aMode = _WinAPI_EnumDisplaySettings($sDevice, $iIndex) If @error Then ExitLoop ReDim $aModes[$aModes[0][0] + 2][5] $aModes[0][0] += 1 $aModes[$aModes[0][0]][0] = $aMode[0] $aModes[$aModes[0][0]][1] = $aMode[1] $aModes[$aModes[0][0]][2] = $aMode[2] $aModes[$aModes[0][0]][3] = $aMode[3] $aModes[$aModes[0][0]][4] = $aMode[4] $iIndex += 1 WEnd If $aModes[0][0] = 0 Then Return SetError(3, 0, 0) Return $aModes EndFunc ;==>_Monitor_EnumAllDisplayModes ; =============================================================================================================================== ; FUNCTION: _Monitor_GetList() ; PURPOSE : Enumerate connected monitors and fill the global list using _WinAPI_EnumDisplayMonitors ; RETURN : Number of monitors, or -1 on error ; =============================================================================================================================== Func _Monitor_GetList() Local $aMonitors = _WinAPI_EnumDisplayMonitors() If @error Then Return SetError(1, 0, -1) ReDim $__g_aMonitorList[$aMonitors[0][0] + 1][7] $__g_aMonitorList[0][0] = $aMonitors[0][0] Local $l_aVirtual = _Monitor_GetVirtualBounds() Local $l_vRight = $l_aVirtual[0] + $l_aVirtual[2] Local $l_vBottom = $l_aVirtual[1] + $l_aVirtual[3] $__g_aMonitorList[0][1] = $l_aVirtual[0] $__g_aMonitorList[0][2] = $l_aVirtual[1] $__g_aMonitorList[0][3] = $l_vRight $__g_aMonitorList[0][4] = $l_vBottom $__g_aMonitorList[0][5] = $l_aVirtual[2] $__g_aMonitorList[0][6] = $l_aVirtual[3] For $i = 1 To $aMonitors[0][0] Local $hMonitor = $aMonitors[$i][0] Local $tRect = $aMonitors[$i][1] $__g_aMonitorList[$i][0] = $hMonitor $__g_aMonitorList[$i][1] = DllStructGetData($tRect, "Left") $__g_aMonitorList[$i][2] = DllStructGetData($tRect, "Top") $__g_aMonitorList[$i][3] = DllStructGetData($tRect, "Right") $__g_aMonitorList[$i][4] = DllStructGetData($tRect, "Bottom") ; Get additional info Local $aInfo = _WinAPI_GetMonitorInfo($hMonitor) If Not @error Then Local $tWorkRect = $aInfo[1] $__g_aMonitorList[$i][5] = DllStructGetPtr($tWorkRect) $__g_aMonitorList[$i][6] = $aInfo[3] ; Device name EndIf Next Return $__g_aMonitorList[0][0] EndFunc ;==>_Monitor_GetList ; =============================================================================================================================== ; FUNCTION: _Monitor_ShowInfo($iTimeout = 10) ; PURPOSE : Show monitor coordinates and detailed information ; =============================================================================================================================== Func _Monitor_ShowInfo($Msg = 1, $iTimeout = 10) If $__g_aMonitorList[0][0] = 0 Then _Monitor_GetList() Local $sMsg = "> Total Monitors: " & $__g_aMonitorList[0][0] & @CRLF & @CRLF $sMsg &= StringFormat("+ Virtual Desktop: " & @CRLF & "Left=%d, Top=%d, Right=%d, Bottom=%d, Width=%d, Height=%d", $__g_aMonitorList[0][1], $__g_aMonitorList[0][2], $__g_aMonitorList[0][3], $__g_aMonitorList[0][4], $__g_aMonitorList[0][5], $__g_aMonitorList[0][6]) & @CRLF & @CRLF ; For $i = 1 To $__g_aMonitorList[0][0] Local $aInfo = _Monitor_GetInfo($i) If @error Then ContinueLoop Local $aSettings = _Monitor_GetDisplaySettings($i) Local $sResolution = @error ? "N/A" : $aSettings[0] & "x" & $aSettings[1] & " @" & $aSettings[3] & "Hz" $sMsg &= StringFormat("+ Monitor %d: %s%s\n", $i, $aInfo[9] ? "(Primary) " : "", $aInfo[10]) $sMsg &= StringFormat(" Bounds: L=%d, T=%d, R=%d, B=%d (%dx%d)\n", _ $aInfo[1], $aInfo[2], $aInfo[3], $aInfo[4], _ $aInfo[3] - $aInfo[1], $aInfo[4] - $aInfo[2]) $sMsg &= StringFormat(" Work Area: L=%d, T=%d, R=%d, B=%d (%dx%d)\n", _ $aInfo[5], $aInfo[6], $aInfo[7], $aInfo[8], _ $aInfo[7] - $aInfo[5], $aInfo[8] - $aInfo[6]) $sMsg &= " Resolution: " & $sResolution & @CRLF & @CRLF Next ConsoleWrite($sMsg) If $Msg Then MsgBox(64 + 262144, "Monitor Information", $sMsg, $iTimeout) Return $sMsg EndFunc ;==>_Monitor_ShowInfo ;~ _Monitor_ShowInfo(1, 3) EG: expandcollapse popup; ================================================================================================== ; MonitorUDF_Examples.au3 ; Interactive example tester for MonitorUDF.au3 UDF (fixed: uses GuiListBox functions correctly) ; ================================================================================================== #include <GUIConstantsEx.au3> #include <ButtonConstants.au3> #include <WindowsConstants.au3> #include <GuiListBox.au3> #include <GuiEdit.au3> #include <Array.au3> #include "MonitorUDF.au3" ; make sure this file is In the same folder ; ================================================================================================== ; MonitorUDF_Examples.au3 ; Interactive tester with buttons for each MonitorUDF function + log edit ; Requires: MonitorUDF.au3 in the same folder ; ================================================================================================== ; ----------------------------- ; Create GUI ; ----------------------------- Global $GUI_W = 560, $GUI_H = 540 Global $hGUI = GUICreate("MonitorUDF - Examples (by TRONG.PRO)", $GUI_W, $GUI_H, -1, -1) GUISetBkColor(0xF5F5F5, $hGUI) ; Title GUICtrlCreateLabel("MonitorUDF Example Launcher", 12, 10, 400, 24) GUICtrlSetFont(-1, 12, 800, 0, 'Segoe UI', 5) ; Buttons column 1 Local $x1 = 12, $y1 = 48, $bw = 260, $bh = 36, $gap = 8 Global $iBtn1 = GUICtrlCreateButton("1. Enumerate monitors", $x1, $y1, $bw, $bh) Global $iBtn2 = GUICtrlCreateButton("2. Move Notepad -> Monitor #2 (center)", $x1, $y1 + ($bh + $gap) * 1, $bw, $bh) Global $iBtn3 = GUICtrlCreateButton("3. Move Notepad -> Monitor #2 @ (100,100)", $x1, $y1 + ($bh + $gap) * 2, $bw, $bh) Global $iBtn4 = GUICtrlCreateButton("4. Which monitor is mouse on?", $x1, $y1 + ($bh + $gap) * 3, $bw, $bh) Global $iBtn5 = GUICtrlCreateButton("5. Show virtual desktop bounds", $x1, $y1 + ($bh + $gap) * 4, $bw, $bh) ; Buttons column 2 Local $x2 = $x1 + $bw + 12 Global $iBtn6 = GUICtrlCreateButton("6. Convert coords (local <-> virtual)", $x2, $y1 + ($bh + $gap) * 0, $bw, $bh) Global $iBtn7 = GUICtrlCreateButton("7. Show monitor info (MsgBox)", $x2, $y1 + ($bh + $gap) * 1, $bw, $bh) Global $iBtn8 = GUICtrlCreateButton("8. Check if Notepad is visible", $x2, $y1 + ($bh + $gap) * 2, $bw, $bh) Global $iBtn9 = GUICtrlCreateButton("9. Move all visible windows -> primary", $x2, $y1 + ($bh + $gap) * 3, $bw, $bh) Global $iBtn10 = GUICtrlCreateButton("10. Create small GUI on each monitor", $x2, $y1 + ($bh + $gap) * 4, $bw, $bh) ; Controls: log edit, clear, auto-demo, close Local $logX = 12, $logY = $y1 + ($bh + $gap) * 6 Local $logW = $GUI_W - 24, $logH = 180 Global $idLog = GUICtrlCreateEdit("", $logX, $logY, $logW, $logH, BitOR($ES_READONLY, $WS_HSCROLL, $WS_VSCROLL, $ES_MULTILINE)) GUICtrlSetFont($idLog, 9) Global $idFuncTest__ClearLog = GUICtrlCreateButton("Clear Log", 12, $logY + $logH + 10, 120, 28) Global $idFuncTest__RunAllDemo = GUICtrlCreateButton("Auto Demo (Run 1..10)", 150, $logY + $logH + 10, 220, 28) Global $idFuncTest__Close = GUICtrlCreateButton("Close", $GUI_W - 120, $logY + $logH + 10, 100, 28) Global $pidNotepad = 0 GUISetState(@SW_SHOW) ; Keep a list of created GUIs for Example 10 so we can close them later Global $Msg, $g_createdGUIs = [] ; ----------------------------- ; Main loop ; ----------------------------- While 1 $Msg = GUIGetMsg() Switch $Msg Case $GUI_EVENT_CLOSE, $idFuncTest__Close ; close any GUIs created in example 10 For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next ExitLoop Case $idFuncTest__ClearLog GUICtrlSetData($idLog, '', '') Case $idFuncTest__RunAllDemo FuncTest_1() Sleep(1000) ; $iBtn2 FuncTest_2() Sleep(2000) ; $iBtn3 ProcessClose($pidNotepad) FuncTest_3() Sleep(2000) ; $iBtn4 ProcessClose($pidNotepad) FuncTest_4() Sleep(1000) ; $iBtn5 FuncTest_5() Sleep(1000) ; $iBtn6 FuncTest_6() Sleep(1000) ; $iBtn7 FuncTest_7() Sleep(1000) ; $iBtn8 FuncTest_8() Sleep(2000) ; $iBtn9 ProcessClose($pidNotepad) FuncTest_9() Sleep(1000) ; $iBtn10 FuncTest_10() Sleep(2000) ; $iBtn10 For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next Case $iBtn1 FuncTest_1() Case $iBtn2 FuncTest_2() Case $iBtn3 FuncTest_3() Case $iBtn4 FuncTest_4() Case $iBtn5 FuncTest_5() Case $iBtn6 FuncTest_6() Case $iBtn7 FuncTest_7() Case $iBtn8 FuncTest_8() Case $iBtn9 FuncTest_9() Case $iBtn10 FuncTest_10() EndSwitch Sleep(5) WEnd GUIDelete() Exit 0 ; ----------------------------- ; Helper: append to log (with timestamp) ; ----------------------------- Func _Log($s) ConsoleWrite($s & @CRLF) Local $t = @HOUR & ":" & @MIN & ":" & @SEC Local $cur = GUICtrlRead($idLog) If $cur = "" Then GUICtrlSetData($idLog, "[" & $t & "] " & $s) Else GUICtrlSetData($idLog, $cur & @CRLF & "[" & $t & "] " & $s) EndIf ; move caret to end _GUICtrlEdit_LineScroll($idLog, 0, _GUICtrlEdit_GetLineCount($idLog)) EndFunc ;==>_Log Func FuncTest_1() _Log('+ TEST 1: Enumerate monitors -----------------------\') ; Enumerate monitors _Monitor_GetList() Local $cnt = _Monitor_GetCount() _Log("---> Example 1: Monitors detected: " & $cnt) For $i = 1 To $cnt Local $a = _Monitor_GetInfo($i) _Log(" Monitor " & $i & ": Device=" & $a[10] & " Bounds=(" & $a[1] & "," & $a[2] & ")-(" & $a[3] & "," & $a[4] & ") Work=(" & $a[5] & "," & $a[6] & ")-(" & $a[7] & "," & $a[8] & ") Primary=" & $a[9]) Next _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_1 Func FuncTest_2() _Log('+ TEST 2: Move Notepad to monitor #2 centered ------\') ; Move Notepad to monitor #2 centered $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then _Log("---> Example 2: Notepad did not start / focus") Else Sleep(1000) _Monitor_GetList() If _Monitor_GetCount() < 2 Then _Log("---> Example 2: Need at least 2 monitors") Else _Monitor_MoveWindowToScreen("[CLASS:Notepad]", "", 2, -1, -1, True) _Log("---> Example 2: Notepad moved to monitor #2 (centered)") EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_2 Func FuncTest_3() _Log('+ TEST 3: Move Notepad to monitor #2 at (100,100 ----\)') ; Move Notepad to monitor #2 at (100,100) $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then _Log("---> Example 3: Notepad did not start / focus") Else Sleep(1000) _Monitor_GetList() If _Monitor_GetCount() < 2 Then _Log("---> Example 3: Need at least 2 monitors") Else _Monitor_MoveWindowToScreen("[CLASS:Notepad]", "", 2, 100, 100, True) _Log("---> Example 3: Notepad moved to monitor #2 at (100,100)") EndIf EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_3 Func FuncTest_4() _Log('+ TEST 4: Which monitor is mouse on ------------------\') ; Which monitor is mouse on _Monitor_GetList() Local $m = _Monitor_GetFromPoint() _Log("---> Example 4: Mouse is on monitor #" & $m) MsgBox(64, "Example 4", "Mouse is on monitor #" & $m, 2) _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_4 Func FuncTest_5() _Log('+ TEST 5: Virtual desktop bounds -----------------------\') ; Virtual desktop bounds Local $aV = _Monitor_GetVirtualBounds() _Log("---> Example 5: Virtual bounds L=" & $aV[0] & " T=" & $aV[1] & " W=" & $aV[2] & " H=" & $aV[3]) MsgBox(64, "Example 6", "Virtual Desktop Bounds. See log.", 2) _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_5 Func FuncTest_6() _Log('+ TEST 6: Convert coords example (local -> virtual -> back) --\') ; Convert coords example (local -> virtual -> back) _Monitor_GetList() Local $mon = _Monitor_GetCount() If $mon < 1 Then _Log("---> Example 6: No monitors detected") Else For $i = 1 To $mon Local $xLocal = 50, $yLocal = 100 Local $aV = _Monitor_ToVirtual($i, $xLocal, $yLocal) Local $aBack = _Monitor_FromVirtual($i, $aV[0], $aV[1]) _Log("---> Example 6: Mon " & $i & " local(" & $xLocal & "," & $yLocal & ") -> virtual(" & $aV[0] & "," & $aV[1] & ") -> back(" & $aBack[0] & "," & $aBack[1] & ")") Next MsgBox(64, "Example 6", "Converted. See log.", 2) EndIf _Log('- End --------------------------------------------------------/') EndFunc ;==>FuncTest_6 Func FuncTest_7() _Log('+ TEST 7: Show detailed info via MsgBox (calls UDF) ------\') ; Show detailed info via MsgBox (calls UDF) _Monitor_GetList() _Monitor_ShowInfo(2) _Log("---> Example 7: _Monitor_ShowInfo() called") _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_7 Func FuncTest_8() _Log('+ TEST 8: Start notepad, check visible ---------------\') ; Start notepad, check visible $pidNotepad = Run("notepad.exe") If Not WinWaitActive("[CLASS:Notepad]", "", 5) Then _Log("---> Example 8: Notepad did not start/focus") Else Sleep(1000) Local $h = WinGetHandle("[CLASS:Notepad]") Local $b = _Monitor_IsVisibleWindow($h) _Log("---> Example 8: Notepad handle " & $h & " visible? " & ($b ? "Yes" : "No")) MsgBox(64, "Example 8", "Notepad visible? " & ($b ? "Yes" : "No"), 2) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_8 Func FuncTest_9() _Log('+ TEST 9: Create small GUI on each monitor -------------\') ; Create small GUI on each monitor _Monitor_GetList() ; close previously created For $i = 0 To UBound($g_createdGUIs) - 1 If IsHWnd($g_createdGUIs[$i]) Then GUIDelete($g_createdGUIs[$i]) Next ReDim $g_createdGUIs[1] ; reset Local $created = 0 For $i = 1 To _Monitor_GetCount() Local $a = _Monitor_GetInfo($i) Local $h = GUICreate("Monitor #" & $i & " - " & $a[10], 260, 120, $a[1] + 40, $a[2] + 40) GUICtrlCreateLabel("Monitor " & $i & ($a[9] ? " (Primary)" : ""), 10, 12, 240, 20) GUISetState(@SW_SHOW, $h) ; store to close later __ArrayAdd($g_createdGUIs, $h) $created += 1 Next _Log("---> Example 9: Created " & $created & " GUI(s) on monitors. Use Close to exit (they will be closed).") MsgBox(64, "Example 9", "Created " & $created & " GUIs (they will be closed when you close this launcher).", 2) _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_9 Func FuncTest_10() _Log('+ TEST 10: Move all visible windows to primary ----------\') ; Move all visible windows to primary _Monitor_GetList() Local $prim = _Monitor_GetPrimary() If $prim = 0 Then _Log("---> Example 10: Primary monitor not found") Else Local $aList = WinList() Local $moved = 0 For $i = 1 To $aList[0][0] If $aList[$i][0] <> "" Then Local $h = WinGetHandle($aList[$i][1]) If _Monitor_IsVisibleWindow($h) Then _Monitor_MoveWindowToScreen($h, "", $prim) $moved += 1 EndIf EndIf Next _Log("---> Example 10: Moved " & $moved & " visible windows to primary monitor #" & $prim) MsgBox(64, "Example 10", "Moved " & $moved & " visible windows to primary monitor #" & $prim, 2) EndIf _Log('- End ------------------------------------------------/') EndFunc ;==>FuncTest_10 ; ----------------------------- ; Small helper to push item into dynamic array (simple) ; ----------------------------- Func __ArrayAdd(ByRef $a, $v) Local $n = 0 If IsArray($a) Then $n = UBound($a) ReDim $a[$n + 1] $a[$n] = $v EndFunc ;==>__ArrayAdd Edited 14 hours ago by Trong fix code WildByDesign 1 Enjoy my work? Buy me a 🍻 or tip via ❤️ PayPal
WildByDesign Posted 43 minutes ago Posted 43 minutes ago 16 hours ago, Trong said: _Monitor_MoveWindowToAll In this function here, does it display the same GUI window identically on all monitors? Or does it split up the GUI window evenly so that different parts on the window are visible on each monitor?
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