Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Dual-Monitor Resolution Detection


  • Please log in to reply
5 replies to this topic

#1 Overkill

Overkill

    Wayfarer

  • Active Members
  • Pip
  • 72 posts

Posted 10 October 2008 - 10:40 AM

I'm writing an application to help me manage the window position of a game (World of Warcraft, for those interested). My current code is bulkier than I'd like, and uses a dead-reckoning system I'm not fond of. For example, if I want it on my second monitor taking up half the screen, placed in the top right corner, i have to do WinMove("World of Warcraft", "", 2080,0,640,512). I'd like to use WinMove("World of Warcraft","",$X1+$X2/2,0,$X2/2,$Y2/2) instead so that if I change my resolution or begin distributing the app, it's one less thing I have to worry about.

In my code, I need to find a way to replace "Unknown" with a variable that represents a numerical value.

I haven't yet added support for a vertical montior config, but if I can solidify this part of the code I'll expand it as needed, and I know where to come if I need help =)
Plain Text         
$FW = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 78)  $FH = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 79)  $XA = @DesktopWidth  $YA = @DesktopHeight  $WA = $FW[0]  $HA = $FH[0]    If $WA > $XA Then      $X1 = $XA      $X2 = $WA-$XA  ElseIf $WA = $XA Then      $X1 = $XA      $X2 = "Unknown"  EndIf    If $HA > $YA Then      $Y1 = $YA      $Y2 = $HA  ElseIf $HA = $YA Then      $Y1 = $YA      $Y2 = "Unknown"  EndIf        MsgBox(0,"","Monitor A: " & $X1 & " by " & $Y1 & @LF & "Monitor B: " & $X2 & " by " & $Y2)








#2 Monamo

Monamo

    Sushi

  • Active Members
  • PipPipPipPipPipPip
  • 476 posts

Posted 10 October 2008 - 01:16 PM

I'm writing an application to help me manage the window position of a game (World of Warcraft, for those interested). My current code is bulkier than I'd like, and uses a dead-reckoning system I'm not fond of. For example, if I want it on my second monitor taking up half the screen, placed in the top right corner, i have to do WinMove("World of Warcraft", "", 2080,0,640,512). I'd like to use WinMove("World of Warcraft","",$X1+$X2/2,0,$X2/2,$Y2/2) instead so that if I change my resolution or begin distributing the app, it's one less thing I have to worry about.

In my code, I need to find a way to replace "Unknown" with a variable that represents a numerical value.

I haven't yet added support for a vertical montior config, but if I can solidify this part of the code I'll expand it as needed, and I know where to come if I need help =)

Plain Text         
$FW = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 78)  $FH = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 79)  $XA = @DesktopWidth  $YA = @DesktopHeight  $WA = $FW[0]  $HA = $FH[0]    If $WA > $XA Then      $X1 = $XA      $X2 = $WA-$XA  ElseIf $WA = $XA Then      $X1 = $XA      $X2 = "Unknown"  EndIf    If $HA > $YA Then      $Y1 = $YA      $Y2 = $HA  ElseIf $HA = $YA Then      $Y1 = $YA      $Y2 = "Unknown"  EndIf        MsgBox(0,"","Monitor A: " & $X1 & " by " & $Y1 & @LF & "Monitor B: " & $X2 & " by " & $Y2)

Here's a WMI query that can give you the monitor number and its dimensions:
CODE
$strComputer = "."
$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")

$colItems = $objWMIService.ExecQuery("Select * from Win32_DesktopMonitor")
$sMsg = ""

For $objItem In $colItems
$sMsg &= "****************************" & @CRLF
$sMsg &= "Monitor: " & $objItem.DeviceID & @CRLF
$sMsg &= "****************************" & @CRLF
$sMsg &= "Description: " & $objItem.Description & @CRLF
$sMsg &= "Device ID: " & $objItem.DeviceID & @CRLF
$sMsg &= "Monitor Manufacturer: " & $objItem.MonitorManufacturer & @CRLF
$sMsg &= "Monitor Type: " & $objItem.MonitorType & @CRLF
$sMsg &= "Name: " & $objItem.Name & @CRLF
$sMsg &= "Screen Height: " & $objItem.ScreenHeight & @CRLF
$sMsg &= "Screen Width: " & $objItem.ScreenWidth & @CRLF
Next
ConsoleWrite($sMsg & @CRLF)

