How to hook a window focused event in win7 - autohotkey

I want to turn off capslock when I switch to the mintty window. And according Autohotkey: Toggle caps lock on/off on activating certain windows I try to hook the focused event using autohotkey. But this does not work on my pc(win7-64bit).
How to do to fix this on win7, or is there a better way or workaround?
My code is exactly the same as the answer to the link I referenced:
#Persistent ; Don't close when the auto-execute ends
SetTitleMatchMode, 2 ; Partial title matching
WinGet, myHwnd, ID, AutoHotKeys; Get the handle to the your window
; Listen for activation messages to all windows
DllCall("CoInitialize", "uint", 0)
if (!hWinEventHook := DllCall("SetWinEventHook", "uint", 0x3, "uint", 0x3, "uint", 0, "uint", RegisterCallback("HookProc"), "uint", 0, "uint", 0, "uint", 0))
{
MsgBox, Error creating shell hook
Exitapp
}
;MsgBox, Hook made
;DllCall("UnhookWinEvent", "uint", hWinEventHook) ; Remove the message listening hook
return
; Handle the messages we hooked on to
HookProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime)
{
global myHwnd
static lastHwnd
WinGetTitle, title, ahk_id %hwnd%
if (hwnd == myHwnd) ; If our window was just activated
{
tooltip, Gained focus
}
else if (lastHwnd == myHwnd) ; If our window was just deactivated
{
tooltip, Lost focus
}
lastHwnd := hwnd
}
Note that I am trying to use a handle of the window of notepad to test the functionality. And if this works I will replace the 'notepad' to 'mintty'.
And the info in the panel of AHK is:
Script lines most recently executed (oldest first). Press [F5] to refresh. The seconds elapsed between a line and the one after it is in parentheses to the right (if not 0). The bottommost line's elapsed time is the number of seconds since it executed.
025: SetTitleMatchMode,2
026: WinGet,myHwnd,ID,AutoHotKeys; Get the handle to the your window
029: DllCall("CoInitialize", "uint", 0)
030: if (!hWinEventHook := DllCall("SetWinEventHook", "uint", 0x3, "uint", 0x3, "uint", 0, "uint", RegisterCallback("HookProc"), "uint", 0, "uint", 0, "uint", 0))
038: Return (1.28)
045: WinGetTitle,title,ahk_id %hwnd%
047: if (hwnd == myHwnd)
051: if (lastHwnd == myHwnd)
053: ToolTip,Lost focus (0.03)
054: }
056: lastHwnd := hwnd
057: } (0.05)
045: WinGetTitle,title,ahk_id %hwnd%
047: if (hwnd == myHwnd)
051: if (lastHwnd == myHwnd)
056: lastHwnd := hwnd
057: } (2.14)
Press [F5] to refresh.

I don't know if this is that you need.
I've used this code
#Persistent
SetTimer, testing,200
return
testing:
IfWinExist Calculadora
{
SetCapsLockState ,Off
}
else
{
SetCapsLockState ,On
}
return
When I open the Windows calc the CapsLock turns off and vice versa.
Greetings!

#Persistent
SetTitleMatchMode, 2 ; use RegEx for finer control
Loop
{
WinWaitActive, Notepad
{
WinGet, opVar, ID
CapsLockState := GetKeyState("CapsLock", "T")
SetCapsLockState, AlwaysOff ; or just "Off"
}
WinWaitNotActive, ahk_id %opVar%
SetCapsLockState, % CapsLockState ? "On" : "Off"
}

Related

ControlSend not sending to the non-topmost window

