AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

WindowPad - multi-monitor window-moving tool
Goto page Previous  1, 2, 3 ... 7, 8, 9 ... 20, 21, 22  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Rhetticus



Joined: 12 Jul 2008
Posts: 1
Location: Australia

PostPosted: Sat Jul 12, 2008 3:43 pm    Post subject: Reply with quote

I have created new taskbar icons for use with this program and thought that I should share it with you.

Preview of new tray icon (left-most icon):

Download here:
http://www.esnips.com/doc/72257248-9218-41a3-95dd-ece3d51eed28/tray3

Preview of new disabled icon(left-most icon):

Download here:
http://www.esnips.com/doc/e3a242e7-2292-494e-8ffd-3385ff77714c/disabled2

As for installation simply place the new icons into the "icons" folder where "WindowPad" is kept. Then in the "WindowPad.ahk" script replace the line:
icon := is_enabled ? "tray.ico" : "disabled.ico"
With:
icon := is_enabled ? "tray3.ico" : "disabled2.ico"
Back to top
View user's profile Send private message
Max99



Joined: 10 Jul 2008
Posts: 3

PostPosted: Sat Jul 12, 2008 8:46 pm    Post subject: Reply with quote

Lexikos wrote:
...which functions did you try? WindowPad originally used Win+Numpad, but the latest version uses Numpad0/NumpadDot+Numpad or Capslock+q/w/e/a/s/d/z/x/c. If I download the latest version and extract it somewhere, it Just Works.


Problem solved as I must somehow have missed the fact that the Windows key is no longer the operator key. Now all working fine and exactly what I need (and more) to replace the buggy nView software. Will also definitely now try to use AutoHotkey for other applications.

Many thanks for help and for a great little utility.
Back to top
View user's profile Send private message
HelgeFin



Joined: 04 Apr 2007
Posts: 12

PostPosted: Fri Aug 29, 2008 7:15 pm    Post subject: Reply with quote

I used WindowPad for some time, thanks a lot, but now I found something with the same functionality and much more good stuff:

SplitMon
http://www.autoitscript.com/forum/index.php?showtopic=39050
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Sat Aug 30, 2008 2:12 am    Post subject: Reply with quote

Thanks for posting, HelgeFin. Here are my biased findings after a quick try:
  • Redirect maximize is an interesting idea, but not so useful in practice if you must click the maximize button. It is too small to be efficient - I use a mouse gesture instead.
  • The WinMove features do not seem applicable to single-monitor set-ups, or they simply don't work on my system.
  • WinMem might be useful to some, but I probably wouldn't use it.
  • WinResize (multi-window resizer) is excellent. Smile ezuk requested similar hotkey-based functionality a while back, but I never got around to implementing it.
Interestingly, the GUI paints very slowly when Aero is enabled (on Vista). This does not happen with AutoHotkey GUIs.
Back to top
View user's profile Send private message Visit poster's website
HelgeFin



Joined: 04 Apr 2007
Posts: 12

PostPosted: Sat Aug 30, 2008 12:16 pm    Post subject: Reply with quote

You are right,

Lexikos wrote:
WinResize (multi-window resizer) is excellent. Smile


It is the killer feature. That alone makes it worth having that program running.
Back to top
View user's profile Send private message
deepfriedcheese



Joined: 04 Jul 2008
Posts: 8

PostPosted: Wed Sep 03, 2008 12:58 pm    Post subject: WinMove in Windowpad Reply with quote

I monkeyed with the windowpad code to get something like the WinMove feature in splitmon some time ago. I use a five monitor setup in my office and a two or three monitor system at client's offices. The software for the nVidia card in my docking station included this function, but I wanted it while in the field without the dock.

I inserted the following lines in the code:
Code:
Prefix_Alternate  = #^  ; Ctrl+Win+Numpad = Move window directly to a monitor

Defined at the same time as the other prefixes.

Code:
Hotkey, %Prefix_Alternate%Numpad%A_Index%, DoMoveWindowToMonitor

In the loop registering hotkeys.

Code:
;
; Move window directly to monitor number selected without resizing (relative to screen).
;

DoMoveWindowToMonitor:
    gosub WP_SetLastFoundWindowByHotkey
    WinGet, state, MinMax
    if state = 1
    {   ; Maximized windows don't move correctly on XP
        ; (and possibly other versions of Windows)
        WinRestore
        DoMoveWindowToMonitor()
        WinMaximize
    }
    else
        DoMoveWindowToMonitor()
return

