【发布时间】:2017-06-16 04:35:04
【问题描述】:
我想编写一个脚本,当我激活标题中包含特定关键字的窗口(如 SQL)时,该脚本将打开大写锁定。当我切换到标题不包含我指定的任何关键字的窗口时,我还希望关闭大写锁定。
我该怎么做?我考虑过#Persistent 有一个定时器来定期检查活动窗口。但是,我认为应该有更好的方法。
【问题讨论】:
标签: autohotkey
我想编写一个脚本,当我激活标题中包含特定关键字的窗口(如 SQL)时,该脚本将打开大写锁定。当我切换到标题不包含我指定的任何关键字的窗口时,我还希望关闭大写锁定。
我该怎么做?我考虑过#Persistent 有一个定时器来定期检查活动窗口。但是,我认为应该有更好的方法。
【问题讨论】:
标签: autohotkey
查看答案:http://www.reddit.com/r/AutoHotkey/comments/1qjf83/force_specific_program_to_use_caps/。特别是 G33kDude 的回答。这是一个聪明而有效的解决方案:当前窗口的检查只绑定到窗口激活。
=========================
编辑:下面插入的代码。 请注意,这不是一个完整的解决方案,您需要根据需要进行一些编辑。不过不是很大。
#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
}
【讨论】:
如果您想在不使用SetTimer 的情况下执行此操作,最好的方法是使用context-sensitive 热键。例如:
SetTitleMatchMode, 2
#If WinActive("SQL") or WinActive("Notepad")
a::A
b::B
c::C
d::D
e::E
;; etc.
如果您想避免很长的 #If 行,也可以使用 WinActive 函数和 Window Groups 而不是标题。
编辑:不区分大小写的示例
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.
【讨论】:
由于您的标签中有 Autoit,因此在 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
【讨论】:
Milos' 的回答非常直截了当,但它忽略了一个关键点。您需要将SendCapslockMode 设置为0。否则Send命令的效果是没有用的,因为命令执行后会恢复原来的状态。
接下来,您不需要使用带有Sleep 的无限循环,它将每隔几毫秒执行一次完整的循环主体,但您可以等待活动窗口不再处于活动状态,这CPU 密集度较低。所以 AutoIt 中一个完全有效的解决方案是:
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
【讨论】:
#Persistent
SetTitleMatchMode, 2 ; use RegEx for finer control
Loop
{
WinWaitActive, Notepad
{
WinGet, opVar, ID
SetCapsLockState, On
}
WinWaitNotActive, ahk_id %opVar%
SetCapsLockState, Off
}
【讨论】:
#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
}
【讨论】: