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 

Auto-raise / mouse hover
Goto page 1, 2, 3, 4, 5, 6  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Mon Sep 03, 2007 1:43 pm    Post subject: Auto-raise / mouse hover Reply with quote

Auto-raise and Other Stuff on Mouse Hover

This script was written in reply to a request on the Ask for Help forum. See the comments for a description of each option.
Code:
#Persistent

hover_task_buttons  = 1 ; hover over taskbar button to activate window
  hover_task_group  = 1 ; hover to select (or exit) from a window-group menu
                        ; (for Windows' "Group similar taskbar buttons" feature)
hover_task_min_info = 0 ; only show info for minimized windows, don't activate
hover_start_button  = 1 ; hover over start button to open start menu
hover_min_max       = 1 ; minimize or maximize by hovering over the min/max buttons
hover_any_window    = 0 ; activate any window by hovering (except the taskbar)

hover_no_buttons    = 1 ; ignore hover if a mouse button is in the down state

hover_delay       = 500 ; hover delay, from when the mouse stops moving

; WORKS, BUT NOT PERFECTLY: (brings the window forward, then puts it back in place)
hover_keep_zorder   = 0 ; don't bring windows forward, only activate them

;
; DisableHover - since menus aren't usually truly "activated", if any
;   window in the DisableHover group *EXISTS*, hover will be ignored.
;
GroupAdd, DisableHover, ahk_class #32768

; I'm not certain whether this class is used only for menus;
; if not, you may need to comment out this line.
GroupAdd, DisableHover, ahk_class MozillaDropShadowWindowClass


CoordMode, Mouse, Screen
SetTimer, hovercheck, 10
return


; Don't consider it hovering if the mouse was clicked.
; However, clicking and then moving a small amount will still trigger hover.
~LButton::
~RButton::
~MButton::
    MouseGetPos, lastx, lasty
return


hovercheck:
    MouseGetPos, x, y
    if (x != lastx or y != lasty)
    {
        SetTimer, hovering, % -hover_delay
        lastx := x
        lasty := y

        if (remove_ttip_on_move)
        {
            ToolTip
            remove_ttip_on_move := false
        }
    }
return


hovering:
    if (hover_no_buttons && (GetKeyState("LButton") or GetKeyState("RButton")))
        return
   
    if (WinExist("ahk_group DisableHover"))
        return

; hover over taskbar button to activate window:
    if (hover_task_buttons)
    {   ; hovering over taskbar button.
        if (GetMouseTaskButton(win))
        {
            if (win)
            {
                if (hover_task_min_info)
                {
                    WinGet, min_max, MinMax, ahk_id %win%
                    if (min_max = -1)
                    {
                        WinGetTitle, ti, ahk_id %win%
                        ToolTip, %ti% (minimized)
                        remove_ttip_on_move := true
                        return
                    }
                }
                if (hover_keep_zorder)
                {
                    JustActivate(win)
                    return
                }
                WinActivate, ahk_id %win%
            }
            ; May be a group button ("Group similar taskbar buttons")
            else
                Click
            return
        }
        else if (hover_task_group && WinActive("ahk_class Shell_TrayWnd"))
        {   ; Check if we are hovering over a toolbar window,
            ; possibly a list of grouped buttons/windows.
            MouseGetPos,,, win, ctl, 2
            ctl_parent := DllCall("GetParent", "uint", ctl) ; get control parent
            WinGetClass, ctl, ahk_id %ctl%                  ; get control class
            WinGetClass, ctl_parent, ahk_id %ctl_parent%    ; get parent class
            WinGetClass, win, ahk_id %win%                  ; get window class
            if (win="BaseBar"                       ; probably a button group menu
                || (win="Shell_TrayWnd"             ; taskbar
                 && ctl_parent="MSTaskSwWClass"))   ; task buttons
                Click
            ; (The win="BaseBar" check excludes the system notification area.)
            return
        }
    }
; hover over start button to open start menu:
    if (hover_start_button && !WinActive("ahk_class DV2ControlHost")) ; Start Menu
    {
        MouseGetPos,,, win, ctl
        WinGetTitle, ti, ahk_id %win%
        WinGetClass, cl, ahk_id %win%
        if ((cl = "Button" && ti = "Start")) ; Vista / Windows 7
            or (cl = "Shell_TrayWnd" && ctl = "Button1")
        {
            Click
            return
        }
    }
; hover over minimize, maximize or help buttons on titlebar:
    if (hover_min_max)
    {
        MouseGetPos, x, y, win, ctl, 2
        SendMessage, 0x84,, (x & 0xFFFF) | (y & 0xFFFF) << 16,, % "ahk_id " (ctl ? ctl : win)
        if ErrorLevel in 8,9  ; min,max (titlebar)
        {
            Click
            return
        }
    }
; hover over any window to focus:
    if (hover_any_window)
    {
        ifWinExist, ahk_id %win% ahk_class Shell_TrayWnd
            return  ; don't activate the taskbar
        MouseGetPos,,, win
        if (!WinActive("ahk_id " win)) {
            if (hover_keep_zorder)
                JustActivate(win)
            else
                WinActivate, ahk_id %win%
        }
    }
return


JustActivate(hwnd)
{
    if (WinActive("ahk_id " hwnd))
        return
   
    ; Get the window which hwnd is positioned after, so hwnd's position
    ; in the z-order can be restored after activation.   
    hwnd_prev := GetPrevWindow(hwnd)
    ; DllCall("GetWindow","uint",hwnd,"uint",3) would be simpler,
    ; but doesn't work right since it usually gets an invisible window
    ; which moves when we activate hwnd.
   
    ; Repositioning a window in the z-order sometimes sets AlwaysOnTop.
    WinGet, OldExStyle, ExStyle, ahk_id %hwnd%
   
    ;WinActivate, ahk_id %hwnd%  ; -- best to use SetWinDelay,-1 if using WinActivate.
    DllCall("SetForegroundWindow", "uint", hwnd)
    DllCall("SetWindowPos", "uint", hwnd, "uint", hwnd_prev
        , "int", 0, "int", 0, "int", 0, "int", 0
        , "uint", 0x13)  ; NOSIZE|NOMOVE|NOACTIVATE (0x1|0x2|0x10)
   
    ; Note NOACTIVATE above: if this is not specified, SetWindowPos activates
    ; the window, bringing it forward (effectively ignoring hwnd_prev...)

    ; Check if AlwaysOnTop status changed.   
    WinGet, ExStyle, ExStyle, ahk_id %hwnd%
    if (OldExStyle ^ ExStyle) & 0x8
        WinSet, AlwaysOnTop, Toggle
}

; Like GetWindow(hwnd, GW_HWNDPREV), but ignores invisible windows.
GetPrevWindow(hwnd)
{
    global GetPrevWindow_RetVal

    static cb_EnumChildProc
    if (!cb_EnumChildProc)
        cb_EnumChildProc := RegisterCallback("GetPrevWindow_EnumChildProc","F")

    ; Set default in case enumeration fails.
    GetPrevWindow_RetVal := DllCall("GetWindow", "uint", hwnd, "uint", 3)
   
    ; Enumerate all siblings of hwnd.
    hwnd_parent := DllCall("GetParent", "uint", hwnd)
    DllCall("EnumChildWindows", "uint", hwnd_parent, "uint", cb_EnumChildProc, "uint", hwnd)
   
    ; Return the last visible window before hwnd.
    return GetPrevWindow_RetVal
}
GetPrevWindow_EnumChildProc(test_hwnd, hwnd)
{
    global GetPrevWindow_RetVal
    ; Continue until hwnd is enumerated.
    if (test_hwnd = hwnd)
        return false
    ; Remember the last visible window before hwnd.
    if (DllCall("IsWindowVisible", "uint", test_hwnd))
        GetPrevWindow_RetVal := test_hwnd
    return true
}


; Gets the index+1 of the taskbar button which the mouse is hovering over.
; Returns an empty string if the mouse is not over the taskbar's task toolbar.
;
; Some code and inspiration from Sean's TaskButton.ahk
GetMouseTaskButton(ByRef hwnd)
{
    MouseGetPos, x, y, win, ctl, 2
    ; Check if hovering over taskbar.
    WinGetClass, cl, ahk_id %win%
    if (cl != "Shell_TrayWnd")
        return
    ; Check if hovering over a Toolbar.
    WinGetClass, cl, ahk_id %ctl%
    if (cl = "MSTaskListWClass"  ; Windows 7: the methods used below won't work.
        || A_PtrSize=8  ; Script not compatible with 64-bit AutoHotkey.exe.
        || DllCall("IsWow64Process", "Uint", DllCall("GetCurrentProcess")
            , "intP", iswow64) && iswow64)  ; OS/taskbar is 64-bit - not compatible.
    {   
        hwnd := 0
        return 1
    }
    if (cl != "ToolbarWindow32")
        return
    ; Check if hovering over task-switching buttons (specific toolbar).
    hParent := DllCall("GetParent", "Uint", ctl)
    WinGetClass, cl, ahk_id %hParent%
    if (cl != "MSTaskSwWClass")
        return
   
    WinGet, pidTaskbar, PID, ahk_class Shell_TrayWnd

    hProc := DllCall("OpenProcess", "Uint", 0x38, "int", 0, "Uint", pidTaskbar)
    pRB := DllCall("VirtualAllocEx", "Uint", hProc
        , "Uint", 0, "Uint", 20, "Uint", 0x1000, "Uint", 0x4)

    VarSetCapacity(pt, 8, 0)
    NumPut(x, pt, 0, "int")
    NumPut(y, pt, 4, "int")
   
    ; Convert screen coords to toolbar-client-area coords.
    DllCall("ScreenToClient", "uint", ctl, "uint", &pt)
   
    ; Write POINT into explorer.exe.
    DllCall("WriteProcessMemory", "uint", hProc, "uint", pRB+0, "uint", &pt, "uint", 8, "uint", 0)

;     SendMessage, 0x447,,,, ahk_id %ctl%  ; TB_GETHOTITEM
    SendMessage, 0x445, 0, pRB,, ahk_id %ctl%  ; TB_HITTEST
    btn_index := ErrorLevel
    ; Convert btn_index to a signed int, since result may be -1 if no 'hot' item.
    if btn_index > 0x7FFFFFFF
        btn_index := -(~btn_index) - 1
   
   
    if (btn_index > -1)
    {
        ; Get button info.
        SendMessage, 0x417, btn_index, pRB,, ahk_id %ctl%   ; TB_GETBUTTON
   
        VarSetCapacity(btn, 20)
        DllCall("ReadProcessMemory", "Uint", hProc
            , "Uint", pRB, "Uint", &btn, "Uint", 20, "Uint", 0)
   
        state := NumGet(btn, 8, "UChar")  ; fsState
        pdata := NumGet(btn, 12, "UInt")  ; dwData
       
        ret := DllCall("ReadProcessMemory", "Uint", hProc
            , "Uint", pdata, "UintP", hwnd, "Uint", 4, "Uint", 0)
    } else
        hwnd = 0

       
    DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pRB, "Uint", 0, "Uint", 0x8000)
    DllCall("CloseHandle", "Uint", hProc)


    ; Negative values indicate seperator items. (abs(btn_index) is the index)
    return btn_index > -1 ? btn_index+1 : 0
}
Covered by Lexikos' default copyright license.

