xyhqqaa 发表于 2021-11-30 00:38:38

关于父子窗口的消息传递的问题

求教大佬,最近测试一个父子窗口例子。
发现个问题,界面1与界面2同时打开的时候,按钮弹窗正常,但是先打开界面1关闭后,再打开界面2,按钮弹窗就异常了~~,感觉是$WM_COMMAND消息有问题,但是不知道哪错了- -!!!




#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global $Main_Form,$MainButton1,$ck_Form,$Button1,$Button2,$ck_in_Form,$ck_in_ok,$ck_in_esc,$ck_out_Form,$ck_out_ok,$ck_out_esc

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")

main()
Do
        Sleep(10)
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func main();父界面
$Main_Form = GUICreate("父界面", 556, 310, -1, -1)
$MainButton1 = GUICtrlCreateButton("子界面", 212, 80, 75, 25)
GUISetState(@SW_SHOW,$Main_Form)
EndFunc

Func ck();子界面
$ck_Form = GUICreate("子界面", 456, 210, -1, -1)
$Button1 = GUICtrlCreateButton("界面1", 72, 80, 75, 25)
$Button2 = GUICtrlCreateButton("界面2", 232, 80, 75, 25)
GUISetState(@SW_SHOW,$ck_Form)
EndFunc

Func ck_in();界面1
        $ck_in_Form = GUICreate("界面1", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW,$ck_Form)
        $ck_in_ok = GUICtrlCreateButton("入库",12, 38, 83, 41)
        $ck_in_esc = GUICtrlCreateButton("取消", 12,88, 83, 41)
        GUISetState(@SW_SHOW,$ck_in_Form)
EndFunc   ;==>ck_Inventory_manager_in

Func ck_out();界面2
        $ck_out_Form = GUICreate("界面2", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW,$ck_Form)
        $ck_out_ok = GUICtrlCreateButton("出库", 12, 38, 83, 41)
        $ck_out_esc = GUICtrlCreateButton("取消", 12, 88, 83, 41)
        GUISetState(@SW_SHOW,$ck_out_Form)
EndFunc   ;==>ck_Inventory_manager_in

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) ;感觉是这边有问题,但是不太清楚,求有时间的大佬解析下。
        Switch $hWnd
                Case $Main_Form,$ck_Form,$ck_in_Form,$ck_out_Form ;主界面
                ck_Event_COMMAND($hWnd, BitAND($wParam, 0x0000FFFF), BitShift($wParam, 16), $lParam)
        EndSwitch
        Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND


Func ck_Event_COMMAND($hWnd, $iControl, $iMsg, $ilParam)
        Switch $iControl
                Case $MainButton1
                        ;GUISetState(@SW_HIDE, $main_Form)
                        ck()
                Case $Button1
                        ck_in()
                Case $Button2
                        ck_out()
                       
                Case $ck_in_ok
                        MsgBox("", "", "入库")
                Case $ck_out_ok
                        MsgBox("", "", "出库")
                Case $ck_in_esc;
                        MsgBox("", "", "入库退出")
                        GUIDelete($ck_in_Form)
                        WinActivate("子界面")
                Case $ck_out_esc
                        MsgBox("", "", "出库退出")
                        GUIDelete($ck_out_Form)
                        WinActivate("子界面")
        EndSwitch
EndFunc   ;==>ck_Inventory_manager_Event_COMMAND


Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
        Local $SC_CLOSE = 0xF060
        Local $nID = BitAND($wParam, 0x0000FFFF)
        Switch $nID
                Case $SC_CLOSE
                        If $hWnd = $Main_Form Then
                                Exit
                        Else
                                GUIDelete($hWnd)
                        EndIf
        EndSwitch
EndFunc   ;==>WM_SYSCOMMAND




chzj589 发表于 2021-11-30 08:37:31

我测试没问题。
>运行 AU3Check (3.3.14.2) 检查代码.参数: D:\AutoIt3au3 文件: D:\AU3调试\ListView例子资料\关于父子窗口的消息传递.au3
+>08:34:32 AU3Check 语法检查结束.rc: 0
>运行:D:\AutoIt3\autoit3_x64.exe(3.3.14.2), 脚本: D:\AutoIt3\autoit3_x64.exe "D:\AU3调试\ListView例子资料\关于父子窗口的消息传递.au3"
Win7_64系统

tubaba 发表于 2021-11-30 10:18:26

像你这种动态创建窗口及控件的话,操作不应使用控件ID,而应该用控件句柄。控件ID一般是根据控件创建顺序依次+1,而你界面1和界面2如果创建顺序不同,会引起控件ID发生变化。如果界面1未创建,而先创建了界面2,界面2内的控件ID就变成了你原本期望界面1创建的控件ID。

