星雨朝霞 发表于 2012-2-21 21:53:14

如何在系统菜单里添加菜单项和相应事件?

帮助中_GUICtrlMenu_GetSystemMenu()的例子可以在记事本的系统菜单中添加一个菜单项,

那如果响应它的点击事件?求例子

298311657 发表于 2012-2-21 22:55:10

GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")这里面响应系统菜单事件

298311657 发表于 2012-2-21 22:56:34

具体例子,参阅http://www.autoitx.com/thread-28035-1-1.html

gto250 发表于 2012-2-21 23:38:04

回复 2# 298311657

兄弟,你确定这样子就能响应非au3程序的自定义菜单项?

afan 发表于 2012-2-21 23:42:34

需要 Hook

风行者 发表于 2012-2-22 00:59:19

WM_SYSCOMMAND 消息即可,网页快捕源码里有例子(置顶功能)

pusofalse 发表于 2012-2-22 01:44:32

本帖最后由 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

haijie1223 发表于 2012-2-22 08:08:40

p版 太厉害学习学习。。。

星雨朝霞 发表于 2012-2-22 10:36:04

回复 7# pusofalse


    P大,你的例子好像是把事件写到内存中?
我想让此项目执行的事件为脚本中的一个自定义函数,该如何写?

星雨朝霞 发表于 2012-2-22 10:37:12

回复 2# 298311657


    我说的不是脚本自身的窗口哦.也可以?求例子.{:face (52):}

zldfsz 发表于 2012-2-22 12:02:42

试试,学习了

pusofalse 发表于 2012-2-22 18:17:09

#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

lfx99 发表于 2012-2-22 19:55:57

可惜无MsgSpy.au3文件。努力

星雨朝霞 发表于 2012-2-22 19:58:07

回复 12# pusofalse


    P侠V5.{:face (67):}
困扰了半年的问题终于解决....内牛满面.....

pusofalse 发表于 2012-2-22 20:36:50

本帖最后由 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
查看完整版本: 如何在系统菜单里添加菜单项和相应事件?