DoMoveWindowToMonitor()
{
    WinGetPos, x, y, w, h

    ; Determine which monitor contains the center of the window.
    ms := GetMonitorAt(x+w/2, y+h/2)
   
    ; Determine which monitor to move to.
    StringRight, md, A_ThisHotkey, 1
    SysGet, mon, MonitorCount
    ; This may happen if someone tries to move to a monitor number that does not exist.
    if (md > mon)
        return
   
    ; This may happen if someone tries it with only one screen. :P
    if (md = ms)
        return

    ; Get source and destination work areas (excludes taskbar-reserved space.)
    SysGet, ms, MonitorWorkArea, %ms%
    SysGet, md, MonitorWorkArea, %md%
    msw := msRight - msLeft, msh := msBottom - msTop
    mdw := mdRight - mdLeft, mdh := mdBottom - mdTop
   
    ; Calculate new size.
    if (IsResizable()) {
        w *= (mdw/msw)
        h *= (mdh/msh)
    }
    SetWinDelay, -1
    ; Move window, using resolution difference to scale co-ordinates.
    WinMove,,, mdLeft + (x-msLeft)*(mdw/msw), mdTop + (y-msTop)*(mdh/msh), w, h
}

This is the routine that actually moves the window.

I also wanted to be able to move either direction with NumpadDot so I added this.

Code:
Hotkey, %Prefix_Alternate%NumpadDot, MoveWindowBackOneScreen

So I could easily move forward and back one screen using NumpadDot.

Code:
MoveWindowBackOneScreen:
    gosub WP_SetLastFoundWindowByHotkey
    WinGet, state, MinMax
    if state = 1
    {   ; Maximized windows don't move correctly on XP
        ; (and possibly other versions of Windows)
        WinRestore
        MoveWindowBackOneScreen()
        WinMaximize
    }
    else
        MoveWindowBackOneScreen()
return

MoveWindowBackOneScreen()
{
    WinGetPos, x, y, w, h
   
    ; Determine which monitor contains the center of the window.
    ms := GetMonitorAt(x+w/2, y+h/2)
   
    ; Determine which monitor to move to.
    md := ms-1
    SysGet, mon, MonitorCount
    if (md < 1)
        md := mon
   
    ; This may happen if someone tries it with only one screen. :P
    if (md = ms)
        return

    ; Get source and destination work areas (excludes taskbar-reserved space.)
    SysGet, ms, MonitorWorkArea, %ms%
    SysGet, md, MonitorWorkArea, %md%
    msw := msRight - msLeft, msh := msBottom - msTop
    mdw := mdRight - mdLeft, mdh := mdBottom - mdTop
   
    ; Calculate new size.
    if (IsResizable()) {
        w *= (mdw/msw)
        h *= (mdh/msh)
    }
    SetWinDelay, -1
    ; Move window, using resolution difference to scale co-ordinates.
    WinMove,,, mdLeft + (x-msLeft)*(mdw/msw), mdTop + (y-msTop)*(mdh/msh), w, h
}

This is a barely modified version of the MoveWindowToNextScreen to move it back instead.

I looked at the splitmon page, but I didn't try it out. I don't get what the WinResize actually does.

Lexikos, I hope you don't mind me posting the changes I've made. Windowpad is a great program that adds a big dose of efficiency to my days.
Back to top
View user's profile Send private message
mpareja
Guest





PostPosted: Fri Sep 26, 2008 4:05 am    Post subject: Oh no! Google Chrome doesn't resize! Reply with quote

I don't know if you have tried Google Chrome yet, but WindowPad's resizing isn't working!

I may have to ditch Chrome simply because I like WindowPad so much.
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Fri Sep 26, 2008 9:10 am    Post subject: Reply with quote

I switched to Chrome shortly after it came out, and have not yet had any issues with WindowPad. I'm running Windows Vista, if it matters.
Back to top
View user's profile Send private message Visit poster's website
eddo
Guest





PostPosted: Fri Sep 26, 2008 3:20 pm    Post subject: Reply with quote

Thanks for providing this awesome utility.

I have a question, when I'm using the WindowPadMove command to move to the center of the screen as follows:

*Numpad5 = WindowPadMove, 0, 0, 0.75, 0.75

Once the window is in place, and if I hit the command again odd things happen in a pattern:
- if on the primary monitor it moves it up a bit
- then it jumps to the secondary monitor
- then when on the secondary monitor, it jumps back to the primary...

And it cycles...

Any idea why this is happening?

Thanks. BTW, this is a fantastic tool. One suggestion would be to allow us to specify any grid of locations on the screen, so to say I could cut my screen into a 2 row x 3 columns and arrow my way around..

Also, one different thing I had to get used to is the way there is a master hotkey which enables the subhotkeys (chord?). It's good, but take a bit of getting used to, as it makes it a bit difficult to merge some of my other hotkeys key with this one. For example, I used to use my windows key + arrows for all my window management movements. But I also used it as my starting apps hotkey. If it's used as a master hotkey to get into the WindowPad script it might mean I cannot use it as a hotkey for apps?

Anyway, great stuff. Thanks again!
Back to top
mpareja
Guest





PostPosted: Fri Sep 26, 2008 6:49 pm    Post subject: Google Chrome Reply with quote

Maybe it is because I am on XP?

I have WindowPad on 3 different XP machines with Google Chrome and they all have problems resizing. The window switches into "Restore" mode (out of maximize mode) and it moves to the appropriate location but it does not resize.

