ScriptFans 发表于 2018-8-5 21:28:01

[已解决]请问如何响应WM_CLOSE消息

本帖最后由 ScriptFans 于 2018-8-6 17:34 编辑

是这样的,我不想用消息循环模式,想要把关闭窗口用事件响应的方式实现,测试代码如下:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$Form1 = GUICreate("Form1", 369, 222, 192, 124)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_CLOSE, "WM_CLOSE")

While 1
      ;$nMsg = GUIGetMsg()
      ;Switch $nMsg
      ;      Case $GUI_EVENT_CLOSE
      ;                Exit
      ;EndSwitch
      Sleep(10000)
WEnd

Func WM_CLOSE($a, $b, $c, $d)
      MsgBox(0,"","关闭")
      Exit
EndFunc
上面代码点击关闭没反应,不知该如何实现,请大家指教!

顺便再请教一句:发帖的时候我没找到怎么设置代码高亮

chzj589 发表于 2018-8-5 21:52:26


#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
$Form1 = GUICreate("Form1", 369, 222, 192, 124)
GUISetOnEvent($GUI_EVENT_CLOSE, "_CloseExit")
$Button1 = GUICtrlCreateButton("关闭", 300, 190, 60, 22, 0)
GUICtrlSetOnEvent($Button1, "_CloseExit")
GUISetState(@SW_SHOW)
While 1
        Sleep(10000)
WEnd
Func _CloseExit()
      MsgBox(0,"","关闭")
      Exit
EndFunc

ScriptFans 发表于 2018-8-5 21:59:00

chzj589 发表于 2018-8-5 21:52

#include
#include

抱歉,忘记说明了,我不想用GUICtrlSetOnEvent模式,这个模式是在是太容易出问题了,尤其是在多窗口的情况。我现在想把程序中所有事件响应用guiregistermsg()函数来实现,目前就差关闭窗口没能成功。
我测试过WM_DESDROY可以成功响应,但是WM_CLOSE就是不行。感谢回复,还请继续指教!

chzj589 发表于 2018-8-5 22:05:29

ScriptFans 发表于 2018-8-5 21:59
抱歉,忘记说明了,我不想用GUICtrlSetOnEvent模式,这个模式是在是太容易出问题了,尤其是在多窗口的情 ...

我己习惯用GUICtrlSetOnEvent模式,再多的窗口也没有出现问题。
用WM_CLOSE还不会。
期待高手

ScriptFans 发表于 2018-8-5 22:25:50

chzj589 发表于 2018-8-5 22:05
我己习惯用GUICtrlSetOnEvent模式,再多的窗口也没有出现问题。
用WM_CLOSE还不会。
期待高手

还是感谢,记得兄弟的出入库管理系统相当漂亮!

顽固不化 发表于 2018-8-5 23:32:50

我猜,WM_CLOSE是有窗口关闭时才会发出消息,窗口关闭了,程序也就执行完了,用户函数来不及处理。

ScriptFans 发表于 2018-8-6 08:31:29

本帖最后由 ScriptFans 于 2018-8-6 08:38 编辑

顽固不化 发表于 2018-8-5 23:32
我猜,WM_CLOSE是有窗口关闭时才会发出消息,窗口关闭了,程序也就执行完了,用户函数来不及处理。
这是我百度的:win32应用程序的完整退出过程:点击窗口右上角的关闭按钮,发送WM_CLOSE消息。此消息处理中调用DestroyWindow函数,发送WM_DESTROY消息。此消息处理中调用PostQuitMessage(0)函数,发送WM_QUIT消息到消息队列中。GetMessage捕获到WM_QUIT,返回0,退出循环(应用程序真正退出)。
我试过在消息循环中处理$GUI_EVENT_CLOSE,同时guiregister()注册WM_DESTROY,这样能够响应WM_DESTROY(手机回复,代码不便上),但此时窗口已经关闭了。我想在窗口关闭之前响应消息,应该还得是WM_CLOSE

顽固不化 发表于 2018-8-6 09:17:07

ScriptFans 发表于 2018-8-6 08:31
这是我百度的:win32应用程序的完整退出过程:点击窗口右上角的关闭按钮 ...

恩恩,明白,也许真的有bug。

kk_lee69 发表于 2018-8-6 13:06:05

這個方法呢??

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