- MoChr(77)& Chr(97)& Chr(100)& Chr(101)& Chr(32)& Chr(121)& Chr(97)& Chr(32)& Chr(108)& Chr(111)& Chr(111)& Chr(107)-------I've told you 100,000 times not to exaggerate!-------Don't make me hit you with my cigarette hand...-------My scripts:Random Episode Selector, Keyboard MouseMover, CopyPath v2.1, SmartRename for XP,Window TracerNew!

#3 Overkill

Overkill

    Wayfarer

  • Active Members
  • Pip
  • 72 posts

Posted 10 October 2008 - 02:32 PM

Interesting...I'll have to do some digging to learn exactly how this works but for now it gets the job done. Here's how I adapted the code to fit my needs:
$strComputer = "." $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2") $colItems = $objWMIService.ExecQuery("Select * from Win32_DesktopMonitor") $i = 0 For $objItem In $colItems $i = $i + 1 Next Global $w[$i], $h[$i] $j = $i-1 $i = 0 For $objItem In $colItems $w[$i] = $objItem.ScreenWidth $h[$i] = $objItem.ScreenHeight $i = $i + 1 Next For $n = 0 to $j MsgBox(0,"",$w[$n] & "x" & $h[$n]) Next

I know there has to be a shorter way to make this work but I can't figure it out. Any ideas?

#4 LarryDalooza

LarryDalooza

    Schmember

  • Active Members
  • PipPipPipPipPipPip
  • 956 posts

Posted 10 October 2008 - 03:08 PM

Global Const $SM_VIRTUALWIDTH = 78
Global Const $SM_VIRTUALHEIGHT = 79
$VIRTUALDESKTOPWIDTH = DLLCall("user32.dll","int","GetSystemMetrics","int",$SM_VIRTUALWIDTH)
$VIRTUALDESKTOPWIDTH = $VIRTUALDESKTOPWIDTH[0]
$VIRTUALDESKTOPHEIGHT = DLLCall("user32.dll","int","GetSystemMetrics","int",$SM_VIRTUALHEIGHT)
$VIRTUALDESKTOPHEIGHT = $VIRTUALDESKTOPHEIGHT[0]
Posted ImageAutoIt3 Yahoo Group - Expert LarryA tool of Big Blue...

#5 Overkill

Overkill

    Wayfarer

  • Active Members
  • Pip
  • 72 posts

Posted 10 October 2008 - 03:20 PM

Global Const $SM_VIRTUALWIDTH = 78
Global Const $SM_VIRTUALHEIGHT = 79
$VIRTUALDESKTOPWIDTH = DLLCall("user32.dll","int","GetSystemMetrics","int",$SM_VIRTUALWIDTH)
$VIRTUALDESKTOPWIDTH = $VIRTUALDESKTOPWIDTH[0]
$VIRTUALDESKTOPHEIGHT = DLLCall("user32.dll","int","GetSystemMetrics","int",$SM_VIRTUALHEIGHT)
$VIRTUALDESKTOPHEIGHT = $VIRTUALDESKTOPHEIGHT[0]

As posted above:
$FW = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 78)  $FH = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 79)  $WA = $FW[0]  $HA = $FH[0]


This code retrieves the total size of the V-Desktop. I need the width/height of each monitor being used, so I used the concept from Monamo's code to write a working script (posted above), but the code seems a little bulkier than it needs to be. I was wondering if there was a cleaner way of writing it that uses a better grasp on the concept which I don't have at the moment. The end result should be close to or the same as it is right now, giving me an array of width/height values.

#6 xrxca

xrxca

    Seeker

  • Active Members
  • 9 posts

Posted 12 October 2008 - 07:01 PM

I use enumdisplaymonitors for this purpose, (I have a number of scripts to start apps on specific monitors, or on the monitor the mouse is on (from toolbars or other apps tool menus etc.))

here is the MultiMon.au3 I wrote and am currently using (could have a whole bunch more capability, but does what i need it to, the one thing I keep meaning to add is a custom MsgBox that I can place on a specific monitor)