I diff'ed my windowpad.ahk with your latest version and it is the same.
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Sat Sep 27, 2008 1:12 am    Post subject: Reply with quote

eddo wrote:
- if on the primary monitor it moves it up a bit
I can't explain this. It doesn't happen on my system, with only one monitor. Unfortunately I don't have a second monitor to test with.
Quote:
- then it jumps to the secondary monitor
- then when on the secondary monitor, it jumps back to the primary...
This is exactly what it is supposed to do. If the window is already in position, rather than do nothing, the hotkey cycles between screens.
Quote:
If it's used as a master hotkey to get into the WindowPad script it might mean I cannot use it as a hotkey for apps?
You don't have to use the default scheme. Try moving the hotkeys from the [Hotkeys: ...] sections into [Hotkeys], and prepending the desired modifiers (i.e. #) to the key names.
mpareja wrote:
Maybe it is because I am on XP?
If Chrome is running on Vista with Aero/desktop composition enabled, it uses the Chrome_VistaFrame window class. This has the WS_SIZEBOX style, whereas Chrome_XPFrame does not. I suppose this is done because a custom window frame is not required if Aero is present. You may either disable IsResizable() or add an exception:
Code:
IsResizable()
{
    WinGetClass, Class
    if Class = Chrome_XPFrame
        return true
    WinGet, Style, Style
    return (Style & 0x40000) ; WS_SIZEBOX
}
Back to top
View user's profile Send private message Visit poster's website
mpareja
Guest





PostPosted: Sat Sep 27, 2008 5:43 am    Post subject: Google Chrome on XP now resizes. Reply with quote

Lexikos wrote:
If Chrome is running on Vista with Aero/desktop composition enabled, it uses the Chrome_VistaFrame window class. This has the WS_SIZEBOX style, whereas Chrome_XPFrame does not. I suppose this is done because a custom window frame is not required if Aero is present. You may either disable IsResizable() or add an exception:
Code:
IsResizable()
{
    WinGetClass, Class
    if Class = Chrome_XPFrame
        return true
    WinGet, Style, Style
    return (Style & 0x40000) ; WS_SIZEBOX
}


Well done Lexikos! This solved the problem.

Perhaps you should add it to the default script?
Back to top
mattb



Joined: 31 Oct 2008
Posts: 1
Location: Melbourne, Australia

PostPosted: Fri Oct 31, 2008 2:30 am    Post subject: Reply with quote

I have made a few modifications to the 1.53 script.

The script detects when an MDI application is being moved to another screen, and it rescales the child windows appropriately. This works for most MDI apps, but not all (eg: Excel).

The second mod creates a right-click context window that is displayed when a user right-clicks in the title bar for >0.2 seconds.
This could be improved by reading the definitions in the WindowPad.ini file.


Code:

; WindowPad v1.53
;
; Credits:
;   Concept based on HiRes Screen Splitter by JOnGliko.
;   Written from scratch by Lexikos to support multiple monitors.
;   NumpadDot key functionality suggested by bobbo.
;
; Built with AutoHotkey v1.0.47
;

WindowPadInit:  ; for backwards-compatibility. :)
    WindowPad_Init(WINDOWPAD_INI_PATH)
return

WindowPad_Init(IniPath="")
{
    global WINDOWPAD_INI_PATH
;     if A_IsCompiled  ; Load icons from my custom WindowPad.exe.
;     {
;         ; Default icon is 32x32, so doesn't look good in the tray.
;         Menu, TRAY, Icon, %A_ScriptFullPath%, 11
;     }
;     else
    if (A_LineFile = A_ScriptFullPath)
    {   ; Set the tray icon, but only if not included in some other script.
        WindowPad_SetTrayIcon(true)
        ; Use OnMessage to catch "Suspend Hotkeys" or "Pause Script"
        ; so the "disabled" icon can be used.
        OnMessage(0x111, "WM_COMMAND")
    }
   
    if IniPath =
        IniPath = %A_ScriptDir%\WindowPad.ini
    WINDOWPAD_INI_PATH := IniPath
    WindowPad_LoadSettings(IniPath)
   
    Menu, ContextMenu, add
    Menu, ContextMenu, DeleteAll
    Menu, ContextMenu, add, Swap Monitor, WindowScreenMove, Next
    Menu, ContextMenu, add, Maximise/Restore, MaximizeToggle
    Menu, ContextMenu, add,
    Menu, ContextMenu, add, Move Left, CM_MoveLeft
    Menu, ContextMenu, add, Move Right, CM_MoveRight
    Menu, ContextMenu, add, Move Up, CM_MoveUp
    Menu, ContextMenu, add, Move Right , CM_MoveDown
    Menu, ContextMenu, add,
    Menu, ContextMenu, add, Move Up+Left, CM_MoveLeftUp
    Menu, ContextMenu, add, Move Up+Right, CM_MoveRightUp
    Menu, ContextMenu, add, Move Middle, CM_MoveMiddle
    Menu, ContextMenu, add, Move Down+Left, CM_MoveLeftDown
    Menu, ContextMenu, add, Move Down+Right, CM_MoveRightDown
   
   
}