两种解决办法:
1。不要动态创建窗口,在程序开始时就创建好所有要使用的窗口及控件,在后续处理时,显隐相应窗口,这样控件ID就不会发生变化。
2。动态创建窗口,使用句柄来操作控件。

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global $Main_Form,$MainButton1,$ck_Form,$Button1,$Button2,$ck_in_Form,$ck_in_ok,$ck_in_esc,$ck_out_Form,$ck_out_ok,$ck_out_esc
Global $hMainButton1, $hButton1, $hButton2, $hck_in_ok, $hck_in_esc, $hck_out_ok,$hck_out_esc


GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")

main()
Do
      Sleep(10)
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func main();父界面
$Main_Form = GUICreate("父界面", 556, 310, -1, -1)
$MainButton1 = GUICtrlCreateButton("子界面", 212, 80, 75, 25)
$hMainButton1 = GUICtrlGetHandle($MainButton1)
GUISetState(@SW_SHOW,$Main_Form)
EndFunc

Func ck();子界面
$ck_Form = GUICreate("子界面", 456, 210, -1, -1)
$Button1 = GUICtrlCreateButton("界面1", 72, 80, 75, 25)
$hButton1 = GUICtrlGetHandle($Button1)
$Button2 = GUICtrlCreateButton("界面2", 232, 80, 75, 25)
$hButton2 = GUICtrlGetHandle($Button2)
GUISetState(@SW_SHOW,$ck_Form)
EndFunc

Func ck_in();界面1
      $ck_in_Form = GUICreate("界面1", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW,$ck_Form)
      $ck_in_ok = GUICtrlCreateButton("入库",12, 38, 83, 41)
                $hck_in_ok = GUICtrlGetHandle($ck_in_ok)
      $ck_in_esc = GUICtrlCreateButton("取消", 12,88, 83, 41)
                $hck_in_esc = GUICtrlGetHandle($ck_in_esc)
      GUISetState(@SW_SHOW,$ck_in_Form)
EndFunc   ;==>ck_Inventory_manager_in

Func ck_out();界面2
      $ck_out_Form = GUICreate("界面2", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW,$ck_Form)
      $ck_out_ok = GUICtrlCreateButton("出库", 12, 38, 83, 41)
                $hck_out_ok = GUICtrlGetHandle($ck_out_ok)
      $ck_out_esc = GUICtrlCreateButton("取消", 12, 88, 83, 41)
                $hck_out_esc = GUICtrlGetHandle($ck_out_esc)
      GUISetState(@SW_SHOW,$ck_out_Form)
EndFunc   ;==>ck_Inventory_manager_in

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) ;感觉是这边有问题,但是不太清楚,求有时间的大佬解析下。
      Switch $hWnd
                Case $Main_Form,$ck_Form,$ck_in_Form,$ck_out_Form ;主界面
                ck_Event_COMMAND($hWnd, BitAND($wParam, 0x0000FFFF), BitShift($wParam, 16), $lParam)
      EndSwitch
      Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND


Func ck_Event_COMMAND($hWnd, $iControl, $iMsg, $ilParam)
      Switch $ilParam
                Case $hMainButton1
                        ;GUISetState(@SW_HIDE, $main_Form)
                        ck()
                Case $hButton1
                        ck_in()
                Case $hButton2
                        ck_out()
                        
                Case $hck_in_ok
                        MsgBox("", "", "入库")
                Case $hck_out_ok
                        MsgBox("", "", "出库")
                Case $hck_in_esc;
                        MsgBox("", "", "入库退出")
                        GUIDelete($ck_in_Form)
                        WinActivate("子界面")
                Case $hck_out_esc
                        MsgBox("", "", "出库退出")
                        GUIDelete($ck_out_Form)
                        WinActivate("子界面")
      EndSwitch
EndFunc   ;==>ck_Inventory_manager_Event_COMMAND


Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
      Local $SC_CLOSE = 0xF060
      Local $nID = BitAND($wParam, 0x0000FFFF)
      Switch $nID
                Case $SC_CLOSE
                        If $hWnd = $Main_Form Then
                              Exit
                        Else
                              GUIDelete($hWnd)
                        EndIf
      EndSwitch
EndFunc   ;==>WM_SYSCOMMAND

afan 发表于 2021-11-30 13:19:19

这种含子窗口的操作使用事件模式比较方便,当然习惯消息循环模式也可以直接在主循环中处理。对于这种基本操作,无需注册系统消息。
#include <WindowsConstants.au3>

Global $Main_Form, $MainButton1, $ck_Form = -1, $Button1, $Button2, $ck_in_Form = -1, $ck_in_ok, $ck_in_esc, $ck_out_Form = -1, $ck_out_ok, $ck_out_esc

main()