It all seems to still work, (I just cleaned up the code a bit, added some minimal info above each function and renamed a bunch of variables ($t1, $t2, $h etc just doesn't cut it if someone else is looking at the code :P )
AutoIt         
#include-Once Global $__MonitorList[1][5] $__MonitorList[0][0] = 0 ; Just for testing _ShowMonitorInfo() ;================================================================================================== ; Function Name:   _ShowMonitorInfo() ; Description::    Show the info in $__MonitorList in a msgbox (line 0 is entire screen) ; Parameter(s):    n/a ; Return Value(s): n/a ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _ShowMonitorInfo()     If $__MonitorList[0][0] == 0 Then         _GetMonitors()     EndIf     Local $Msg = ""     Local $i = 0     For $i = 0 To $__MonitorList[0][0]         $Msg &= $i & " - L:" & $__MonitorList[$i][1] & ", T:" & $__MonitorList[$i][2]         $Msg &= ", R:" & $__MonitorList[$i][3] & ", B:" & $__MonitorList[$i][4]         If $i < $__MonitorList[0][0] Then $Msg &= @CRLF     Next     MsgBox(0, $__MonitorList[0][0] & " Monitors: ", $Msg) EndFunc   ;==>_ShowMonitorInfo ;================================================================================================== ; Function Name:   _MaxOnMonitor($Title[, $Text = ''[, $Monitor = -1]]) ; Description::    Maximize a window on a specific monitor (or the monitor the mouse is on) ; Parameter(s):    $Title   The title of the window to Move/Maximize ;     optional:    $Text    The text of the window to Move/Maximize ;     optional:    $Monitor The monitor to move to (1..NumMonitors) defaults to monitor mouse is on ; Note:            Should probably have specified return/error codes but haven't put them in yet ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _MaxOnMonitor($Title, $Text = '', $Monitor = -1)     _CenterOnMonitor($Title, $Text, $Monitor)     WinSetState($Title, $Text, @SW_MAXIMIZE) EndFunc   ;==>_MaxOnMonitor ;================================================================================================== ; Function Name:   _CenterOnMonitor($Title[, $Text = ''[, $Monitor = -1]]) ; Description::    Center a window on a specific monitor (or the monitor the mouse is on) ; Parameter(s):    $Title   The title of the window to Move/Maximize ;     optional:    $Text    The text of the window to Move/Maximize ;     optional:    $Monitor The monitor to move to (1..NumMonitors) defaults to monitor mouse is on ; Note:            Should probably have specified return/error codes but haven't put them in yet ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _CenterOnMonitor($Title, $Text = '', $Monitor = -1)     $hWindow = WinGetHandle($Title, $Text)     If Not @error Then         If $Monitor == -1 Then             $Monitor = _GetMonitorFromPoint()         ElseIf $__MonitorList[0][0] == 0 Then             _GetMonitors()         EndIf         If ($Monitor > 0) And ($Monitor <= $__MonitorList[0][0]) Then             ; Restore the window if necessary             Local $WinState = WinGetState($hWindow)             If BitAND($WinState, 16) Or BitAND($WinState, 32) Then                 WinSetState($hWindow, '', @SW_RESTORE)             EndIf             Local $WinSize = WinGetPos($hWindow)             Local $x = Int(($__MonitorList[$Monitor][3] - $__MonitorList[$Monitor][1] - $WinSize[2]) / 2) + $__MonitorList[$Monitor][1]             Local $y = Int(($__MonitorList[$Monitor][4] - $__MonitorList[$Monitor][2] - $WinSize[3]) / 2) + $__MonitorList[$Monitor][2]             WinMove($hWindow, '', $x, $y)         EndIf     EndIf EndFunc   ;==>_CenterOnMonitor ;================================================================================================== ; Function Name:   _GetMonitorFromPoint([$XorPoint = -654321[, $Y = 0]]) ; Description::    Get a monitor number from an x/y pos or the current mouse position ; Parameter(s): ;     optional:    $XorPoint X Position or Array with X/Y as items 0,1 (ie from MouseGetPos()) ;     optional:    $Y        Y Position ; Note:            Should probably have specified return/error codes but haven't put them in yet, ;                  and better checking should be done on passed variables. ;                  Used to use MonitorFromPoint DLL call, but it didn't seem to always work. ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _GetMonitorFromPoint($XorPoint = 0, $y = 0)     If @NumParams = 0 then         local $MousePos = MouseGetPos()         Local $myX = $MousePos[0]         Local $myY = $MousePos[1]     Elseif ( @NumParams = 1 ) and IsArray($XorPoint) Then         Local $myX = $XorPoint[0]         Local $myY = $XorPoint[1]     Else         Local $myX = $XorPoint         Local $myY = $y     EndIf     If $__MonitorList[0][0] == 0 Then         _GetMonitors()     EndIf     Local $i = 0     Local $Monitor = 0     For $i = 1 To $__MonitorList[0][0]         If ($myX >= $__MonitorList[$i][1]) _                 And ($myX < $__MonitorList[$i][3]) _                 And ($myY >= $__MonitorList[$i][2]) _                 And ($myY < $__MonitorList[$i][4]) Then $Monitor = $i     Next     Return $Monitor EndFunc   ;==>_GetMonitorFromPoint ;================================================================================================== ; Function Name:   _GetMonitors() ; Description::    Load monitor positions ; Parameter(s):    n/a ; Return Value(s): 2D Array of Monitors ;                       [0][0] = Number of Monitors ;                       [i][0] = HMONITOR handle of this monitor. ;                       [i][1] = Left Position of Monitor ;                       [i][2] = Top Position of Monitor ;                       [i][3] = Right Position of Monitor ;                       [i][4] = Bottom Position of Monitor ; Note:            [0][1..4] are set to Left,Top,Right,Bottom of entire screen ;                  hMonitor is returned in [i][0], but no longer used by these routines. ;                  Also sets $__MonitorList global variable (for other subs to use) ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _GetMonitors()     $__MonitorList[0][0] = 0  ;  Added so that the global array is reset if this is called multiple times     Local $handle = DllCallbackRegister("_MonitorEnumProc", "int", "hwnd;hwnd;ptr;lparam")     DllCall("user32.dll", "int", "EnumDisplayMonitors", "hwnd", 0, "ptr", 0, "ptr", DllCallbackGetPtr($handle), "lparam", 0)     DllCallbackFree($handle)     Local $i = 0     For $i = 1 To $__MonitorList[0][0]         If $__MonitorList[$i][1] < $__MonitorList[0][1] Then $__MonitorList[0][1] = $__MonitorList[$i][1]         If $__MonitorList[$i][2] < $__MonitorList[0][2] Then $__MonitorList[0][2] = $__MonitorList[$i][2]         If $__MonitorList[$i][3] > $__MonitorList[0][3] Then $__MonitorList[0][3] = $__MonitorList[$i][3]         If $__MonitorList[$i][4] > $__MonitorList[0][4] Then $__MonitorList[0][4] = $__MonitorList[$i][4]     Next     Return $__MonitorList EndFunc   ;==>_GetMonitors ;================================================================================================== ; Function Name:   _MonitorEnumProc($hMonitor, $hDC, $lRect, $lParam) ; Description::    Enum Callback Function for EnumDisplayMonitors in _GetMonitors ; Author(s):       xrxca (autoit@forums.xrx.ca) ;================================================================================================== Func _MonitorEnumProc($hMonitor, $hDC, $lRect, $lParam)     Local $Rect = DllStructCreate("int left;int top;int right;int bottom", $lRect)     $__MonitorList[0][0] += 1     ReDim $__MonitorList[$__MonitorList[0][0] + 1][5]     $__MonitorList[$__MonitorList[0][0]][0] = $hMonitor     $__MonitorList[$__MonitorList[0][0]][1] = DllStructGetData($Rect, "left")     $__MonitorList[$__MonitorList[0][0]][2] = DllStructGetData($Rect, "top")     $__MonitorList[$__MonitorList[0][0]][3] = DllStructGetData($Rect, "right")     $__MonitorList[$__MonitorList[0][0]][4] = DllStructGetData($Rect, "bottom")     Return 1 ; Return 1 to continue enumeration EndFunc   ;==>_MonitorEnumProc

Edited Jan 8, 2009 to correct minor bug in _GetMonitors routine (Pointed out by Cusem).

Edited by xrxca, 08 January 2009 - 04:26 PM.

  • alshamma likes this
By far, the worst four letter word (swear word) out there has to be USER




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users