WindowPad_LoadSettings(ininame)
{
    local v
   
    ; Misc Options
    IniRead, v, %ininame%, Options, TitleMatchMode, %A_TitleMatchMode%
    SetTitleMatchMode, %v%
   
    ; Hotkeys: Exclude Windows
    v := WindowPad_INI_GetList(ininame, "Exclude Windows", "Window")
    Loop, Parse, v, `n
        GroupAdd, HotkeyExclude, %A_LoopField%
   
    ; Read the Hotkeys section in.
    v := WindowPad_INI_ReadSection(ininame, "Hotkeys")
    ; Replace the first = with ::.
    ; ('=' is required for WritePrivateProfileSection to work properly.)
    v := RegExReplace(v, "m`a)^(.*?)=", "$1::")
    Hotkey, IfWinNotActive, ahk_group HotkeyExclude
    Hotkey_Params(v)
   
    ; Gather: Exclude Windows
    v := WindowPad_INI_GetList(ininame, "Gather: Exclude Windows", "Window")
    Loop, Parse, v, `n
        GroupAdd, GatherExclude, %A_LoopField%

    ; Gather: Exclude Processes
    ProcessGatherExcludeList := WindowPad_INI_GetList(ininame
        , "Gather: Exclude Processes", "Process", ",")
}

WindowPad_INI_GetList(ininame, Section, Key, Delim="`n")
{
    v := WindowPad_INI_ReadSection(ininame, Section)
    Loop, Parse, v, `n
    {
        pos := InStr(A_LoopField, "=")
        if (pos && SubStr(A_LoopField,1,pos-1) = Key)
            list .= (list ? Delim : "") . SubStr(A_LoopField, pos+1)
    }
    return list
}

WindowPad_INI_ReadSection(Filename, Section)
{
    ; Expand relative paths, since GetPrivateProfileSection only searches %A_WinDir%.
    Loop, %Filename%, 0
        Filename := A_LoopFileLongPath
   
    VarSetCapacity(text, 0x7FFF, 0)

    len := DllCall("GetPrivateProfileSection"
        , "str", Section, "str", text, "uint", 0x7FFF, "str", Filename)
   
    ; Each line within the section is terminated with a null character.
    ; Replace each delimiting null char with a newline:
    Loop, % len-1
        if (NumGet(text, A_Index-1, "UChar") = 0)
            NumPut(10, text, A_Index-1, "UChar")  ; \0 -> \n

    ; Windows Me/98/95:
    ;   The returned string includes comments.
    ;
    ; This removes comments. Also, I'm not sure if leading/trailing space is
    ; automatically removed on Win9x, so the regex removes that too.
    if A_OSVersion in WIN_ME,WIN_98,WIN_95
        text := RegExReplace(text, "m`n)^[ `t]*(?:;.*`n?|`n)|^[ `t]+|[ `t]+$")
   
    return text
}


WindowPadMove(P)
{
    StringSplit, P, P, `,, %A_Space%%A_Tab%
    ; Params: 1:dirX, 2:dirY, 3:widthFactor, 4:heightFactor, 5:window

    ; dirX and dirY are required.   
    if P1 is not number
        return
    if P2 is not number
        return
   
    WindowPad_WinExist(P5)

    if !WinExist()
        return

    ; Determine width/height factors.
    if (P1 or P2) {     ; to a side
        widthFactor  := P3+0 ? P3 : (P1 ? 0.5 : 1.0)
        heightFactor := P4+0 ? P4 : (P2 ? 0.5 : 1.0)
    } else {            ; to center
        widthFactor  := P3+0 ? P3 : 1.0
        heightFactor := P4+0 ? P4 : 1.0
    }
   
    ; Move the window!
    MoveWindowInDirection(P1, P2, widthFactor, heightFactor)
}
return

MaximizeToggle(P)
{
    WindowPad_WinExist(P)
   
    WinGet, state, MinMax
    if state
        WinRestore
    else
        WinMaximize
}

