AutoHotkey Community

It is currently May 26th, 2012, 12:35 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 337 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 23  Next
Author Message
 Post subject:
PostPosted: November 28th, 2008, 12:39 pm 
Thanks, this is truely a master piece!

This will replace UltraMon on my PC for sure (I tried the trial version).

I also have a question. How could I add a function that moves a window to the next monitor by double-clicking on the window header? Currently double clicking maximizes the windows, but I rarely use this function.

Thanks for any help in advance!


Report this post
Top
  
Reply with quote  
 Post subject: Love it
PostPosted: December 1st, 2008, 11:54 pm 
Love it!

Chrome seems to behave strangely though and when used in combination of Ultramon's taskbar extension it removed the ultramon taskbar by doing windows key + *


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 2nd, 2008, 2:06 am 
Offline

Joined: December 6th, 2007, 12:48 pm
Posts: 364
Love it too!! Are there plans to make it more adaptative to big resolutions live 1920 or 2560? I mean, a way to place the windows in a imaginary 9x9 grid, taking each corner or the center...

_________________
AHK is perfect.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 2nd, 2008, 12:40 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
Mpdreamz, I'm not sure how Chrome is related to Ultramon's taskbar extension, but you may need to add an exception for Ultramon in WindowPad.ini. This is outlined in the Configuration section of the WindowPad help file.

Da Rossa, that can already be done by simply tweaking the values for each hotkey in WindowPad.ini. For instance, the following sets z to move a window to the bottom-left of the screen, with 33.3333% the width and height of the screen.
Code:
z = WindowPadMove, -1, +1,  0.333333, 0.333333


Quote:
Version 1.54:
  • WindowPadMove now halves a window's width or height if there is no other screen to move to.
  • Changed default centre-pad hotkeys to use half the screen width rather than 100%.
If I'm working primarily in one window, I usually place it in the center of the screen. This change to WindowPadMove makes it easier to use the surrounding space. For example, in this 74KB screenshot I used Capslock & qq, Capslock & zz, Capslock & s and Capslock & d.

FYI, I don't plan to develop WindowPad any further, but if I hear or think of any more ideas as useful to me as the above, I'll likely implement them.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 2nd, 2008, 2:15 pm 
Lexikos, wow, this is an excellent script!!!

If you like this script, please also checkout WinWarden (by Skrommel):
http://www.donationcoder.com/Software/S ... #WinWarden

Unfortunately not developed any further either, but works very well!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 2nd, 2008, 5:56 pm 
Offline

Joined: December 6th, 2007, 12:48 pm
Posts: 364
Lexikos you intelligent man! You're very creative!! That SS is even beyond what I thought: I'd like to know if it's already possible to do like this: imagine that the screen is divided in a 9-cell grid. Then, I came up with 37 possibilities of placing a window:

Quote:
; single block
1 2 3 4 5 6 7 8 9

; two-block horizontal rectangles
12 23 45 56 78 89

; two-block vertical rectangles
14 25 36
47 58 69

; three-block horizontal rectangles
123
456
789

; three-block vertical rectangles
147
258
369

; four-block squares
1245
2356
4578
5689

; six-block horizontal rectangles
123456
456789

; six-block vertical rectangles
124578
235689

; Nine-block (all, but not maximized)
123456789

; Maximized
0


Did you get the logic?

About the .ini
Unfortunately I opted to take the windowpad code and append to my main script, which means that a .ini file is no longer needed, also, I didn't even remember of the presence of a ini file...

_________________
AHK is perfect.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 11th, 2008, 2:03 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
Thanks a lot for this terrific script. :D


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 11th, 2008, 2:49 pm 
Script of the Decade!!!


Report this post
Top
  
Reply with quote  
 Post subject: No Hotkey
PostPosted: December 13th, 2008, 8:34 pm 
I was inspired by the UnNumpad .ini example from earlier, so I used this. However, using numlock as a toggle has given me some trouble. For instance, if the script starts with numlock in the wrong state it simply does not work. Futhermore, virtualization software I use (Synergy) does not send the NumLock key specifically, so it does not work over that. I would like to bind the UnNumlock keys to work regardless of the state of numlock. So, when numlock is on and I press the numpad 5 key a Numpad5 signal is sent and interpreted as normal. When I turn numlock off and press numpad 5 a NumpadClear signal is sent and is always interpreted by WindowPad, regardless of it's internal toggle state of any particular key. Does that make sense?

So I want to use no toggling hot key, just the regular dedicated keys. But I've found I cannot leave the sapce before = Hotkeys, UnNumpad blank. Any help/thoughs/suggestions? Thanks!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 14th, 2008, 2:42 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
The entire purpose of a [Hotkey: *] section is to allow a list of hotkeys to be conveniently enabled and disabled. Simply move the hotkeys to the [Hotkeys] section and they will always be enabled. You will need to duplicate the keys for NumpadEnd/Numpad1, NumpadDown/Numpad2, etc. if you haven't already.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 17th, 2008, 5:17 am 
Offline