2007-09-04

  • Replaced Click with WinActivate when the button's associated window is known.
  • Added support for Windows' "Group similar taskbar buttons" feature. If hover_task_group is set to 1, hovering over an item in a button-group menu will select it, and hovering over the taskbar will close the group menu.
  • Added hover_task_min_info. If set to 1, hovering over the button of a minimized window will show a tooltip instead of activating it. (Ideas for more useful information in the tooltip are welcome.)
  • Added hover_no_menus. If set to 1, hovering will have no effect if a menu (ahk_class #32768) is open.
  • Added primitive z-order preservation, via hover_keep_zorder. Currently windows are still brought forward when activated, but the script attempts to move them back to where they were.
  • Replaced the second timer (hovering) with an A_TimeIdle check and gosub (in hovercheck.)
  • Increased the frequency of hovercheck to 10ms. This should improve the accuracy of hover_delay.
  • A few misc changes.

2007-09-05
  • GetMouseTaskButton() now uses TB_HITTEST instead of TB_GETHOTITEM, so should be more accurate.

2007-09-23
  • Changed default hover_task_min_info to 0 (off - hovering over the button of a minimized window will activate it.)
  • Clicking a mouse button now prevents "hover", unless the mouse was moved even slightly.
  • Hovering over the taskbar no longer activates it when hover_any_window is enabled and the mouse isn't over a taskbar button (and in any other case.)

2007-09-24
  • Replaced hover_no_menus with the DisableHover group. Added #32768 (standard menus) and MozillaDropShadowWindowClass (used by Firefox and Thunderbird menus.)

2007-09-29
  • Changed default hover_any_window back to 0 (off). It was left on unintentionally during testing.

2008-12-30
  • Added license info.

2011-03-18
  • Got basic hover_task_buttons and hover_start_button functionality working on Windows 7.


Last edited by Lexikos on Tue Mar 22, 2011 12:12 pm; edited 11 times in total
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Mon Sep 03, 2007 5:37 pm    Post subject: Reply with quote

Cool! Thanks for sharing it.

One thing, which could be different: hovering over a taskbar button activates the corresponding window, even if it was minimized. It would be more conventional to show only info on that application.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Mon Sep 03, 2007 5:47 pm    Post subject: Reply with quote

Have you considered using A_TimeIdlePhysical for determining the hovering time? It could allow saving a few lines of code.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Tue Sep 04, 2007 2:12 am    Post subject: Reply with quote

Both excellent ideas. Smile

Edit: Still need the position check - it needs to prevent repeat "hover" in cases where the user presses a key but doesn't move the mouse.
Edit: I can't think of any useful info to show for a minimized window. What did you have in mind?
Edit: Does anyone know how to activate a window without bringing it to the front of the z-order?
Back to top
View user's profile Send private message Visit poster's website
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Wed Sep 05, 2007 12:19 am    Post subject: Reply with quote

Updated (again). The script now uses TB_HITTEST instead of TB_GETHOTITEM. It turns out TB_HITTEST wasn't working because the POINT was supposed to be in explorer.exe's memory space. I hadn't realised this because by some freak coincidence I was actually pointing to valid memory inside explorer.exe. (On the second or third try, it crashed explorer; that's when I realised.)
Back to top
View user's profile Send private message Visit poster's website
user