; Does the grunt work of the script.
MoveWindowInDirection(sideX, sideY, widthFactor, heightFactor)
{
    WinGetPos, x, y, w, h
   
    ; Determine which monitor contains the center of the window.
    m := GetMonitorAt(x+w/2, y+h/2)
   
    ; Get work area of active monitor.
    gosub CalcMonitorStats
    ; Calculate possible new position for window.
    gosub CalcNewPosition

    ; If the window is already there,
    if (newx "," newy "," neww "," newh) = (x "," y "," w "," h)
    {   ; ..move to the next monitor along instead.
   
        if (sideX or sideY)
        {   ; Move in the direction of sideX or sideY.
            SysGet, monB, Monitor, %m% ; get bounds of entire monitor (vs. work area)
            x := (sideX=0) ? (x+w/2) : (sideX>0 ? monBRight : monBLeft) + sideX
            y := (sideY=0) ? (y+h/2) : (sideY>0 ? monBBottom : monBTop) + sideY
            newm := GetMonitorAt(x, y, m)
        }
        else
        {   ; Move to center (Numpad5)
            newm := m+1
            SysGet, mon, MonitorCount
            if (newm > mon)
                newm := 1
        }
   
        if (newm != m)
        {   m := newm
            ; Move to opposite side of monitor (left of a monitor is another monitor's right edge)
            sideX *= -1
            sideY *= -1
            ; Get new monitor's work area.
            gosub CalcMonitorStats
        }
        ; Calculate new position for window.
        gosub CalcNewPosition
    }

    ; Restore before resizing...
    WinGet, state, MinMax
    if state
        WinRestore

    ; Finally, move the window!
    SetWinDelay, 0
    WinMove,,, newx, newy, neww, newh
   
    return

CalcNewPosition:
    ; Calculate new size.
    if (IsResizable()) {
        neww := Round(monWidth * widthFactor)
        newh := Round(monHeight * heightFactor)
    } else {
        neww := w
        newh := h
    }
    ; Calculate new position.
    newx := Round(monLeft + (sideX+1) * (monWidth  - neww)/2)
    newy := Round(monTop  + (sideY+1) * (monHeight - newh)/2)
    return

CalcMonitorStats:
    ; Get work area (excludes taskbar-reserved space.)
    SysGet, mon, MonitorWorkArea, %m%
    monWidth  := monRight - monLeft
    monHeight := monBottom - monTop
    return
}

; Get the index of the monitor containing the specified x and y co-ordinates.
GetMonitorAt(x, y, default=1)
{
    SysGet, m, MonitorCount
    ; Iterate through all monitors.
    Loop, %m%
    {   ; Check if the window is on this monitor.
        SysGet, Mon, Monitor, %A_Index%
        if (x >= MonLeft && x <= MonRight && y >= MonTop && y <= MonBottom)
            return A_Index
    }

    return default
}

IsResizable()
{
    WinGetClass, Class
    if Class = Chrome_XPFrame

        return true
    WinGet, Style, Style
    return (Style & 0x40000) ; WS_SIZEBOX
}

WindowPad_WinExist(WinTitle)
{
    if WinTitle = P
        return WinPreviouslyActive()
    if WinTitle = M
    {
        MouseGetPos,,, win
        return WinExist("ahk_id " win)
    }
    return WinExist(WinTitle!="" ? WinTitle : "A")
}

; Note: This may not work properly with always-on-top windows. (Needs testing)
WinPreviouslyActive()
{
    active := WinActive("A")
    WinGet, win, List

    ; Find the active window.
    ; (Might not be win1 if there are always-on-top windows?)
    Loop, %win%
        if (win%A_Index% = active)
        {
            if (A_Index < win)
                N := A_Index+1
           
            ; hack for PSPad: +1 seems to get the document (child!) window, so do +2
            ifWinActive, ahk_class TfPSPad
                N += 1
           
            break
        }

    ; Use WinExist to set Last Found Window (for consistency with WinActive())
    return WinExist("ahk_id " . win%N%)
}


;
; Switch without moving/resizing (relative to screen)
;
WindowScreenMove(P)
{
    SetWinDelay, 0
   
    StringSplit, P, P, `,, %A_Space%%A_Tab%
    ; 1:Next|Prev|Num, 2:Window
   
    WindowPad_WinExist(P2)

    WinGet, state, MinMax
    if state = 1
        WinRestore

    WinGetPos, x, y, w, h
   
    ; Determine which monitor contains the center of the window.
    ms := GetMonitorAt(x+w/2, y+h/2)
   
    SysGet, mc, MonitorCount

    ; Determine which monitor to move to.
    if P1 in ,N,Next
    {
        md := ms+1
        if (md > mc)
            md := 1
    }
    else if P1 in P,Prev,Previous
    {
        md := ms-1
        if (md < 1)
            md := mc
    }
    else if P1 is integer
        md := P1
   
    if (md=ms or (md+0)="" or md<1 or md>mc)
        return
   
    ; Get source and destination work areas (excludes taskbar-reserved space.)
    SysGet, ms, MonitorWorkArea, %ms%
    SysGet, md, MonitorWorkArea, %md%
    msw := msRight - msLeft, msh := msBottom - msTop
    mdw := mdRight - mdLeft, mdh := mdBottom - mdTop
   
    ; Calculate new size.
    if (IsResizable()) {
        w *= (mdw/msw)
        h *= (mdh/msh)
    }
   
   ; ------------------------------------------------------------------
   ;
   ; Change size and position of MDI windows
   ;
   mw_scale := (mdw/msw)
   mh_scale := (mdh/msh)
   
   WinGet ControlList, ControlList
   ;MsgBox, %ControlList%
   Loop, parse, ControlList, `n
   {
      ; Find position of parent MDI Client
      IfInString, A_Loopfield, MDIClient
      {
         ControlGetPos, mdiX, mdiY, mdiW, mdiH, %A_LoopField%
         ;msgbox %A_Loopfield%, %mdiX%, %mdiY%, %mdiW%, %mdiH%
      }

      ; If the control is a Child window, then calculate it's new position and move it.
      ControlGet, exStyle, ExStyle, , %A_LoopField%      
      if (exStyle & 0x40) ; WS_EX_MDICHILD
      {
         ControlGetPos, cX, cY, cWidth, cHeight, %A_LoopField%
         
         cX -= mdiX
         cY -= mdiY
         
         scX := Round((cX/msw)*mdw) + mdiX
         scY := Round((cY/msh)*mdh) + mdiY
         
         scW := Round(cWidth * mw_scale)
         scH := Round(cHeight * mh_scale)
         
         ;msgbox %cWidth%x%cHeight%, %msw%x%msh%, %mdw%x%mdh%, cx=%cX%, cy=%cY%, scX=%scX%, scY=%scY%, %scW%x%scH%
         ControlMove %A_LoopField%, scX, scY, scW, scH
      }
   }
   ; ------------------------------------------------------------------


    ; Move window, using resolution difference to scale co-ordinates.
    WinMove,,, mdLeft + (x-msLeft)*(mdw/msw), mdTop + (y-msTop)*(mdh/msh), w, h

    if state = 1
        WinMaximize
}


;
; "Gather" windows on a specific screen.
;
GatherWindows(md=1)
{
    global ProcessGatherExcludeList
   
    SetWinDelay, 0
   
    ; List all visible windows.
    WinGet, win, List
   
    ; Copy bounds of all monitors to an array.
    SysGet, mc, MonitorCount
    Loop, %mc%
        SysGet, mon%A_Index%, MonitorWorkArea, %A_Index%
   
    if md = M
    {   ; Special exception for 'M', since the desktop window
        ; spreads across all screens.
        CoordMode, Mouse, Screen
        MouseGetPos, x, y
        md := GetMonitorAt(x, y, 0)
    }
    else if md is not integer
    {   ; Support A, P and WinTitle.
        ; (Gather at screen containing specified window.)
        WindowPad_WinExist(md)
        WinGetPos, x, y, w, h
        md := GetMonitorAt(x+w/2, y+h/2, 0)
    }
    if (md<1 or md>mc)
        return
   
    ; Destination monitor
    mdx := mon%md%Left
    mdy := mon%md%Top
    mdw := mon%md%Right - mdx
    mdh := mon%md%Bottom - mdy
   
    Loop, %win%
    {
        ; If this window matches the GatherExclude group, don't touch it.
        if (WinExist("ahk_group GatherExclude ahk_id " . win%A_Index%))
            continue
       
        ; Set Last Found Window.
        if (!WinExist("ahk_id " . win%A_Index%))
            continue

        WinGet, procname, ProcessName
        ; Check process (program) exclusion list.
        if procname in %ProcessGatherExcludeList%
            continue
       
        WinGetPos, x, y, w, h
       
        ; Determine which monitor this window is on.
        xc := x+w/2, yc := y+h/2
        ms := 0
        Loop, %mc%
            if (xc >= mon%A_Index%Left && xc <= mon%A_Index%Right
                && yc >= mon%A_Index%Top && yc <= mon%A_Index%Bottom)
            {
                ms := A_Index
                break
            }
        ; If already on destination monitor, skip this window.
        if (ms = md)
            continue
       
        WinGet, state, MinMax
        if (state = 1) {
            WinRestore
            WinGetPos, x, y, w, h
        }
   
        if ms
        {
            ; Source monitor
            msx := mon%ms%Left
            msy := mon%ms%Top
            msw := mon%ms%Right - msx
            msh := mon%ms%Bottom - msy
           
            ; If the window is resizable, scale it by the monitors' resolution difference.
            if (IsResizable()) {
                w *= (mdw/msw)
                h *= (mdh/msh)
            }
       
            ; Move window, using resolution difference to scale co-ordinates.
            WinMove,,, mdx + (x-msx)*(mdw/msw), mdy + (y-msy)*(mdh/msh), w, h
        }
        else
        {   ; Window not on any monitor, move it to center.
            WinMove,,, mdx + (mdw-w)/2, mdy + (mdh-h)/2
        }

        if state = 1
            WinMaximize
    }
}


Hotkeys(P)
{
    local this_hotkey, P0, P1, P2, SectionVar, hotkeys, wait_for_keyup, m, m1, pos, k
    static key_regex = "^(?:.* & )?[#!^+&<>*~$]*(.+)"
   
    this_hotkey := A_ThisHotkey
   
    StringSplit, P, P, `,, %A_Space%%A_Tab%
    ; 1:Section, 2:Options
   
    if !P1
        goto HC_SendThisHotkeyAndReturn
   
    pos := RegExMatch(P2, "i)(?<=\bD)\d*\.?\d*", m)
    if pos
    {
        P2 := SubStr(P2, 1, pos-2) . SubStr(P2, pos+StrLen(m))
        if (m+0 = "")
            m := 0.1
        Input, k, L1 T%m%
        if ErrorLevel != Timeout
        {
            gosub HC_SendThisHotkey
            Send %k%
            return
        }
    }
   
    SectionVar := RegExReplace(P1, "[^\w#@$?\[\]]", "_")
    hotkeys := Hotkeys_%SectionVar%
   
    if hotkeys =
    {
        ; Load each hotkeys section on first use. Since the ini file may be
        ; edited between enabling and disabling the hotkeys, loading them
        ; each and every time would be hazardous.
        hotkeys := WindowPad_INI_ReadSection(WINDOWPAD_INI_PATH, "Hotkeys: " P1)
        if hotkeys =
            goto HC_SendThisHotkeyAndReturn
       
        ; key=command  ->  key::command
        hotkeys := RegExReplace(hotkeys, "m`a)^(.*?)=", "$1::")
       
        Hotkeys_%SectionVar% := hotkeys
    }
       
    ; If Options were omitted and this is a key-down hotkey,
    ; automatically disable the hotkeys when the key is released.
    if (wait_for_keyup := (P2="" && SubStr(this_hotkey,-2) != " up"))
        P2 = On ; Explicit "on" in case hotkey exists but is disabled.
   
    Hotkey, IfWinNotActive, ahk_group HotkeyExclude
    Hotkey_Params(hotkeys, P2)
   
    if (wait_for_keyup)
    {
        if (!RegExMatch(this_hotkey, key_regex, m) || GetKeyState(m1)="") {
            MsgBox, % "Error retrieving primary key of hotkey in Hotkeys().`n"
                    . "`tHotkey: " this_hotkey "`n"
                    . "`tResult: " m1
                    . "`nPlease inform Lexikos. Tip: Press Ctrl+C to copy this message."
            return
        }
       
        KeyWait, %m1%
       
        Hotkey_Params(hotkeys, "Off")

        ; A_ThisHotkey: "The key name of the *most recently executed* hotkey"
        ;if(some other hotkey was executed during KeyWait)
        if (this_hotkey = A_ThisHotkey)
            goto HC_SendThisHotkeyAndReturn
    }
    return