Joined: March 10th, 2008, 8:56 pm
Posts: 1
General tip for WindowPad users:

I have a common scenario that I addressed in WindowPad via a simple .ini modification. I'm posting it here in case others find it useful.

Here's the story: I have a 1920-by-it-doesn't-matter monitor. Unfortunately, some web sites assume a 1024-wide screen, so a 1/2 screen size is juuust a bit too narrow at 960 pixels wide.

To fix this, I added a new hotkey (Numpad+PlusSign) that adjusts to 60% of the screen instead of 50%. Since I only do this occasionally, it's better for me than modifying the primary hotkey, the NumPad0/Ins key. To do this, I just added:

Code:
NumpadAdd = Hotkeys, Active Window (NumpadAlt)

To the top [Hotkeys] section. Then, down below, I added this:
Code:
[Hotkeys: Active Window (NumpadAlt)]
*Numpad1 = WindowPadMove, -1, +1,  0.6, 0.6
*Numpad2 = WindowPadMove,  0, +1,  1.0, 0.6
*Numpad3 = WindowPadMove, +1, +1,  0.6, 0.6
*Numpad4 = WindowPadMove, -1,  0,  0.6, 1.0
*Numpad5 = WindowPadMove,  0,  0,  1.0, 1.0
*Numpad6 = WindowPadMove, +1,  0,  0.6, 1.0
*Numpad7 = WindowPadMove, -1, -1,  0.6, 0.6
*Numpad8 = WindowPadMove,  0, -1,  1.0, 0.6
*Numpad9 = WindowPadMove, +1, -1,  0.6, 0.6

above the [Gather: Exclude Windows] section. Now, if I run into a situation where 50% is a bit too narrow, I just hit Numpad-Plus and a numpad directional arrow and it stretches the size a bit.

Note that .6 (60%) gives me a width of 1152, while .533 would have been closer to 1024. I find the extra width to be OK, and with 1.54 it also goes to a nice size with the new "squeeze against the edge" feature. I might play around with it a bit more to find the right amount though.

What I really wanted was a "nudge" option that adds (say) 5% to the width of the current window in the direction of the modifier key. However, it doesn't look like that can be done in the .ini file, so this is good enough for now.

I know this isn't rocket science or anything, but for new users of WindowPad it might be helpful to see what else can be done in the WindowPad.ini.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 19th, 2008, 4:01 am 
Lexikos wrote:
The entire purpose of a [Hotkey: *] section is to allow a list of hotkeys to be conveniently enabled and disabled. Simply move the hotkeys to the [Hotkeys] section and they will always be enabled. You will need to duplicate the keys for NumpadEnd/Numpad1, NumpadDown/Numpad2, etc. if you haven't already.


Wow - that was easy. Thanks!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: December 19th, 2008, 9:38 am 
Offline

Joined: December 6th, 2007, 12:48 pm
Posts: 364
Please Lexikos, don't stop developing it! Not saying that it's faulty/buggy, because it's not, I'm just wondering if some more combinations are possible! :D

But, if you're really gonna stop it, please solve my issue:

Remeber that version in which we held down Win and pressed numpadbuttons, in order to move the window to the region of the screen associated to that number? (for example: Win+Numpad1 would move the window to the bottom-left corner of the window, and so on).

So, I have it appended to my main-daily script. It is...

Code:
gosub WindowPadInit

; WindowPad:
;
;   Move and resize windows with Win+Numpad.
;     Win+Numpad1 = Fill bottom-left quarter of screen
;     Win+Numpad2 = Fill bottom half of screen
;     etc.
;
;   Move windows across monitors. For example:
;     Win+Numpad4 places the window on the left half of the screen.
;     Win+Numpad4 again moves it to the monitor to the right.
;
;   Quick monitor switch:
;     Win+Numpad5 places the window in the center of the screen.
;     Win+Numpad5 again moves the window to the next monitor.
;     (This works by monitor number, not necessarily left to right.)
;
;   QUICKER Monitor Switch:
;     Win+NumpadDot switches to the next monitor (1->2->3->1 etc.)
;     Win+NumpadDiv moves ALL windows to monitor 2.
;     Win+NumpadMult moves ALL windows to monitor 1.
;
;   Other shortcuts:
;     Win+Numpad0 toggles maximize.
;     Insert (or some other key) can be used in place of "Win".
;


WindowPadInit:
; Exclusion examples:
GroupAdd, GatherExclude, ahk_class SideBar_AppBarWindow
; These two come in pairs for the Vista sidebar gadgets:
GroupAdd, GatherExclude, ahk_class SideBar_HTMLHostWindow   ; gadget content
GroupAdd, GatherExclude, ahk_class BasicWindow              ; gadget shadow/outline

