smooth 发表于 2020-2-12 09:28:34

如何获取菜单项目的句柄以便触发动作?


#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
Local $hGUI = GUICreate('', 400, 400)
Local $idSetMenu = GUICtrlCreateMenu("设置[&S]", -1, 1)
Local $idTopItem = GUICtrlCreateMenuItem("窗口置顶", $idSetMenu)
GUICtrlSetState(-1, $GUI_CHECKED)
Local $idRepeatItem = GUICtrlCreateMenuItem("结果去重", $idSetMenu)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlCreateMenuItem("", $idSetMenu, 2)
Local $idFunctionItem = GUICtrlCreateMenuItem("功能设置", $idSetMenu)
GUISetState(@SW_SHOW)
WinSetOnTop($hGUI, "", 1)

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
While 1
        $Msg = GUIGetMsg()
        Switch $Msg
                Case -3
                        Exit
                Case $idTopItem
                        If BitAND(GUICtrlRead($idTopItem), $GUI_CHECKED) = $GUI_CHECKED Then
                                GUICtrlSetState($idTopItem, $GUI_UNCHECKED)
                                WinSetOnTop($hGUI, "", 0)
                        Else
                                GUICtrlSetState($idTopItem, $GUI_CHECKED)
                                WinSetOnTop($hGUI, "", 1)
                        EndIf
                Case $idRepeatItem
                        If BitAND(GUICtrlRead($idRepeatItem), $GUI_CHECKED) = $GUI_CHECKED Then
                                GUICtrlSetState($idRepeatItem, $GUI_UNCHECKED)
                        Else
                                GUICtrlSetState($idRepeatItem, $GUI_CHECKED)
                        EndIf
        EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
        Switch $lParam
                Case GUICtrlGetHandle($idRepeatItem)
                        ToolTip(GUICtrlGetHandle($idRepeatItem), 600, 600)
                        MsgBox(0,0,"???????", '', $hGUI)
        EndSwitch               
    Return $GUI_RUNDEFMSG
EndFunc

各位大神,我的目的是当点击菜单项目$idRepeatItem的时候,执行Msgbox(),可是现在不管点击哪个菜单项目,不知道为什么都会弹出Msgbox()呢?

smooth 发表于 2020-2-12 12:48:37

afan 发表于 2020-2-12 12:23
直接在主循环的 Case $idRepeatItem 处理不香么?还多此一举GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") … ...

A大,用GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") 主要是为了“实时”。

haijie1223 发表于 2020-2-12 09:52:36

我这里测试正常

haijie1223 发表于 2020-2-12 10:21:21

哦哦,理解错了。你要获取的是菜单的句柄,那么你应该用_GUICtrlMenu_GetMenu

smooth 发表于 2020-2-12 10:42:40

haijie1223 发表于 2020-2-12 10:21
哦哦,理解错了。你要获取的是菜单的句柄,那么你应该用_GUICtrlMenu_GetMenu

谢谢发哥。
我把GUICtrlGetHandle($idRepeatItem)改为_GUICtrlMenu_GetMenu($idRepeatItem),结果还是一样的,不管点击的哪个菜单,都会往下执行。而我想实现的是,点击菜单$idRepeatItem才往下执行。

floor6ggg 发表于 2020-2-12 10:46:50

试一下:注册事件更改一下:
Func WM_COMMAND($hWnd, $iMsg, $wParam, $ilParam)
$iIDFrom = BitAND($wParam, 0xFFFF);contril id
           Switch $iIDFrom
                   Case $idRepeatItem;GUICtrlGetHandle($idRepeatItem)
                        ToolTip(GUICtrlGetHandle($idRepeatItem), 600, 600)
                        MsgBox(0,0,"???????", '', $hGUI)                        
      EndSwitch
      Return
EndFunc   ;==>WM_COMMAND

floor6ggg 发表于 2020-2-12 10:51:10

应该不用句柄,直接control id匹配即可,control id从$wParam的低位值获得,…………没有动用 $lParam

haijie1223 发表于 2020-2-12 11:01:16

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
        #forceref $hWnd, $iMsg
        Local $hWndFrom, $iIDFrom, $iCode
        $hWndFrom = $lParam
        $iIDFrom = BitAND($wParam, 0xFFFF) ; Low Word
        $iCode = BitShift($wParam, 16) ; Hi Word
        Switch $iIDFrom
                Case $idTopItem
                       
                Case $idRepeatItem
                       
                Case $idFunctionItem
                       
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

smooth 发表于 2020-2-12 11:47:03

floor6ggg 发表于 2020-2-12 10:46
试一下:注册事件更改一下:

试了一下,不行的。

smooth 发表于 2020-2-12 11:48:41

本帖最后由 smooth 于 2020-2-12 11:50 编辑

haijie1223 发表于 2020-2-12 11:01
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
      #forceref $hWnd, $iMsg
      Local $hWndFrom, $iIDFrom ...
可以了,谢谢发哥。以下2行好像是不起作用的,测试了一下。

#forceref $hWnd, $iMsg

$hWndFrom = $lParam

afan 发表于 2020-2-12 12:23:47

直接在主循环的 Case $idRepeatItem 处理不香么?还多此一举GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") ……

haijie1223 发表于 2020-2-12 18:12:40

afan 发表于 2020-2-12 12:23
直接在主循环的 Case $idRepeatItem 处理不香么?还多此一举GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") … ...

楼主应该是为了增加代码的复杂性,这样看起来比较高级。

itsky2 发表于 2020-2-13 11:55:20

smooth 发表于 2020-2-12 12:48
A大,用GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") 主要是为了“实时”。

实际上你理解错了,GUIGetMsg只有收到消息的时候才会返回,而返回后在主循环中就立即开始Switch判断并执行操作,因此这也是“实时”的。而注册事件反而多了传入的变量等等导致的耗时。

smooth 发表于 2020-2-14 09:19:50

本帖最后由 smooth 于 2020-2-14 09:21 编辑

haijie1223 发表于 2020-2-12 18:12
楼主应该是为了增加代码的复杂性,这样看起来比较高级。
发哥,不是为了增加代码的复杂性。在Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)函数里,我还有其他代码,比如在input框输入后就自动返回结果,不用点击,也不用回车,只是我这里举例子的时候省略了。当然这并不影响在主循环里Case $idRepeatItem这个菜单,只是我觉得放到Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)函数里,比较统一。

smooth 发表于 2020-2-14 09:24:12

itsky2 发表于 2020-2-13 11:55
实际上你理解错了,GUIGetMsg只有收到消息的时候才会返回,而返回后在主循环中就立即开始Switch判断并执 ...

在主循环的GUIGetMsg(),能实时响应?比如在input框中输入数据,不用鼠标点击,不用回车,就能自动返回结果?怎么实现,没研究过。
页: [1] 2
查看完整版本: 如何获取菜单项目的句柄以便触发动作?