HC_SendThisHotkey:
HC_SendThisHotkeyAndReturn:
    if ! InStr(this_hotkey, "~")
        if (RegExMatch(this_hotkey, key_regex, m) && GetKeyState(m1)!="") {
            Hotkey, %this_hotkey%, Off
            Send {Blind}{%m1%}
            Hotkey, %this_hotkey%, On
        }
    return
}


; Hotkey_Params( line [, Options ] )
;   Associates a hotkey with a parameter string.
;
; Expects a newline(`n)-delimited list of hotkeys in the form:
;   Hotkey:: LabelName, Params
;
; Note:
;   - Spaces are optional.
;   - As with hotkey labels, there should be no space between 'Hotkey' and '::'.
;   - Unlike the Hotkey command, LabelName MUST NOT be omitted.
;   - Params MUST NOT contain a newline character (`n).
;   - Params may contain zero or more commas.
;   - , (comma) is supported as a hotkey.
;   - Unlike the Hotkey command, 'Toggle' should be specified in the Options, not as a label.
;
; Returns the number of hotkeys successfully enabled/disabled.
;
Hotkey_Params(line, Options="")
{
    static List ; List of hotkeys and associated labels + parameters.
   
    count = 0
   
    ; Note: The parsing loop operates on a temporary copy of 'line',
    ;       so 'line' can be (and is) reused within the loop.
   
    Loop, Parse, line, `n, %A_Space%%A_Tab%
    {
        ; Clear ErrorLevel in case UseErrorLevel is (not) specified.
        ErrorLevel =

        if ! RegExMatch(A_LoopField, "^\s*(?<Hotkey>.+?)::\s*(?<Label>.+?)(?:,\s*(?<Params>.*?))?\s*$", line)
            continue
       
        if (!IsLabel(lineLabel))
            continue
       
        if Options = Toggle ; Not supported as an option (must be Label.)
        {
            ; Toggle hotkey.  If it doesn't exist, the next line will enable it.
            Hotkey, %lineHotkey%, Toggle, UseErrorLevel
            ; Ensure the hotkey will execute the correct label.
            Hotkey, %lineHotkey%, ExecuteHotkeyWithParams, UseErrorLevel
        } else
            Hotkey, %lineHotkey%, ExecuteHotkeyWithParams, %Options%
       
        ; Check ErrorLevel in case UseErrorLevel was specified.
        if ErrorLevel
            continue
       
        ; Rebuild line to remove whitespace.
        line := lineHotkey "::" lineLabel "," lineParams
       
        ; Update an existing hotkey's label + params,
        temp := RegExReplace(List, "m`n)^\Q" lineHotkey "\E::.*$", line, repl, 1)
        if (repl > 0)
            List := temp
        else    ; or add a new hotkey to the list.
            List .= (List ? "`n" : "") . line

        count += 1
    }
    return count

