1
votes

I want to write a script that will turn on caps lock when I activate a window containing particular keyword in its title(like SQL). I also want the caps lock to be turned off when I switch to a window whose title does not contain any of the keywords that I have specified.

How can I do it? I have considered #Persistent with a timer to periodically check active window. But, I think there should be a better way.

6

6 Answers

2
votes

check answers at: http://www.reddit.com/r/AutoHotkey/comments/1qjf83/force_specific_program_to_use_caps/. Especially G33kDude's answer. It's a clever and efficient solution: check of current window is binded only to windows activation.

=======================

Edit: Code inserted below. Please note that it's not a complete solution, you'll need to make some edits for your needs. Not a big ones, though.

#Persistent ; Don't close when the auto-execute ends

SetTitleMatchMode, 2 ; Partial title matching
WinGet, myHwnd, ID, Notepad ; 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
}
2
votes

If you want to do this without using SetTimer, the best way would be to use context-sensitive hotkeys. For Example:

SetTitleMatchMode, 2

#If WinActive("SQL") or WinActive("Notepad")
    a::A
    b::B
    c::C
    d::D
    e::E
    ;; etc.

You could also use the WinActive function with Window Groups instead of the title if you wanted to avoid a very long #If line.

EDIT: Case-Insensitive Example

SetTitleMatchMode, Regex

GroupAdd, Editor, (?i).*sql ; Regular expression for window title
GroupAdd, Editor, (?i).*ahk

#IfWinActive ahk_group Editor
    a::A
    b::B
    c::C
    d::D
    e::E
    ;; etc.
2
votes

Since you have a Autoit in your tag, here is how it is done easy in autoit.

Opt("SendCapslockMode", 0)

While 1

    Sleep(200)
    $title = WinGetTitle("", ""); will get the title of the active window

    If StringInStr($title, "sql") Then
        Send("{CAPSLOCK ON}")
    Else
        Send("{CAPSLOCK OFF}")
    EndIf

WEnd
1
votes

Milos' answer is quite straight forward, but it misses a vital point. You need to set SendCapslockMode to 0. Else the effect of the Send command will be useless, because after the command the original state will be restored.

The next thing is, you don't need to use an infinite loop with a Sleep which will execute the complete loop body every few milliseconds, but you can wait for the active window to not be active any more, which is less CPU intensive. So a fully working solution in AutoIt is:

Opt("SendCapslockMode", 0)

While True
   $win = WinGetHandle("[ACTIVE]")

   If StringInStr(WinGetTitle($win), "sql") Then
      Send("{CAPSLOCK ON}")
   Else
      Send("{CAPSLOCK OFF}")
   EndIf

   WinWaitNotActive($win)
WEnd
0
votes
#Persistent

SetTitleMatchMode, 2   ; use RegEx for finer control

Loop
{
    WinWaitActive, Notepad
    {
        WinGet, opVar, ID
        SetCapsLockState, On
    }

    WinWaitNotActive, ahk_id %opVar%
        SetCapsLockState, Off
}
0
votes
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.


; This script solves the problem of forgetting to turn on or off the capslock when using specific programs
; I for one ALWAYS use capital letters when typing things in CAD. My problem was when switching to another
; program, usually e-mail, I'd start typing and then have to erase it. Problem solved!

; The beauty of this script is that you don't lose the ability to manually turn the capslock on or off 
; My first few interations of this script would turn it on when in the CAD window but then
; I'd never be able to turn it on wihtout it being forced off again.


Loop    {

state := GetKeyState("Capslock", "T")        ; check toggle state, save in variable 'state'

if state = 0
    status = Off                ; this block converts the 1 or 0 of variable 'state'
if state = 1                    ; into the word ON or OFF and stores it in variable 'status'
    status = On


Beginsub:

WinGetTitle, Title, A                ; retreive current window title, store in Title


if title contains AutoCAD 2012            ; if title contains "AutoCAD" turn on capslock
                        ; then go back to the BeginSub subroutine and see if the title 
{    SetCapsLockState, on            ; still matches "AutoCAD 2012" if it does not...\/\/\/
    goto, BeginSub
            }

SetCapsLockState, %status%            ; ...Put caps lock back to the state it was when we started.

                        ; 'SetCapsLockState'  doesn't recognize a 1/0 variable
                        ; therefore the use of 'status' and ON/OFF words

Sleep, 1000                    ; only check every second


}