Joined: 05 Oct 2006
Posts: 476

PostPosted: Wed Sep 05, 2007 5:15 am    Post subject: Reply with quote

thank you very much for this script that will save us numerous clicks and time Smile
Back to top
View user's profile Send private message
Sridhar
Guest





PostPosted: Thu Sep 06, 2007 6:00 am    Post subject: Reply with quote

Hello,

I saved the code in the first post as AutoRaise.ahk and double clicked on it. Then got the error below. Help please?

Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Thu Sep 06, 2007 6:15 am    Post subject: Reply with quote

Get the latest version of AutoHotkey. Optional ByRef parameters were added in v1.0.46.13.
Back to top
View user's profile Send private message Visit poster's website
Sridhar
Guest





PostPosted: Thu Sep 06, 2007 10:27 am    Post subject: Reply with quote

Thanks. Updating to the latest version fixed it. But this script doesn't work on Office 2007 suite apps' windows.
Back to top
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Thu Sep 06, 2007 1:02 pm    Post subject: Reply with quote

Surprised

Which feature doesn't work with Office 2007?

The taskbar is part of the shell, so it really should make no difference which app the taskbar button belongs to. (That is, if you're talking about the "hover over taskbar button to activate" feature, which is the main purpose of the script.)
Back to top
View user's profile Send private message Visit poster's website
user



Joined: 05 Oct 2006
Posts: 476

PostPosted: Tue Sep 18, 2007 10:22 am    Post subject: Reply with quote

any update please? Smile
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Tue Sep 18, 2007 10:55 am    Post subject: Reply with quote

Until I know exactly what doesn't work with Office 2007, there will be no update. Even then, I don't plan on getting Office 2007, so may not be able to fix it.
I wrote:
Which feature doesn't work with Office 2007?
Back to top
View user's profile Send private message Visit poster's website
user



Joined: 05 Oct 2006
Posts: 476

PostPosted: Tue Sep 18, 2007 3:24 pm    Post subject: Reply with quote

I experience troubles in xp, the script doesnt work at all, it only produces this effect:



(two tooltips)
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7295
Location: Australia

PostPosted: Wed Sep 19, 2007 1:39 am    Post subject: Reply with quote

That's the expected behaviour if the window is minimized. Try setting hover_task_min_info to 0 at the top of the script. I have already tested the script on XP with and without visual styles, so I know it works.

Btw, I seem to have mistaken you (user) for Sridhar. I apologise. Still, I don't see any need for an update beyond apparent Office 2007 compatibility.
Back to top
View user's profile Send private message Visit poster's website
user



Joined: 05 Oct 2006
Posts: 476

PostPosted: Wed Sep 19, 2007 11:49 pm    Post subject: Reply with quote

thanks it works now very well!

but I have noticed something:

I have touchpad and not conventional mouse

so I noticed that the script doesnt activate the window if I hover over the tab, UNLESS I remove the finger from the touchpad

in other words, what triggers the window activation, is not hovering over the tab, but the release of the touchpad (after hovering over the tab)

I dont know if this is intented and if this is better than activating with just hovering (and not having to release the touchpad)

it would be best to have another version of it that will work even if we dont release the touchpad to compare

thank you in advance
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
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