如何在系统菜单里添加菜单项和相应事件?
帮助中_GUICtrlMenu_GetSystemMenu()的例子可以在记事本的系统菜单中添加一个菜单项,那如果响应它的点击事件?求例子 GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")这里面响应系统菜单事件 具体例子,参阅http://www.autoitx.com/thread-28035-1-1.html 回复 2# 298311657
兄弟,你确定这样子就能响应非au3程序的自定义菜单项? 需要 Hook WM_SYSCOMMAND 消息即可,网页快捕源码里有例子(置顶功能) 本帖最后由 pusofalse 于 2012-2-22 01:51 编辑
#include <GUIMenu.au3>
#include <Thread.au3>
Const $tagREMOTE_SYSCOMMAND = "ptr SetWindowLongW;ptr CallWindowProcW;ptr GetSystemMenu;ptr GetMenuStringW;ptr MessageBoxW;ptr wsprintfW;ptr WndProc;dword Breakpoint;wchar wzTitle;wchar wzText;ubyte ShellX"
$hWnd = WinGetHandle("")
If $hWnd = 0 Then
Run(@WindowsDir & "\notepad.exe")
$hWnd = WinWait("")
EndIf
$hMenu = _GUICtrlMenu_GetSystemMenu($hWnd)
If $hMenu = 0 Then Exit
_GUICtrlMenu_InsertMenuItem($hMenu, -1, "", 0)
_GUICtrlMenu_InsertMenuItem($hMenu, -1, "Hello", 0xF201)
$iProcessID = WinGetProcess($hWnd)
$hProcess = _RTOpenProcess($iProcessID)
$pBaseAddress = _RTVirtualAllocEx($hProcess, 4096)
$tBuffer = DllStructCreate($tagREMOTE_SYSCOMMAND)
$pBuffer = DllStructGetPtr($tBuffer)
DllStructSetData($tBuffer, "SetWindowLongW", _RTGetProcAddress("User32.dll", "SetWindowLongW"))
DllStructSetData($tBuffer, "CallWindowProcW", _RTGetProcAddress("User32.dll", "CallWindowProcW"))
DllStructSetData($tBuffer, "GetSystemMenu", _RTGetProcAddress("User32.dll", "GetSystemMenu"))
DllStructSetData($tBuffer, "GetMenuStringW", _RTGetProcAddress("User32.dll", "GetMenuStringW"))
DllStructSetData($tBuffer, "MessageBoxW", _RTGetProcAddress("User32.dll", "MessageBoxW"))
DllStructSetData($tBuffer, "wsprintfW", _RTGetProcAddress("User32.dll", "wsprintfW"))
DllStructSetData($tBuffer, "Breakpoint", 0xCCCCCCCC)
DllStructSetData($tBuffer, "wzTitle", "Hello")
DllStructSetData($tBuffer, "wzText", "You clicked ID 0x%08X.")
DllStructSetData($tBuffer, "ShellX", _GetShellX())
_RTWriteProcessMemory($hProcess, $pBaseAddress, $pBuffer, DllStructGetSize($tBuffer))
$hThread = _RTCreateRemoteThread($hProcess, $pBaseAddress + 0x80, $hWnd)
_RTWaitForObject($hThread)
_RTCloseHandle($hThread)
_RTCloseHandle($hProcess)
Func _GetShellX()
Local $bBinary = "0x558BEC53E8000000005B81EB890000008D83A8000000506AFCFF7508FF138943185B5DC20400CCCC558BEC53E8000000005B81EBB1000000817D0C12010000753AF7451000020000743181EC00040000568D742404FF75108D43405056FF531483C40C6A308D43205056FF7508FF531033C05E81C400040000EB12FF7514FF7510FF750CFF7508FF7318FF53045B5DC21000CCCC"
Return Binary($bBinary)
EndFunc ;==>_GetShellX
为了区分系统定义的命令ID,_GUICtrlMenu_InsertMenuItem函数中指定的ID的第9位必须为1,即合法的命令ID为 0x.....2..,0x.....3..,0x.....7..,0x.....E..等等,以下是汇编代码。00AD0080 55 push ebp ; 设置窗口过程
00AD0081 8BEC mov ebp, esp
00AD0083 53 push ebx
00AD0084 E8 00000000 call 00AD0089 ; 代码自定位
00AD0089 5B pop ebx
00AD008A 81EB 89000000 sub ebx, 89
00AD0090 8D83 A8000000 lea eax, dword ptr
00AD0096 50 push eax
00AD0097 6A FC push -4
00AD0099 FF75 08 push dword ptr
00AD009C FF13 call dword ptr ; SetWindowLongW
00AD009E 8943 18 mov dword ptr , eax
00AD00A1 5B pop ebx
00AD00A2 5D pop ebp
00AD00A3 C2 0400 retn 4
00AD00A6 CC int3
00AD00A7 CC int3
00AD00A8 55 push ebp ; 窗口过程
00AD00A9 8BEC mov ebp, esp
00AD00AB 53 push ebx
00AD00AC E8 00000000 call 00AD00B1
00AD00B1 5B pop ebx
00AD00B2 81EB B1000000 sub ebx, 0B1
00AD00B8 817D 0C 12010000 cmp dword ptr , 112 ; if MsgID = WM_SYSCOMAMND ...
00AD00BF 75 3A jnz short 00AD00FB
00AD00C1 F745 10 00020000 test dword ptr , 200 ; 测试标志位
00AD00C8 74 31 je short 00AD00FB
00AD00CA 81EC 00040000 sub esp, 400
00AD00D0 56 push esi
00AD00D1 8D7424 04 lea esi, dword ptr
00AD00D5 FF75 10 push dword ptr
00AD00D8 8D43 40 lea eax, dword ptr
00AD00DB 50 push eax
00AD00DC 56 push esi
00AD00DD FF53 14 call dword ptr ; wsprintfW
00AD00E0 83C4 0C add esp, 0C
00AD00E3 6A 30 push 30
00AD00E5 8D43 20 lea eax, dword ptr
00AD00E8 50 push eax
00AD00E9 56 push esi
00AD00EA FF75 08 push dword ptr
00AD00ED FF53 10 call dword ptr ; MessageBoxW
00AD00F0 33C0 xor eax, eax
00AD00F2 5E pop esi
00AD00F3 81C4 00040000 add esp, 400
00AD00F9 EB 12 jmp short 00AD010D
00AD00FB FF75 14 push dword ptr
00AD00FE FF75 10 push dword ptr
00AD0101 FF75 0C push dword ptr
00AD0104 FF75 08 push dword ptr
00AD0107 FF73 18 push dword ptr
00AD010A FF53 04 call dword ptr ; CallWindowProcW
00AD010D 5B pop ebx
00AD010E 5D pop ebp
00AD010F C2 1000 retn 10
00AD0112 CC int3
00AD0113 CC int3 p版 太厉害学习学习。。。 回复 7# pusofalse
P大,你的例子好像是把事件写到内存中?
我想让此项目执行的事件为脚本中的一个自定义函数,该如何写? 回复 2# 298311657
我说的不是脚本自身的窗口哦.也可以?求例子.{:face (52):} 试试,学习了 #include <MsgSpy.au3>
Const $WM_SYSCOMAMND = 0x112
$hWnd = WinGetHandle("")
If $hWnd = 0 Then
Run(@WindowsDir & "\notepad.exe")
$hWnd = WinWait("")
EndIf
$hMenu = _GUICtrlMenu_GetSystemMenu($hWnd)
If $hMenu = 0 Then Exit
_GUICtrlMenu_InsertMenuItem($hMenu, -1, "", 0)
_GUICtrlMenu_InsertMenuItem($hMenu, -1, "Hello", 0xF201)
_GUICtrlMenu_InsertMenuItem($hMenu, -1, "Test", 0xF202)
_SPY_InitLibrary()
_SPY_ListenPort($SPY_OBJECT_WINDOW)
$hCallBack = DllCallBackRegister("_SpyMsgHandler", "none", "ptr;long;ptr;hwnd;long;wparam;lparam;lresult")
$pCallBack = DllCallBackGetPtr($hCallBack)
Local $aMsg = [$WM_SYSCOMAMND]
$pMsgFilter = _SPY_CreateMsgFilter($aMsg, $SPY_MSG_OK)
$pObject = _SPY_CreateObject($hWnd, $pCallBack, $pMsgFilter, 0)
_SPY_CreateChannel($pObject)
_SPY_SignalObject($pObject)
HotKeySet("!{esc}", "_OnExitFreeObject")
While 1
Sleep(1000)
WEnd
Func _SpyMsgHandler($pObject, $iObjectType, $pContext, $hWnd, $iMsg, $iwParam, $ilParam, $iResult)
If $iMsg = $WM_SYSCOMAMND Then
Switch $iwParam
Case 0xF201 To 0xF202
MsgBox(48, "Hello", StringFormat("You clicked ID 0x%08X.", $iwParam), 0, $hWnd)
EndSwitch
EndIf
EndFunc ;==>_SpyMsgHandler
Func _OnExitFreeObject()
_SPY_UnsignalObject($pObject)
_SPY_CloseChannel($pObject)
_SPY_CloseObject($pObject)
DllCallBackFree($hCallBack)
Exit
EndFunc ;==>_OnExitFreeObject 可惜无MsgSpy.au3文件。努力 回复 12# pusofalse
P侠V5.{:face (67):}
困扰了半年的问题终于解决....内牛满面..... 本帖最后由 pusofalse 于 2012-2-22 20:39 编辑
将 _SpyMsgHandler函数中的Switch $iwParam ... 改成 If BitAND($iwParam, 0x200) Then ...,判断wParam参数的标志位。系统定义的命令ID都是 0xF0XX或0xF1XX,第9位都是0,BitAND($iwParam, 0x200) 如果第9位(以第0位为基始)不为0,则说明是Au3进程添加的菜单项。
页:
[1]
2