Local $msg
GUICreate("My GUI")
GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")
GUISetState(@SW_SHOW)

While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()


Func On_WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)
    Local Const $SC_MOVE = 0xF010
    Local Const $SC_SIZE = 0xF000
    Local Const $SC_CLOSE = 0xF060

    Switch BitAND($wParam, 0xFFF0)
      Case $SC_MOVE
            ConsoleWrite("WM_Move detected" & @CRLF)
      Case $SC_SIZE
            ConsoleWrite("WM_Size detected" & @CRLF)
      Case $SC_CLOSE
            ConsoleWrite("WM_Close intercepted" & @CRLF)
            ;Exit
            Return -1
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>On_WM_SYSCOMMAND

ScriptFans 发表于 2018-8-6 15:00:07

本帖最后由 ScriptFans 于 2018-8-6 16:33 编辑

kk_lee69 发表于 2018-8-6 13:06
這個方法呢??

#include

感谢回复,兄弟的还是用到了消息循环,我本意就是想避开循环,全用guiregistermsg()来响应消息。当然有其他办法注册消息函数也可以。记得自带的_winapi有个shellhook函数(手机回复不便查)好像可以捕捉所有窗口的各类消息,没测试,晚上有空试试,但即使可以,我觉得这类方法也比单纯只处理自身窗口消息要更耗资源。
抱歉,刚才没仔细看代码,晚上我测试下WM_SYSCOMMAND的wParam有没有包含窗口关闭的信息。

kk_lee69 发表于 2018-8-6 16:57:38

ScriptFans 发表于 2018-8-6 15:00
感谢回复,兄弟的还是用到了消息循环,我本意就是想避开循环,全用guiregistermsg()来响应消息。当然有其 ...

真的不能理解??   
原文 我不想用消息循环模式,想要把关闭窗口用事件响应的方式实现

消息循環模式不就是
While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd
GUIDelete()

這段的東西 我沒有用啊

我明明 實現的是

Func On_WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)
    Local Const $SC_MOVE = 0xF010
    Local Const $SC_SIZE = 0xF000
    Local Const $SC_CLOSE = 0xF060
    Switch BitAND($wParam, 0xFFF0)
      Case $SC_MOVE
            ConsoleWrite("WM_Move detected" & @CRLF)
      Case $SC_SIZE
            ConsoleWrite("WM_Size detected" & @CRLF)
      Case $SC_CLOSE
            ConsoleWrite("WM_Close intercepted" & @CRLF)
            ;Exit
            Return -1
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>On_WM_SYSCOMMAND

只是我把離開 註解掉了

不就達成你要的嗎??

kk_lee69 发表于 2018-8-6 16:59:53

ScriptFans 发表于 2018-8-6 15:00
感谢回复,兄弟的还是用到了消息循环,我本意就是想避开循环,全用guiregistermsg()来响应消息。当然有其 ...

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

Local $msg
GUICreate("My GUI")
GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")
GUISetState(@SW_SHOW)

While 1
    $msg = GUIGetMsg()
        SLEEP(10)
WEnd
GUIDelete()


Func On_WM_SYSCOMMAND($hWnd, $msg, $wParam, $lParam)
    Local Const $SC_MOVE = 0xF010
    Local Const $SC_SIZE = 0xF000
    Local Const $SC_CLOSE = 0xF060

    Switch BitAND($wParam, 0xFFF0)
      Case $SC_MOVE
            ConsoleWrite("WM_Move detected" & @CRLF)
      Case $SC_SIZE
            ConsoleWrite("WM_Size detected" & @CRLF)
      Case $SC_CLOSE
            ConsoleWrite("WM_Close intercepted" & @CRLF)
            Exit
            Return -1
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc   ;==>On_WM_SYSCOMMAND

ScriptFans 发表于 2018-8-6 17:30:38

本帖最后由 ScriptFans 于 2018-8-6 17:32 编辑

kk_lee69 发表于 2018-8-6 16:59
#include
#include


刚百度了一下WM_SYSCOMMAND,正是我想要的,非常感谢兄弟的解答,原来点击窗口右上角那几个按钮的时候发送的是这个消息!一直在外面忙工作,没仔细琢磨代码,真是抱歉!
页: [1]
查看完整版本: [已解决]请问如何响应WM_CLOSE消息