ExecuteHotkeyWithParams:
    ; Local variables can't be used from the subroutine, so use a function.
    Hotkey_Params_Execute(A_ThisHotkey, List)
return
}

Hotkey_Params_Execute(Hotkey, ByRef List)
{
    global Params ; Parameters of hotkey currently executing.
   
    if (RegExMatch(List, "m`n)^\Q" Hotkey "\E::(?<Label>.+?),(?<Params>.*?)$", a))
    {
        Params := aParams
        gosub %aLabel%
    }
}


;
; Tray Icon Override
;

WM_COMMAND(wParam, lParam)
{
    static IsPaused, IsSuspended
    Critical
    id := wParam & 0xFFFF
    if id in 65305,65404,65306,65403
    {  ; "Suspend Hotkeys" or "Pause Script"
        if id in 65306,65403  ; pause
            IsPaused := ! IsPaused
        else  ; at this point, A_IsSuspended has not yet been toggled.
            IsSuspended := ! A_IsSuspended
        WindowPad_SetTrayIcon(!(IsPaused or IsSuspended))
    }
}

WindowPad_SetTrayIcon(is_enabled)
{
    icon := is_enabled ? "tray.ico" : "disabled.ico"
    icon = %A_ScriptDir%\icons\%icon%

    ; avoid an error message if the icon doesn't exist
    IfExist, %icon%
        Menu, TRAY, Icon, %icon%,, 1
}


GetLastMinimizedWindow()
{
    WinGet, w, List

    Loop %w%
    {
        wi := w%A_Index%
        WinGet, m, MinMax, ahk_id %wi%
        if m = -1 ; minimized
        {
            lastFound := wi
            break
        }
    }

    return "ahk_id " . (lastFound ? lastFound : 0)
}

   
RButton::
   WinGet, win_id, ID, A
   SysGet,TitleH,30
   SysGet,BorderH,33
   TitleH += %BorderH%
   
   MouseGetPos,MouseX,MouseY,MouseWin
   ms := GetMonitorAt(MouseX, MouseY)
   SysGet, ms, MonitorWorkArea, %ms%   
   WinGet, task_bar, ID, ahk_class Shell_TrayWnd
   
   mshow := 0

   if win_id <> %task_bar%
   if win_id = %MouseWin%
      if MouseY between 0 and %TitleH% ; if mouse is in title-bar
      {
         GetKeyState,MState,RButton,P   
         if MState = D
         {
            KeyWait,RButton, U T0.2 ; wait if mousebutton will be released
            if ErrorLevel = 1 ; continue if mousebutton is down after 0.2 sec
            {
               Menu, ContextMenu, show
               mshow := 1
            }
         }
      }
      
   if mshow = 0
      send,{%A_ThisHotkey%}
      
return


;
; Commands usable in WindowPad.ini
;

GatherWindows:
    GatherWindows(Params)
    return
WindowPadMove:
    WindowPadMove(Params)
    return
WindowScreenMove:
    WindowScreenMove(Params)
    return
MaximizeToggle:
    MaximizeToggle(Params)
    return
Hotkeys:
    Hotkeys(Params)
    return
Send:
    Send, %Params%
    return
Minimize:
    if WindowPad_WinExist(Params)
        PostMessage, 0x112, 0xF020  ; WM_SYSCOMMAND, SC_MINIMIZE
    return
Unminimize:
    if WinExist(GetLastMinimizedWindow())
        WinRestore
    return
Restore:
    if WindowPad_WinExist(Params)
        WinRestore
    return

CM_MoveLeft:
   WindowPadMove("-1,0,0.5,1.0")
   return
   
CM_MoveRight:
   WindowPadMove("+1,0,0.5,1.0")
   return
   
CM_MoveUp:
   WindowPadMove("0,-1,1.0,0.5")
   return
   
CM_MoveDown:
   WindowPadMove("0,+1,1.0,0.5")
   return
   
CM_MoveLeftUp:
   WindowPadMove("-1,-1,0.5,0.5")
   return
   
CM_MoveRightUp:
   WindowPadMove("+1,-1,0.5,0.5")
   return
   
CM_MoveLeftDown:
   WindowPadMove("-1,+1,0.5,0.5")
   return
   
CM_MoveRightDown:
   WindowPadMove("+1,+1,0.5,0.5")
   return
   
CM_MoveMiddle:
   WindowPadMove("0,0,0.75,0.75")
   return
   
Back to top
View user's profile Send private message
James UK



Joined: 30 Sep 2008
Posts: 18

PostPosted: Wed Nov 05, 2008 10:53 am    Post subject: Reply with quote

Just wanted to say I've just discovered this script, and it's magnificent!

Truly inspirational work, and such a good idea!
Back to top
View user's profile Send private message Visit poster's website
miniben
Guest





PostPosted: Wed Nov 26, 2008 1:31 pm    Post subject: Reply with quote

Agreed, this script works brilliantly. I paid for some software on my work PC to flip applications between monitors, but this works just as well, is free, and will also flip the previous window as well as active. Just wanted to say thanks.
Back to top
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3 ... 7, 8, 9 ... 20, 21, 22  Next
Page 8 of 22

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group