Local $aiMSG
While 1
        $aiMSG = GUIGetMsg(1)
        Switch $aiMSG
                Case $Main_Form
                        Switch $aiMSG
                                Case -3
                                        Exit
                                Case $MainButton1
                                        ck()
                        EndSwitch

                Case $ck_Form
                        Switch $aiMSG
                                Case -3
                                        GUISetState(@SW_HIDE, $ck_Form)
                                Case $Button1
                                        ck_in()
                                Case $Button2
                                        ck_out()
                        EndSwitch

                Case $ck_in_Form
                        Switch $aiMSG
                                Case -3, $ck_in_esc
                                        GUISetState(@SW_HIDE, $ck_in_Form)
                                Case $ck_in_ok
                                        MsgBox("", "", "入库")

                        EndSwitch

                Case $ck_out_Form
                        Switch $aiMSG
                                Case -3, $ck_out_esc
                                        GUISetState(@SW_HIDE, $ck_out_Form)
                                Case $ck_out_ok
                                        MsgBox("", "", "出库")

                        EndSwitch
        EndSwitch
WEnd

Func main();父界面
        $Main_Form = GUICreate("父界面", 556, 310, -1, -1)
        $MainButton1 = GUICtrlCreateButton("子界面", 212, 80, 75, 25)
        GUISetState(@SW_SHOW, $Main_Form)
EndFunc   ;==>main

Func ck();子界面
        If IsHWnd($ck_Form) Then Return GUISetState(@SW_SHOW, $ck_Form)
        $ck_Form = GUICreate("子界面", 456, 210, -1, -1)
        $Button1 = GUICtrlCreateButton("界面1", 72, 80, 75, 25)
        $Button2 = GUICtrlCreateButton("界面2", 232, 80, 75, 25)
        GUISetState(@SW_SHOW, $ck_Form)
EndFunc   ;==>ck

Func ck_in();界面1
        If IsHWnd($ck_in_Form) Then Return GUISetState(@SW_SHOW, $ck_in_Form)
        $ck_in_Form = GUICreate("界面1", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW, $ck_Form)
        $ck_in_ok = GUICtrlCreateButton("入库", 12, 38, 83, 41)
        $ck_in_esc = GUICtrlCreateButton("取消", 12, 88, 83, 41)
        GUISetState(@SW_SHOW, $ck_in_Form)
EndFunc   ;==>ck_in

Func ck_out();界面2
        If IsHWnd($ck_out_Form) Then Return GUISetState(@SW_SHOW, $ck_out_Form)
        $ck_out_Form = GUICreate("界面2", 172, 296, -1, -1, $WS_SYSMENU, $WS_EX_APPWINDOW, $ck_Form)
        $ck_out_ok = GUICtrlCreateButton("出库", 12, 38, 83, 41)
        $ck_out_esc = GUICtrlCreateButton("取消", 12, 88, 83, 41)
        GUISetState(@SW_SHOW, $ck_out_Form)
EndFunc   ;==>ck_out

xyhqqaa 发表于 2021-11-30 20:21:45

tubaba 发表于 2021-11-30 10:18
像你这种动态创建窗口及控件的话,操作不应使用控件ID,而应该用控件句柄。控件ID一般是根据控件创建顺序依 ...

感谢大佬在如此卡顿的情况下,还给予解答~~明白了!!:face (31):

xyhqqaa 发表于 2021-11-30 20:25:37

本帖最后由 xyhqqaa 于 2021-11-30 20:31 编辑

afan 发表于 2021-11-30 13:19
这种含子窗口的操作使用事件模式比较方便,当然习惯消息循环模式也可以直接在主循环中处理。对于这种基本操 ...
感谢A版的回复。。。最近论坛这么卡都能回复,万分感谢,您的思路方法我再学习下~~~回复不易~~:face (36):

xyhqqaa 发表于 2021-11-30 20:29:12

chzj589 发表于 2021-11-30 08:37
我测试没问题。
>运行 AU3Check (3.3.14.2) 检查代码.参数: D:\AutoIt3au3 文件: D:\AU3调试\ListView ...

感谢回复,不过您这边需要多点几次就会出现问题,大致如tu大佬所说。我琢磨好几天,大致猜得到,但是还是听完大佬的解释才清楚。

afan 发表于 2021-11-30 21:57:08

xyhqqaa 发表于 2021-11-30 20:25
感谢A版的回复。。。最近论坛这么卡都能回复,万分感谢,您的思路方法我再学习下~~~回复不易~~:face (36) ...

确实很卡,不过你的问题贴描述很到位、图文并茂、精简且可重现问题的代码,再卡都要助推一把~

xyhqqaa 发表于 2021-12-1 21:37:11

afan 发表于 2021-11-30 21:57
确实很卡,不过你的问题贴描述很到位、图文并茂、精简且可重现问题的代码,再卡都要助推一把~

:face (27):说的我都不意思了。感谢A版的代码~~~学习ing
页: [1]
查看完整版本: 关于父子窗口的消息传递的问题