Is it possible to make ControlSend send / click to a background window?
This code finds a window by id / handler, but sends a click / keystroke only if the window is the topmost. ControlSend skips its action if the window is not topmost. ControlClick force brings window to top and then clicks.
#Singleinstance
DetectHiddenWindows, On
#SingleInstance Force
#MaxThreadsPerHotkey, 2
SendMode Input ; Recommended for new scripts
SetControlDelay -1
PostClick(x,y,win="A") {
lParam := x & 0xFFFF | (y & 0xFFFF) << 16
PostMessage, 0x201, , %lParam%, , %win% ;WM_LBUTTONDOWN
PostMessage, 0x202, , %lParam%, , %win% ;WM_LBUTTONUP
}
RunAsAdmin() {
Loop, %0% {
param := %A_Index% ; Fetch the contents of the variable whose name is contained in A_Index.
params .= A_Space . param
}
ShellExecute := A_IsUnicode ? "shell32\ShellExecute":"shell32\ShellExecuteA"
if not A_IsAdmin
{
If A_IsCompiled
DllCall(ShellExecute, uint, 0, str, "RunAs", str, A_ScriptFullPath, str, params , str, A_WorkingDir, int, 1)
Else
DllCall(ShellExecute, uint, 0, str, "RunAs", str, A_AhkPath, str, """" . A_ScriptFullPath . """" . A_Space . params, str, A_WorkingDir, int, 1)
ExitApp
}
}
RunAsAdmin()
F1::
Loop
{
; http://particle-clicker.web.cern.ch/particle-clicker/
WinGet, WinID, ID, Particle Clicker - Google Chrome
; Send keystrokes only if tab active and topmost, suspend if focus lost, continue when gain focue
; ControlSend, ahk_parent, {Space}, ahk_id %WinID%
; send clicks only if tab not mininised, if tab on background - force bring it to front
; ControlClick, x799 y449, ahk_id %WinID%
; same as above
; ControlClick, x799 y449, ahk_id %WinID%,,,,NA
; same as above
; Controlclick x799 y449,ahk_id %WinID%,,Left,1,NA
; same as above
PostClick(799,449,"Particle Clicker - Google Chrome")
sleep 1000
}
return
F12::ExitApp

AHK Opening last opened windows explorer window if active, else starting new

This code figures out the current explorer windows open,
I would like to open the first in the list, and if the list is empty open a
new explorer instead.
I hope to the open/activate the either window at the current mouse position
#e::
list := ""
numberOfwindows := ""
wins := ""
WinGet, id, list, ahk_class CabinetWClass ahk_exe explorer.exe
Loop, %id%
{
numberOfwindows := A_Index
this_ID := id%A_Index%
WinGetTitle, title, ahk_id %this_ID%
wins .= A_Index A_Space title ? A_Index A_Space title "`n" : ""
}
MsgBox, number of explorer windows = %numberOfwindows%`n`n%wins%
return
This solves it. - however it can be optimized, anyone have any suggestions ?
#e::
list := ""
numberOfwindows := ""
wins := ""
WinGet, id, list, ahk_class CabinetWClass ahk_exe explorer.exe
Loop, %id%
{
numberOfwindows := A_Index
this_ID := id%A_Index%
WinGetTitle, title, ahk_id %this_ID%
if (A_Index = 1) { ; if it's the first index of the loop
;MsgBox %title%
win = %title% ; store the title in " win "
}
wins .= A_Index A_Space title ?½½ A_Index A_Space title "`n" : ""
}
IfWinNotExist ahk_class CabinetWClass
{
Run C:\Windows\explorer.exe
win := File Explorer
WinWait, %win% ahk_class CabinetWClass
WinMove, mxpos_new , mypos_new
WinActivate
}
;MsgBox, number of explorer windows = %numberOfwindows%`n`n%wins%
; above msgbox displays number and the names of the windows.
;~ ; we now know the win
; and its title, exe and class.
; we want it's current position.
WinGetPos, X, Y, Width, Height,%win% ahk_class CabinetWClass
;MsgBox, %X%, %Y%, %Width%, %Height%
; and we want the mouse position.
CoordMode, Mouse, Screen ; Coordinates are relative to the desktop (entire screen).
MouseGetPos, mxpos , mypos,
;MsgBox, %mxpos%, %mypos%
mxpos_new := mxpos - (Width / 2)
mypos_new := mypos - (Height / 2)
;MsgBox, %mxpos% %mypos% %Width% %Height% %mxpos_new% %mypos_new%
; activate that specific window
WinWait, %win% ahk_class CabinetWClass
WinMove, mxpos_new , mypos_new
WinActivate
return

Autohotkey: Activate foremost of X monitor

How do I activate the foremost window in a given monitor? suppose I have two monitors, one with an editor, and one with different apps, such as chrome and slack. I want to bind a key that will activate the foremost window in monitor two, be it slack or chrome, and one for the editor, for easy manuvering.
The foremost window in a given monitor is the currently active window
or (if the currently active window is on the other monitor) the last active window of this monitor.
; activate the editor:
F1::
WinActivate, ahk_exe notepad.exe ; replace notepad with the ahk_exe of the editor
return
; activate the last active window in the right monitor:
F2::
WinGetPos, X,,,, A
If (X > 1920) ; replace 1920 with the width of the left monitor
return ; do nothing
; otherwise:
WinGet, id, list
Loop, %id%
{
this_ID := id%A_Index%
WinGet, exStyle, exStyle, ahk_id %this_ID%
If !(exStyle & 0x100)
continue
WinGetTitle, title, ahk_id %this_ID%
If (title = "")
continue
WinGetPos, X,,,, ahk_id %this_ID%
If (X > 1920) ; replace 1920 with the width of the left monitor
{
WinActivate, ahk_id %this_ID%
break
}
}
return

Resize window after taskbar hidden

Below hotkey script hides/displays taskbar when lWin&H is keyed :
LWin & h::
if toggle := !toggle
{
WinHide ahk_class Shell_TrayWnd
WinHide Start ahk_class Button
}
else
{
WinShow ahk_class Shell_TrayWnd
WinShow Start ahk_class Button
}
return
Script is taken from a comment at http://lifehacker.com/taskbar-control-hides-and-unhides-the-windows-taskbar-w-1573974951
But when the taskbar is hidden the space which occupied the taskbar is unusable : windows do not drag to this area, newly opened program do not occupy this space.
Can script be modified so that when taskbar is hidden the entire screen area is usable ?
Here is a way that sets the work area to include the taskbar space to.
LWin & h::
if toggle := !toggle
{
WinHide ahk_class Shell_TrayWnd
WinHide Start ahk_class Button
SysGet, Mon, Monitor
SetWorkArea(MonLeft, MonTop, MonRight, MonBottom)
}
else
{
WinShow ahk_class Shell_TrayWnd
WinShow Start ahk_class Button
SysGet, Mon, MonitorWorkArea
SetWorkArea(MonLeft, MonTop, MonRight, MonBottom)
}
return
SetWorkArea(left,top,right,bottom) ; set main monitor work area ; windows are not resized!
{
VarSetCapacity(area, 16)
NumPut(left, area, 0, "UInt") ; left
NumPut(top, area, 4, "UInt") ; top
NumPut(right, area, 8, "UInt") ; right
NumPut(bottom,area,12, "UInt") ; bottom
DllCall("SystemParametersInfo", "UInt", 0x2F, "UInt", 0, "UPtr", &area, "UInt", 0) ; SPI_SETWORKAREA
}
Hope it helps
Instead of using autohotkey I use this utility :
http://www.itsamples.com/taskbar-hider.html
This appears to work (just tested on Windows7) :
lWin & h::
;#NoEnv
#NoTrayIcon
;#SingleInstance force
DetectHiddenWindows, Off ;for IfWinExist
VarSetCapacity( APPBARDATA, 36, 0 )
;------------------------------------------------------------
; Fetch current hidden/showing status
IfWinNotExist, ahk_class Shell_TrayWnd
TaskbarAndStartToggleState = 0 ;Currently [color=darkred]hidden[/color] (not showing)
Else
TaskbarAndStartToggleState = 1 ;Currently [color=darkred]non-hidden[/color] (showing)
;------------------------------------------------------------
Gosub +z ;Toggle the taskbar/SM state
;------------------------------------------------------------
Exit
;------------------------------------------------------------
+z::
TaskbarAndStartToggleState := Func(TaskbarAndStartToggleState)
Return
Func(TaskbarAndStartToggleState)
{
Global APPBARDATA
If TaskbarAndStartToggleState = 0
{
NumPut( (ABS_ALWAYSONTOP := 0x2), APPBARDATA, 32, "UInt" ) ;Enable "Always on top" [color=darkred](& disable auto-hide)[/color]
DllCall( "Shell32.dll\SHAppBarMessage", "UInt", ( ABM_SETSTATE := 0xA ), "UInt", &APPBARDATA )
WinShow ahk_class Shell_TrayWnd
Return 1 ;Now showing
}
If TaskbarAndStartToggleState = 1
{
NumPut( ( ABS_AUTOHIDE := 0x1 ), APPBARDATA, 32, "UInt" ) ;Disable "Always on top" [color=darkred](& enable auto-hide to hide Start button)[/color]
DllCall( "Shell32.dll\SHAppBarMessage", "UInt", ( ABM_SETSTATE := 0xA ), "UInt", &APPBARDATA )
WinHide ahk_class Shell_TrayWnd
;WinHide ahk_class Shell_TrayWnd ;[color=darkred]don't need this 2nd one?[/color]
Return 0 ;Now hidden
}
}
return
Slightly modified from :
http://www.autohotkey.com/board/topic/25932-trying-to-toggle-autohide-taskbar-with-keystroke-in-vista/page-2
Update : This script causes unexpected behavior when using multiple desktops. The taskbar is hidden but when toggle to restore just windows icon is display. Hiding the taskbar and unhiding the taskbar in taskbar properties appears to fix this, but this makes the script unusable if using multiple desktops.

What to do when ControlSend or Send doesn't work?

I recently upgraded to Windows 8.1 x64, now script that i was using doesn't work anymore. That script would right click tray icon of a certain program than navigate to one of its options then click that option.
Here is the script:::
;#NoTrayIcon
DetectHiddenWindows, On
;Outlook on the Desktop--------------------------------------------------------------------------------------------------------------------------------
^1:: ;25,000$ Fine Tuned
Info := TrayIcons("OutlookDesktop.exe") ; OutlookDesktop.exe is the prog i tested with
StringSplit, TrayInfo, Info,|
PostMessage, TrayInfo1, TrayInfo2, 0x0205,, ahk_id %TrayInfo3% ; this is the right-click
Sleep 500
Send {Down 3}{Right}{Down 7}{Right}{Down 4}{Enter}
return
^2:: ;Projects
Info := TrayIcons("OutlookDesktop.exe") ; OutlookDesktop.exe is the prog i tested with
StringSplit, TrayInfo, Info,|
PostMessage, TrayInfo1, TrayInfo2, 0x0205,, ahk_id %TrayInfo3% ; this is the right-click
Sleep 500
Send {Down 3}{Right}{Down 7}{Right}{Down 1 4}{Enter}
return
^3:: ;Due This Week - unfinished
Info := TrayIcons("OutlookDesktop.exe") ; OutlookDesktop.exe is the prog i tested with
StringSplit, TrayInfo, Info,|
PostMessage, TrayInfo1, TrayInfo2, 0x0205,, ahk_id %TrayInfo3% ; this is the right-click
Sleep 500
Send {Down 3}{Right}{Down 7}{Right}{Down 2 4}{Enter}
return
^4:: ;To-do Bar Calendar View
Info := TrayIcons("OutlookDesktop.exe") ; OutlookDesktop.exe is the prog i tested with
StringSplit, TrayInfo, Info,|
PostMessage, TrayInfo1, TrayInfo2, 0x0205,, ahk_id %TrayInfo3% ; this is the right-click
Sleep 500
Send {Down 3}{Right}{Down 7}{Right}{Down 7 4}{Enter}
return
; Found and abused from
; http://www.autohotkey.com/forum/topic17314.html
; thx, Sean ... GREAT WORK!
TrayIcons(sExeName = "OutlookDesktop.exe")
{
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(btn, 20)
VarSetCapacity(nfo, 24)
VarSetCapacity(sTooltip, 128)
VarSetCapacity(wTooltip, 128 * 2)
SendMessage, 0x418, 0, 0, ToolbarWindow32, ahk_class Shell_TrayWnd
Loop, %ErrorLevel%
{
SendMessage, 0x417, A_Index - 1, pRB, ToolbarWindow32, ahk_class Shell_TrayWnd
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", pRB, "Uint", &btn, "Uint", 20, "Uint", 0)
iBitmap := NumGet(btn, 0), idn := NumGet(btn, 4), Statyle := NumGet(btn, 8)
dwData := NumGet(btn,12), iString := NumGet(btn,16)
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", dwData, "Uint", &nfo, "Uint", 24, "Uint", 0)
hWnd := NumGet(nfo, 0), uID := NumGet(nfo, 4)
nMsg := NumGet(nfo, 8)
WinGet, pid, PID, ahk_id %hWnd%
WinGet, sProcess, ProcessName, ahk_id %hWnd%
WinGetClass, sClass, ahk_id %hWnd%
If !sExeName || (sExeName = sProcess) || (sExeName = pid)
{
DllCall("ReadProcessMemory", "Uint", hProc, "Uint", iString
, "Uint", &wTooltip, "Uint", 128 * 2, "Uint", 0)
DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", wTooltip
, "int", -1, "str", sTooltip, "int", 128, "Uint", 0, "Uint", 0)
sTrayIcons .= nMsg "|" uID "|" hWnd
}
}
DllCall("VirtualFreeEx", "Uint", hProc, "Uint", pRB, "Uint", 0, "Uint", 0x8000)
DllCall("CloseHandle", "Uint", hProc)
Return sTrayIcons
}
;Outlook on the Desktop-----------------------END OF SCRIPT------------------------------------------------------------------------------
Now i googled some more and found this script:::
BlockInput, on
pos := Tray_Define("CCC.exe", "i")
Tray_Click(pos, "R")
WinWait, ahk_class #32768
; WinHide, ahk_class #32768 ;this and next line are to hide the menu.
; WinKill, ahk_class SysShadow
ControlSend,,{Down}{Down}{Down}{Down}{Down}{ENTER},ahk_class #32768
BlockInput, off
ExitApp
Interestingly enough, script is working perfectly on Catalyst Control Centar (CCC.exe) but not on that program i want it to work on, it successfully right clicks but sending control commands is not working. (Also have tried with just Send instead of ControlSend)
What do you guys think is the problem here, why are ControlSend and Send commands not working? What do you suggest that i try?
This is an partial answer:
Since Windows 7, AHK must be always run as administrator, otherwise it shows strange behavior (sometimes not listening to hotkeys, sometimes not sending keys).
Please post your point with BlockIntput into another answer.