Feren6,希望没有压倒你,但是我曾经剪辑过这段文字,还没用过,希望对你有所帮助,尤其是HSHELL_ENDTASK。
记录的 wParam 值为:
1. HSHELL_WINDOWCREATED
2. HSHELL_WINDOWDESTROYED
3. HSHELL_ACTIVATESHELLWINDOW
4. HSHELL_WINDOWACTIVATED
5. HSHELL_GETMINRECT
6. HSHELL_REDRAW
7. HSHELL_TASKMAN
8. HSHELL_LANGUAGE
9. HSHELL_SYSMENU
10. HSHELL_ENDTASK
11. HSHELL_ACCESSIBILITYSTATE
12. HSHELL_APPCOMMAND
13. HSHELL_WINDOWREPLACED
14. HSHELL_WINDOWREPLACING
15. HSHELL_HIGHBIT
16. HSHELL_FLASH
17. HSHELL_RUDEAPPACTIVATED
lParam 的类型根据接收到的 wParam 的值而有所不同。对于大多数 wParam 值,lParam 是一个窗口句柄,可以在 AHK 的窗口命令中用作 ahk_id %lParam%。
一些想法:
每当窗口被最小化/最大化时,shell 都会接收 HSHELL_GETMINRECT(带有 shellhook 结构)。脚本可能会监视它以将窗口最小化到托盘。
当窗口被重绘时,shell 接收 HSHELL_REDRAW。脚本可以监视它以在其内容更改时激活窗口。
我尝试过,这里有一些例子:
实验一:
在 Windows XP 中,CTRL+ALT+DEL 会带来任务管理器。论坛已经看到一些帖子请求拒绝访问任务管理器的方法。
以下脚本在创建时几乎立即检测并关闭 Windows 任务管理器。
代码:
持久
SetBatchLines, -1
进程、优先级、高
桂 +LastFound
hWnd := WinExist()
DllCall("RegisterShellHookWindow", UInt,hWnd)
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage(MsgNum, "ShellMessage")
返回
ShellMessage(wParam,lParam){
如果(wParam = 1); HSHELL_WINDOWCREATED := 1
{
WinGetTitle,标题,ahk_id %lParam%
如果(标题=“Windows 任务管理器”)
{
WinClose, ahk_id %lParam%
;运行,Calc.exe;反而
}
}
}
实验 2:
Hooking Shell 消息提供了一种可靠的方法来跟踪上一个活动窗口。
请参阅:如何检索最后一个活动窗口?由 r0lZ
以下脚本切换活动窗口的 TopMost/TopLevel 样式 ( Always on Top On/OFF )。
代码:
持久
菜单、托盘、NoStandard
菜单、托盘、添加、切换 AOT、切换 AOT
菜单,托盘,添加,
菜单、托盘、添加、重新加载、退出脚本
菜单、托盘、添加、退出、退出脚本
菜单、托盘、提示、切换 AOT
菜单、托盘、默认、切换 AOT
桂 +LastFound
DllCall("RegisterShellHookWindow", UInt,WinExist())
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage(MsgNum, "ShellMessage")
LastActiveWindowID := WinActive("A")
返回; // 自动执行部分结束 //
ShellMessage(wParam, lParam) {
全局 LastActiveWindowID
If ( wParam = 4 And WinExist( "ahk_id " lParam ) ) { ; HSHELL_WINDOWACTIVATED = 4
LastActiveWindowID := lParam
}
}
切换AOT:
WinSet、AlwaysOnTop、切换、ahk_id %LastActiveWindowID%
返回
退出脚本:
DllCall("DeregisterShellHookWindow", UInt,hWnd) ;冗余,我猜!
IfEqual,A_ThisMenuItem,重新加载,重新加载
退出应用程序
返回
运行脚本。
单击目标窗口以将其聚焦。
双击脚本托盘图标。
目标窗口将在 TopMost 和 TopLevel 样式之间切换。
实验 3:
我有一个罗技多媒体键盘,但没有安装它附带的软件。我使用的是我自己的 OSD 脚本,它使用 VOLUME_UP /DN/MUTE 键作为热键来触发 SoundGet / SoundSet 命令的调整。
现在我发现,每当我按下多媒体键时,Shell 都会收到通知 (HSHELL_APPCOMMAND)。 lParam 的 HiWord 包含按下的 MM 键的值。所以我修改了我的 Volume Change OSD 脚本,让它在没有 HotKeys 或 SoundSet 命令的情况下工作。
代码:
桂,颜色,FFFFFF
Gui, -Caption +Border +AlwaysOnTop +ToolWindow +LastFound
hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage(MsgNum, "ShellMessage")
Gui, Add, Picture, x5 y5 w32 h32 Icon4 vIcon1, SndVol32.exe
Gui, Add, Picture, x5 y5 w32 h32 Icon5 vIcon2, SndVol32.exe
循环,25
Gui, Add, Text, x+3 w5 h32 隐藏边框 vText%A_Index% 0x4 ;
返回; // 自动执行部分结束 //
ShellMessage(wParam,lParam){
如果 ( wParam = 12 AND ( (lParam>>16) >= 8 OR (lParam>>16)
Loop, 25
IfLessOrEqual, A_Index, % Round(Volume/4), GuiControl, Show, Text%A_Index%
Else GuiControl, Hide, Text%A_Index%
IfEqual, Mute, On, GuiControl, Hide, Icon2
Else GuiControl, Show, Icon2
SetTimer, GuiEscape, 1234
} }
GuiEscape:
设置定时器,GuiEscape,关闭
贵,躲
简单地说,当 wParam 为 12 ( HSHELL_APPCOMMAND ) 时,lParam 的 HiWord 包含以下常量之一:
* APPCOMMAND_BROWSER_BACKWARD = 1
APPCOMMAND_BROWSER_FORWARD = 2
APPCOMMAND_BROWSER_REFRESH = 3
APPCOMMAND_BROWSER_STOP = 4
APPCOMMAND_BROWSER_SEARCH = 5
APPCOMMAND_BROWSER_FAVORITES = 6
APPCOMMAND_BROWSER_HOME = 7
APPCOMMAND_VOLUME_MUTE = 8
APPCOMMAND_VOLUME_DOWN = 9
APPCOMMAND_VOLUME_UP = 10
APPCOMMAND_MEDIA_NEXTTRACK = 11
APPCOMMAND_MEDIA_PREVIOUSTRACK = 12
APPCOMMAND_MEDIA_STOP = 13
APPCOMMAND_MEDIA_PLAY_PAUSE = 14
APPCOMMAND_LAUNCH_MAIL = 15
APPCOMMAND_LAUNCH_MEDIA_SELECT = 16
APPCOMMAND_LAUNCH_APP1 = 17
APPCOMMAND_LAUNCH_APP2 = 18
APPCOMMAND_BASS_DOWN = 19
APPCOMMAND_BASS_BOOST = 20
APPCOMMAND_BASS_UP = 21
APPCOMMAND_TREBLE_DOWN = 22
APPCOMMAND_TREBLE_UP = 23
APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24
APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25
APPCOMMAND_MICROPHONE_VOLUME_UP = 26
APPCOMMAND_HELP = 27
APPCOMMAND_FIND = 28
APPCOMMAND_NEW = 29
APPCOMMAND_OPEN = 30
APPCOMMAND_CLOSE = 31
APPCOMMAND_SAVE = 32
APPCOMMAND_PRINT = 33
APPCOMMAND_UNDO = 34
APPCOMMAND_REDO = 35
APPCOMMAND_COPY = 36
APPCOMMAND_CUT = 37
APPCOMMAND_PASTE = 38
APPCOMMAND_REPLY_TO_MAIL = 39
APPCOMMAND_FORWARD_MAIL = 40
APPCOMMAND_SEND_MAIL = 41
APPCOMMAND_SPELL_CHECK = 42
APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43
APPCOMMAND_MIC_ON_OFF_TOGGLE = 44
APPCOMMAND_CORRECTION_LIST = 45
实验 4:
在尝试研究和理解消息时,我编写了这个粗略的 Shell 间谍来监视 Shell 接收到的消息:
代码:
持久
菜单、托盘、添加
Menu,Tray,Add,&Show, GuiShow
菜单、托盘、默认、&显示
Gui, Font, s9, Courier New
Gui +ToolWindow +AlwaysOnTop +Resize +LastFound
hWnd := WinExist()
DllCall("RegisterShellHookWindow", UInt,hWnd)
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage(MsgNum, "ShellMessages")
GUI,添加,编辑,w512 h512 vMsgs hwndEditC +ReadOnly
Gui, Show, x10 y10, 壳牌间谍
消息名称 =
(
HSHELL_WINDOWCREATED
HSHELL_WINDOWDESTROYED
HSHELL_ACTIVATESHELLWINDOW
HSHELL_WINDOWACTIVATED
HSHELL_GETMINRECT
HSHELL_REDRAW
HSHELL_TASKMAN
HSHELL_LANGUAGE
HSHELL_SYSMENU
HSHELL_ENDTASK
HSHELL_ACCESSIBILITYSTATE
HSHELL_APPCOMMAND
HSHELL_WINDOWREPLACED
HSHELL_WINDOWREPLACING
HSHELL_HIGHBIT
HSHELL_FLASH
HSHELL_RUDEAPPACTIVATED
)
应用命令 =
(
APPCOMMAND_BROWSER_BACKWARD = 1
APPCOMMAND_BROWSER_FORWARD = 2
APPCOMMAND_BROWSER_REFRESH = 3
APPCOMMAND_BROWSER_STOP = 4
APPCOMMAND_BROWSER_SEARCH = 5
APPCOMMAND_BROWSER_FAVORITES = 6
APPCOMMAND_BROWSER_HOME = 7
APPCOMMAND_VOLUME_MUTE = 8
APPCOMMAND_VOLUME_DOWN = 9
APPCOMMAND_VOLUME_UP = 10
APPCOMMAND_MEDIA_NEXTTRACK = 11
APPCOMMAND_MEDIA_PREVIOUSTRACK = 12
APPCOMMAND_MEDIA_STOP = 13
APPCOMMAND_MEDIA_PLAY_PAUSE = 14
APPCOMMAND_LAUNCH_MAIL = 15
APPCOMMAND_LAUNCH_MEDIA_SELECT = 16
APPCOMMAND_LAUNCH_APP1 = 17
APPCOMMAND_LAUNCH_APP2 = 18
APPCOMMAND_BASS_DOWN = 19
APPCOMMAND_BASS_BOOST = 20
APPCOMMAND_BASS_UP = 21
APPCOMMAND_TREBLE_DOWN = 22
APPCOMMAND_TREBLE_UP = 23
APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24
APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25
APPCOMMAND_MICROPHONE_VOLUME_UP = 26
APPCOMMAND_HELP = 27
APPCOMMAND_FIND = 28
APPCOMMAND_NEW = 29
APPCOMMAND_OPEN = 30
APPCOMMAND_CLOSE = 31
APPCOMMAND_SAVE = 32
APPCOMMAND_PRINT = 33
APPCOMMAND_UNDO = 34
APPCOMMAND_REDO = 35
APPCOMMAND_COPY = 36
APPCOMMAND_CUT = 37
APPCOMMAND_PASTE = 38
APPCOMMAND_REPLY_TO_MAIL = 39
APPCOMMAND_FORWARD_MAIL = 40
APPCOMMAND_SEND_MAIL = 41
APPCOMMAND_SPELL_CHECK = 42
APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43
APPCOMMAND_MIC_ON_OFF_TOGGLE = 44
APPCOMMAND_CORRECTION_LIST = 45
)
返回
ShellMessages(wP,lP){
全球编辑C
全局 mVal := lP
GuiControlGet,消息
例程 := GetMessageName( wP )
IfEqual,Routine,, SetEnv, Routine, UNKNOWN
GuiControl,, Msgs, % Msgs "nn" 例程 " [" wP "]"
If IsLabel(例程)
GoSub,%例程%
ControlSend,, ^{End}, ahk_id %EditC%
}
GetMessageName(FieldN=0) {
全局消息名称
循环、解析、MsgNames、`n
IfEqual, A_Index, %FieldN%, 返回, A_LoopField
}
GetAppCommand(FieldN=0) {
全局 AppCommands
循环、解析、AppCommands、`n
IfEqual, A_Index, %FieldN%, 返回, A_LoopField
}
未知:
HSHELL_WINDOW创建:
HSHELL_WINDOWACTIVATED:
HSHELL_WINDOWDESTROYED:
HSHELL_REDRAW:
HSHELL_FLASH:
HSHELL_ENDTASK:
HSHELL_WINDOWREPLACING:
HSHELL_WINDOWREPLACED:
HSHELL_RUDEAPPACTIVATED:
WinGetTitle, 标题, ahk_id %mVal%
WinGetClass, 类, ahk_id %mVal%
GuiControlGet,消息
GuiControl,, 消息
, % Msgs "nnhWndt: " WinExist("ahk_id" mVal) "nTitlet: " Title "nClass`t: "类
返回
HSHELL_GETMINRECT:
返回
HSHELL_APP 命令:
GuiControlGet,消息
GuiControl,, Msgs, % Msgs " // " GetAppCommand( mVal >> 16 )
返回
Gui关闭:
Gui, 显示, 隐藏
返回
桂秀:
桂秀秀
返回
这并不详尽,但有助于了解这些东西的工作原理。
运行上述代码后,运行计算器并将其从标准模式更改为科学模式。
会发现计算器窗口被破坏并重新创建导致句柄发生变化。 (我不知道)
有趣的是,我发现每当窗口闪烁其标题栏/任务栏按钮时,Shell 都会收到一个未记录的 (AFAIK) 值 0x8006 ( 32774 )。以下代码激活了一个正在闪烁的窗口:(不确定它是否适用于所有人):
代码:
桂+LastFound
hWnd := WinExist() , DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage(MsgNum, "ShellMessage")
返回; // 自动执行部分结束 //
ShellMessage(wParam,lParam) {
如果(wParam = 0x8006); 0x8006 是 32774,如 Spy!
{
WinActivate, ahk_id %lParam%
}
}