; Comma-delimited list of processes to exclude.
;ProcessGatherExcludeList = sidebar.exe

; (ProcessGatherExcludeList excludes ALL windows belonging to those processes,
;  including windows you may not want to exclude, like the sidebar config window.)

Prefix_Active = #   ; Win+Numpad      = Move active window
Prefix_Other  = #!  ; Alt+Win+Numpad  = Move previously active window

; Note: Shift (+) should not be used, as +Numpad is hooked by the OS
;   to do left/right/up/down/etc. (reverse Numlock) -- at least on Vista.

EasyKey = Insert    ; Insert is near Numpad on my keyboard...

; Note: Prefix_Other must not be a sub-string of Prefix_Active.
;       (If you want it to be, first edit the line "if (InStr(A_ThisHotkey, Prefix_Other))")

; Width and Height Factors for Win+Numpad5 (center key.)
CenterWidthFactor   = 1.0
CenterHeightFactor  = 1.0

Hotkey, IfWinActive ; in case this is included in another script...

Loop, 9
{   ; Register hotkeys.
    Hotkey, %Prefix_Active%Numpad%A_Index%, DoMoveWindowInDirection
    Hotkey, %Prefix_Other%Numpad%A_Index%, DoMoveWindowInDirection
    ; OPTIONAL
    if EasyKey
        Hotkey, %EasyKey% & Numpad%A_Index%, DoMoveWindowInDirection
}
Hotkey, %Prefix_Active%Numpad0, DoMaximizeToggle
Hotkey, %Prefix_Other%Numpad0, DoMaximizeToggle

Hotkey, %Prefix_Active%NumpadDot, MoveWindowToNextScreen
Hotkey, %Prefix_Other%NumpadDot, MoveWindowToNextScreen

Hotkey, %Prefix_Active%NumpadDiv, GatherWindowsLeft
Hotkey, %Prefix_Active%NumpadMult, GatherWindowsRight

if (EasyKey) {
    Hotkey, %EasyKey% & Numpad0, DoMaximizeToggle
    Hotkey, %EasyKey% & NumpadDot, MoveWindowToNextScreen
    Hotkey, %EasyKey% & NumpadDiv, GatherWindowsLeft
    Hotkey, %EasyKey% & NumpadMult, GatherWindowsRight
    Hotkey, *%EasyKey%, SendEasyKey ; let EasyKey's original function work (on release)
}
return

SendEasyKey:
    Send {Blind}{%EasyKey%}
    return

; This is actually based on monitor number, so if your secondary is on the
; right, you may want to switch these around.
GatherWindowsLeft:
    GatherWindows(2)
    return
GatherWindowsRight:
    GatherWindows(1)
    return



; Hotkey handler.
DoMoveWindowInDirection:
    DoMoveWindowInDirection()
    return

DoMoveWindowInDirection()
{
    local dir, dir0, dir1, dir2, widthFactor, heightFactor
   
    ; Define constants.
    if (!Directions1) {
        dir = -1:+1,0:+1,+1:+1,-1:0,0:0,+1:0,-1:-1,0:-1,+1:-1
        StringSplit, Directions, dir, `,
    }

    gosub WP_SetLastFoundWindowByHotkey
   
    ; Determine which direction we want to go.
    if (!RegExMatch(A_ThisHotkey, "\d+", dir) or !Directions%dir%)
    {
        MsgBox Error: "%A_ThisHotkey%" was registered and I can't figure out which number it is!
        return
    }
    dir := Directions%dir%
    StringSplit, dir, dir, :
   
    ; Determine width/height factors.
    if (dir1 or dir2) { ; to a side
        widthFactor  := dir1 ? 0.5 : 1.0
        heightFactor := dir2 ? 0.5 : 1.0
    } else {            ; to center
        widthFactor  := CenterWidthFactor
        heightFactor := CenterHeightFactor
    }
   
    ; Move the window!
    MoveWindowInDirection(dir1, dir2, widthFactor, heightFactor)
}
return

WP_SetLastFoundWindowByHotkey:
    ; Set Last Found Window.
    if (InStr(A_ThisHotkey, Prefix_Other))
        WinPreviouslyActive()
    else
        WinExist("A")
return

; "Maximize"
DoMaximizeToggle:
    MaximizeToggle()
return
   
MaximizeToggle()
{
    gosub WP_SetLastFoundWindowByHotkey
    WinGet, state, MinMax
    if state
        WinRestore
    else
        WinMaximize
}


; Does the grunt work of the script.
MoveWindowInDirection(sideX, sideY, widthFactor, heightFactor, screenMoveOnly=false)
{
    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, -1
    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()
{
    WinGet, Style, Style
    return (Style & 0x40000) ; WS_SIZEBOX
}

; 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)
;
MoveWindowToNextScreen:
    gosub WP_SetLastFoundWindowByHotkey
    WinGet, state, MinMax
    if state = 1
    {   ; Maximized windows don't move correctly on XP
        ; (and possibly other versions of Windows)
        WinRestore
        MoveWindowToNextScreen()
        WinMaximize
    }
    else
        MoveWindowToNextScreen()
return

MoveWindowToNextScreen()
{
    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 > mon)
        md := 1
   
    ; 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
}


;
; "Gather" windows on a specific screen.
;

GatherWindows(md=1)
{
    global ProcessGatherExcludeList
   
    SetWinDelay, -1 ; Makes a BIG difference to perceived performance.
   
    ; 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%
   
    ; 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 := 1
        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
       
        ; 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)
        }
   
        WinGet, state, MinMax
        if state = 1
            WinRestore
       
        ; Move window, using resolution difference to scale co-ordinates.
        WinMove,,, mdx + (x-msx)*(mdw/msw), mdy + (y-msy)*(mdh/msh), w, h

        if state = 1
            WinMaximize
    }
}


Note that I'm not using any .ini file.

Now, you present us the new version, with that even better arranged window scheme... and I'd like to append it to my script too.

It would be...

Code:
; WindowPad v1.54
;
; 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)
}

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
        }
        else
        {   ; No monitor to move to, alternate size of window instead.
            if sideX
                widthFactor /= 2
            else if sideY
                heightFactor /= 2
            gosub CalcNewPosition
        }
       
        ; 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)
    }
   
    ; 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)
}



;
; 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


But, when I execute my script after appending that, I get the error:

Quote:
"Error at line 10098
Line Text: WindowPadInit
Error: Duplicate label

The program will now exit."


I tried taking the second instance of the "WindowPadInit and rename to WindowPadInit2." Then, the error was:

Quote:
Error at line ....

Line text: MaximizeToggle(P)
Error: Duplicate function definition

The program will exit.


What to do to make them live together in harmony?

Thanks in advance!

_________________
AHK is perfect.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 19th, 2008, 9:53 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7502
Location: Australia
Da Rossa wrote:
Please Lexikos, don't stop developing it!
It's way too late to say that.
Quote:
What to do to make them live together in harmony?
The layout of the original script can be duplicated by editing the INI of the newer script. Configuration is briefly outlined in the help file.

It would be illogical to use both scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 20th, 2008, 7:14 am 
Offline

Joined: December 6th, 2007, 12:48 pm
Posts: 364
:(
Well, I tried with all my knowledge, but I was unable to do that. This is more complicated than i thought, unfortunately. I've been using an older version, don't know which one, but it's the one you controled the window positions with Win+NumpadX. That had actually fewer possibilities, as usual. But as far as I recall, there was no Windowpad.ini file, and things were easier :( there was even a brief but intuitive explanatory comment at the beginning...

Code:
; WindowPad:
;
;   Move and resize windows with Win+Numpad.
;     Win+Numpad1 = Fill bottom-left quarter of screen
;     Win+Numpad2 = Fill bottom half of screen
;     etc.
;
;   Move windows across monitors. For example:
;     Win+Numpad4 places the window on the left half of the screen.
;     Win+Numpad4 again moves it to the monitor to the right.
;
;   Quick monitor switch:
;     Win+Numpad5 places the window in the center of the screen.
;     Win+Numpad5 again moves the window to the next monitor.
;     (This works by monitor number, not necessarily left to right.)
;
;   QUICKER Monitor Switch:
;     Win+NumpadDot switches to the next monitor (1->2->3->1 etc.)
;     Win+NumpadDiv moves ALL windows to monitor 2.
;     Win+NumpadMult moves ALL windows to monitor 1.
;
;   Other shortcuts:
;     Win+Numpad0 toggles maximize.
;     Insert (or some other key) can be used in place of "Win".
;


In which I could know quick which keys would trigger the functions...

With this one, I had to dig a little until I could figure that CapsLock+[qweasdzxc{tab}] would do the job.

I liked this new version because of the extra (narrower) possibilities of a window, and to fit them in that layout you suggested.. But let's be honest: CapsLock+[qweasdzxc] are not very comfortable, don't know if it's about my fingers or whatsoever... Win+NumpadX, if we could use both at the same time, would be great... but the thing is that I'm narrow-brained and don't exactly know how to change the hotkeys (I tried hitting the specified under "[Hotkeys: Active Window (Numpad)]" but nothing happened...

Anyway, that's sad for me :(

_________________
AHK is perfect.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 337 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 23  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Cerberus, Exabot [Bot] and 18 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group