如何通过一次击键自动在显示器之间移动窗口?

如何通过一次击键自动在显示器之间移动窗口?

在 Windows 中,我有这个很棒的小应用程序,它允许我通过单击按钮(或按键)在两个显示器之间移动应用程序窗口。

我知道有一个应用程序可以改变显示器内窗口的位置,但不能改变显示器之间窗口的位置。

你知道是否确实存在这样的应用程序吗?

答案1

我使用以下 AppleScript 来执行您要求的操作;虽然它目前假设屏幕大小相同且并排放置,但对于其他情况,应该相对容易更改。有许多技术可以使用按键命令运行 AppleScript;就我个人而言,我使用巴特勒

tell application "Finder"
    set _bounds to bounds of window of desktop
    set _width to item 3 of _bounds
end tell

set left_width to _width / 2

tell application "System Events"
    tell (first process whose frontmost is true)
        tell first window
            set {x, y} to (get position)
            if x < left_width then
                set position to {x + left_width, y}
            else
                set position to {x - left_width, y}
            end if
        end tell
    end tell
end tell

答案2

快速搜索确实找到了几个包含您所需功能的应用程序 - 但似乎都不是免费的。它们确实有试用版。如果我找到免费的,我会通知您。

尺寸最优布局窗口移动器。SizeUp 似乎是三者中最好的,因为它和 Cinch 是由同一家制造商生产的,而且看起来最轻。

答案3

对于 Linux,我仍在寻找解决方案。

UltraMon 是一个共享软件,可以很好地解决 Windows 的问题。

以下脚本可以在Apple Mac OS X上使用。可以使用Quicksilver创建快捷方式

--  Window Moving Script between multiple monitors for Apple Mac OS X 10.x
-- (something I've been doing with UltraMon for quite a while)
--  inspired by:
--     http://www.tidbits.com/webx?14@@.3c7b1ae3/5
--     http://macscripter.net/viewtopic.php?id=24511
-- and http://daringfireball.net/2006/12/display_size_applescript_the_lazy_way
-- thanx for the input ... I was looking for a solution of this quite a while
-- best to be used with a custom trigger in Quicksilver where this script is assigned to a
-- keyboard short cut (I use ALT Cursor-Right) 
-- you might want to put Quicksilver into your Autostart Objects
-- 2009-09-14 Wolfgang Fahl

--
-- get the front Window
-- 
on getFrontWindow1()
    tell application "System Events"
        set theFrontWindow to first window of (first process whose frontmost is true)
        -- set theFrontWindow to the front window
        set windowname to name of theFrontWindow as string
        say "Moving" & windowname
        --display dialog "front most windows is " & name of  theFrontWindow buttons ("Cool") giving up after 3 default button 1
        return theFrontWindow
    end tell
end getFrontWindow1
--
-- get the front Window
-- 
on getFrontWindow()
    tell application "System Events"
        repeat with theapp in (every application process whose visible is true and frontmost is true)
            repeat with ew in (every window of theapp)
                return ew
            end repeat
        end repeat
    end tell
end getFrontWindow
--
-- list all windows
--
on listWindows()
    tell application "System Events"
        repeat with theapp in (every application process whose visible is true and frontmost is true)
            repeat with ew in (every window of theapp)
                set windowname to name of ew as string
                say windowname
            end repeat
        end repeat
    end tell
end listWindows

--
-- message dialog
--
on show(aMessage)
    -- display a dialog with a message
    display dialog aMessage buttons {"Ok"} default button "Ok"
end show

--
-- get the screen information
--
on getScreenInfo(theIndex)
    -- get the Screen Information from the windowserver defaults
    -- we are using awk to go to the DisplaySets sections and assume that Active = ... is
    -- at the start of each section
    -- we'll find OriginX= ...,OriginY= ..., Width = ... and Height= ... entries
    -- and return all of them a a list like
    -- 0 0     1920 1200
    -- 0 1920  1650 1050
    set screenInfo to do shell script "defaults read /Library/Preferences/com.apple.windowserver | awk '
        BEGIN { FS=\"=\" }
        /Active/  { screens++ }
        { gsub(\";\",\"\",$2) }
        /^ *OriginX/ { ox[screens] = $2 }
        /^ *OriginY/ { oy[screens] = $2 }
        /^ *Width/   { w[screens]  = $2 }
        /^ *Height/  { h[screens]  = $2 }
        END       {
                for (si=1;si<=screens;si++) {
                    print ox[si],oy[si],w[si],h[si]
                    }
            }'"
    set theInfo to paragraph theIndex of screenInfo
    return {word 1 of theInfo, word 2 of theInfo, word 3 of theInfo, word 4 of theInfo}
end getScreenInfo

--
-- move the front window to another monitor
--
tell application "System Events"
    -- get the OffsetX,OffsetY,Width and Height information for the screens
    -- here we assume that two screens are present (without checking this ...)
    -- first screen info
    set theScreen1 to getScreenInfo(1) of me

    -- second screen info
    set theScreen2 to getScreenInfo(2) of me

    -- for the functionality of this script we are happy with the resolution info for the time being
    set startX to item 1 of theScreen1
    set startY to item 2 of theScreen1
    set resolutionX to item 3 of theScreen1
    set resolutionY to item 4 of theScreen1

    set startX2 to item 1 of theScreen2
    set startY2 to item 2 of theScreen2
    set resolutionX2 to item 3 of theScreen2
    set resolutionY2 to item 4 of theScreen2

    -- make some nois to let everybody know we have receive the command
    beep

    -- 1st, determine current X & Y Positions of the current front window
    set theWindow to getFrontWindow() of me
    set thePosition to position of theWindow

    -- uncomment this if you'd like to debug
    -- display alert name of theWindow & ": " & ((first item of thePosition) as string) & ", " & ((second item of thePosition) as string) & " screen1:" & (startX as string) & "," & (startY as string) & "-" & (resolutionX as string) & "," & (resolutionY as string) & " screen2:" & (startX2 as string) & "," & (startY2 as string) & "-" & (resolutionX2 as string) & "," & (resolutionY2 as string)
    set currXPos to (first item of thePosition)
    set currYPos to (second item of thePosition)

    -- are we on the first monitor?
    if currXPos < resolutionX / 2 then
        -- move right
        set newX to currXPos + resolutionX
        set newY to currYPos - startY2
    else
        -- move left
        set newX to currXPos - resolutionX
        if newX < startX then
            set newX to startX
        end if
        set newY to currYPos + startY2
    end if
    -- Now we move the window moveX pixels to the right (or left if negative)
    set position of theWindow to {(newX), (newY)}
end tell

答案4

这是我的 applescript 解决方案,它应该保持位置并按比例缩放窗口大小:

# http://superuser.com/questions/331313/how-to-automagically-move-windows-between-monitors-with-one-keystroke
# https://stackoverflow.com/questions/6565703/math-algorithm-fit-image-to-screen-retain-aspect-ratio
# https://forum.latenightsw.com/t/get-sizes-of-monitor-s-via-applescript/1351/10

---
use framework "Foundation"
use framework "AppKit"
use scripting additions

set allFrames to (current application's NSScreen's screens()'s valueForKey:"frame") as list
try
    set _mon1 to item 2 of item 1 of allFrames
    set _mon2 to item 2 of item 2 of allFrames
    
    set _mon1Width to item 1 of _mon1
    set _mon1Hight to item 2 of _mon1
    set _mon1Size to _mon1Width + _mon1Hight
    
    
    set _mon2Width to item 1 of _mon2
    set _mon2Hight to item 2 of _mon2
    set _mon2Size to _mon2Width + _mon2Hight
    
    set _screenWar to (_mon2Width / _mon1Width) # width adaption ratio of screen 1 & 2
    set _screenHar to (_mon2Hight / _mon1Hight) #  hight adaption ratio of screen 1 & 2 
    
    tell current application to set _hightoffset to do shell script "/usr/libexec/PlistBuddy -c 'Print :DisplayAnyUserSets:Configs:0:0:CurrentInfo:OriginY ' /Library/Preferences/com.apple.windowserver.displays.plist"
    set _hightoffset to _hightoffset as feet as number
    
    tell current application to set _widthoffset to do shell script "/usr/libexec/PlistBuddy -c 'Print :DisplayAnyUserSets:Configs:0:0:CurrentInfo:OriginX ' /Library/Preferences/com.apple.windowserver.displays.plist"
    set _widthoffset to _widthoffset as feet as number
    
    # detect position of the second screen in relation to the main screen
    if _mon1Width = _widthoffset then
        # say "Rechts"
        set _right to true
    else if _mon1Hight = _hightoffset then
        set _right to false
        set _bottom to true
    else if _mon2Width = -_widthoffset then
        set _right to false
        set _bottom to false
        set _left to true
    else if _mon2Hight = -_hightoffset then
        set _right to false
        set _bottom to false
        set _left to false
        set _top to true
    end if
end try

try
    tell application "System Events"
        tell (first process whose frontmost is true)
            set _windowPos to position of window 1
            set x to item 1 of _windowPos # x = position width 
            set y to item 2 of _windowPos # y = position hight 
            
            set _windowSize to size of window 1
            set _windowWidth to (item 1 of _windowSize)
            set _windowHight to (item 2 of _windowSize)
            
            
            # set current location (which monitor) of the frontmost window and new window size and postion 
            if _right is true then
                if x < _mon1Width then
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)} # menubar = 25 pixel
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
                
            else if _bottom is true then
                if y < _mon1Hight then
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)}
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
            else if _left is true then
                if x > -1 then
                    set _newSize to {_windowWidth * _screenWar, _windowHight * _screenHar}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + (_hightoffset + 25)}
                    set _winLocation to "mon1"
                else
                    set _newPosition to {(x - _widthoffset) / _screenWar, ((y - (_hightoffset + 25)) / _screenHar) + 25}
                    set _newSize to {_windowWidth / _screenWar, _windowHight / _screenHar}
                    set _winLocation to "mon2"
                end if
            else if _top is true then
                if y < 25 then
                    set _newPosition to {(x - _widthoffset) / _screenWar, (y + (-_hightoffset - 25)) / _screenHar + 25}
                    set _newSize to {_windowWidth / _screenWar, (_windowHight + 25) / _screenHar - 25}
                    set _winLocation to "mon2"
                else
                    set _newSize to {_windowWidth * _screenWar, (_windowHight + 25) * _screenHar - 25}
                    set _newPosition to {(x * _screenWar) + _widthoffset, ((y - 25) * _screenHar) + _hightoffset + 25}
                    set _winLocation to "mon1"
                end if
            end if
            
            # checking for window loaction and whether the monitor it is located on is bigger or smaller than the other one 
            if _winLocation is "mon1" then
                if _mon1Size > _mon2Size then
                    set size of window 1 to _newSize
                    set position of window 1 to _newPosition
                else
                    set position of window 1 to _newPosition
                    set size of window 1 to _newSize
                end if
                
            else
                if _mon2Size > _mon1Size then
                    set size of window 1 to _newSize
                    set position of window 1 to _newPosition
                else
                    set position of window 1 to _newPosition
                    set size of window 1 to _newSize
                end if
            end if
            
        end tell
    end tell
end try

它只有几行代码,但只要您使用的显示器不超过两个,它应该适用于几乎所有设置。您可以在我的 GitHub 上找到它以及许多其他很好地打包到 LaunchBar 操作中的窗口脚本https://github.com/Ptujec/LaunchBar/tree/master/Window%20Actions

相关内容