Programming 版 (精华区)
发信人: JJason (总统~~), 信区: Programming
标 题: [合集]请问如何捕获关机事件??
发信站: 哈工大紫丁香 (2003年03月20日17:10:04 星期四), 站内信件
────────────────────────────────────────
fenxuan (风轩小筑) 于 2003年02月28日10:16:51 星期五 说道:
希望在程序中实现当用户点击开始菜单下面的“关机...”时程序能够给出提示,然后再
响应关机与否。
语言打算用VB。
────────────────────────────────────────
crack (空气@浴火重生) 于 2003年02月28日10:45:12 星期五 说道:
系统关机时要关闭应用程序,你只需要处理你的应用程序关闭事件即可。
────────────────────────────────────────
valley (天音) 于 2003年02月28日13:23:28 星期五 说道:
这样好像不行。一旦操作系统通知程序关机,这个决定已是不可更改了,
被通知关闭的程序无权决定是否关机。
我想应该可以拦截系统消息,如果是关机消息,则扔掉它不管。
系统关机时要关闭应用程序,你只需要处理你的应用程序关闭事件即可。
────────────────────────────────────────
xceman (辉->伪狼*谎称羔羊) 于 2003年02月28日13:42:17 星期五 说道:
钩子(hook),截获关机消息
────────────────────────────────────────
valley (天音) 于 2003年02月28日14:37:42 星期五 说道:
补充说明:
如果我想关机而软件不允许,我的第一反应可能会是强行关闭软件
然后把它删除。我可不希望软件凌驾在我意志之上。
编程中需要注意的一个重要的问题就是自己的角色。程序员不是主
宰者而是服务者。程序的工作是使用户觉得非常方便舒服,而不是想
关机是遭到拒绝。
以上意见仅供参考。
────────────────────────────────────────
goodday (品位文章) 于 2003年02月28日18:35:25 星期五 说道:
说的完全正确。
//实在强行关闭不了,我还可以直接关电源呢!
────────────────────────────────────────
fenxuan (风轩小筑) 于 2003年02月28日20:46:57 星期五 说道:
首先谢谢大家的回复.
因为这个程序的特殊性,只是想避免误操作,我已经在网上找到了一片相关的文章.
与大家共享:
==================================
在关机或Logff前信息的拦截
如果我们关机或Logoff时,我们的程序有时会因而无法按正常程序结束,一般我们会
在Form的Unload中一段程序结束时要做什么事,但是,如果使用者直接用开始功能菜单的
关机,会使UnLoad的部份没有做到,我们现在就想办法来拦截关机(或Logoff)时的信息。
一般来说,关机或Logff后,Windows会传依序送出WM_QUERYENDSESSION的信息给每个P
rocess,如果中间有一个Process不能顺利结束(例如:Word修改后未存档,而出现是否存
档,但我们按取消),这时该信息执行的结果会传回False(0),这时Windows也就不再继续
送WM_QUERYENDSESSION给下一个Proccess。反之,如果所有的Process都可以顺利结束(也
就是每个送出的WM_QUERYENDSESSION都传回True),那才代表以以顺利结束。
不管WM_QUERYENDSESSION最后的结果是可以顺利结束或不能顺利结束,Windows会再送
一个WM_ENDSESSION的信息给所有的Process,而wParam的内容便是指出是否可以顺利结束(
True菜单可以,False菜单不行,在vb中则CheckwParam = 0 菜单False ,0菜单True),说
到这里大概就知道该如何做啦,程序如下:
’以下在Form
Private Sub Form_Load()
Dim ret As Long
’记录原来的Window Procedure的位址
preWinProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
’设定form的window Procedure到wndproc
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf wndproc)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
’取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(Me.hwnd, GWL_WNDPROC, preWinProc)
’这里只是要看看用关机的方式结束程序时,会不会执行到这里
Dim fno As Long
fno = FreeFile
Open "c:\tt2" For Append As fno
Print #fno, "ccc" + vbCrLf
Close #fno
End Sub
’以下在.Bas
Option Explicit
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const WM_ENDSESSION = &H16
Public Const WM_QUERYENDSESSION = &H11
Public preWinProc As Long
Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_QUERYENDSESSION Then
Debug.Print "QryEnd", wParam, lParam
Else
If Msg = WM_ENDSESSION Then
If wParam 0 Then ’代表将顺利关机或LogOff,这时便得做正常结束程序的操作
Dim fno As Long
Open "c:\ttt" For Output As #1
Print #1, "hahcccc5"
Close #1
End If
End If
End If
’将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam)
End Function
【
在 valley ( 天音) 的大作中提
到: 】: 补充说明:: 如果我想关机而软件不允许,我的第一反应可能会是强行关闭软件
────────────────────────────────────────
fenxuan (风轩小筑) 于 2003年03月02日09:17:50 星期天 说道:
还得继续请教你一下:
我上次找的那篇关于关机控制的文章只能实现在关机时给出提示的作用,如果对提示不加
任何处理系统也会出现强制关闭程序的提示框。总之,关机是一定的。
我现在想实现让用户来选择到底是关还是不关,既可以控制机器不关。即你所说的拦截系
统消息,请问具体怎么实现?
谢谢。
这是我的部分源程序:
------------------------
.bas部分
Option Explicit
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal HWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal HWnd As Long, ByVal nIndex As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal HWnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const WM_ENDSESSION = &H16
Public Const WM_QUERYENDSESSION = &H11
Public preWinProc As Long
Public Function wndproc(ByVal HWnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Dim aa As String
If Msg = WM_QUERYENDSESSION Then
Debug.Print "QryEnd", wParam, lParam
Else
If Msg = WM_ENDSESSION Then
If wParam = 0 Then '代表将顺利关机或LogOff,这时便得做正常结束程序的操作
MsgBox "ok0", vbOKCancel
ElseIf wParam = 1 Then
aa$ = MsgBox("ok1", vbOKCancel)
'控制是否关机部分
End If
End If
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, HWnd, Msg, wParam, lParam)
End Function
------------------------
主体
Private Sub Form_Load()
Dim ret As Long
'记录原来的Window Procedure的位址
preWinProc = GetWindowLong(Me.HWnd, GWL_WNDPROC)
'设定form的window Procedure到wndproc
ret = SetWindowLong(Me.HWnd, GWL_WNDPROC, AddressOf wndproc)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim ret As Long
'取消Message的截取,而使之又只送往原来的Window Procedure
ret = SetWindowLong(Me.HWnd, GWL_WNDPROC, preWinProc)
'这里只是要看看用关机的方式结束程序时,会不会执行到这里
Dim fno As Long
fno = FreeFile
Open "c:\tt2" For Append As fno
Print #fno, "ccc" + vbCrLf
Close #fno
End Sub
==========================================================
────────────────────────────────────────
valley (天音) 于 2003年03月03日14:23:00 星期一 说道:
If Msg = WM_QUERYENDSESSION Then
Debug.Print "QryEnd", wParam, lParam
***********************************************************
aa$ = MsgBox("ok1", vbOKCancel)
'控制是否关机部分
如果用户说不关, 把wParam和lParam置0传回windows
若关机,把非0值传回windows
未亲自验证,仅供参考
***********************************************************
Else
....
End If
'将之送往原来的Window Procedure
wndproc = CallWindowProc(preWinProc, HWnd, Msg, wParam, lParam)
End Function
────────────────────────────────────────
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.604毫秒