问题描述:在最近的windows程序中,由于实现了winform程序点击窗口的关闭按钮,不直接退出程序,而是将程序最小化到托盘中,这样当程序没有退出之前,直接关机会导致关机不能正常进行。
问题原因:操作系统会在用户点击关机后,发送一个关闭的消息到当前运行的应用程序,这个消息的ID号问0x11,这样当应用程序接受到消息后就会关闭自身,然后操作系统就可正常关闭了。但是我们在实现了上面的功能后,会在FormClosing事件中添加一段代码,
e.Cancel = true;
//最小化到托盘
NormalToMinimized();
这样我们虽然实现了功能,但是在接受到操作系统发送来的关闭窗口的消息的时候,就不能关闭程序了。
解决方案:1.在应用程序的主窗口添加一个私有的标识,用来标识,关闭窗口的事件是由用户点击引起的还是由操作系统发送的小心引起的。
2.在应用程序主窗口中添加对系统消息的处理,这个处理的过程需要重写窗口的窗口过程,也就是窗口处理操作系统消息的方法。
protected override void WndProc(ref Message m) { if (m.Msg == 0x11) { //自定义的事件触发标识,为true时表示窗口的关闭事件是由操作系统的关机操作引起的。 isExitAppFalg = true; } base.WndProc(ref m); }
3.修改FormClosing事件的处理过程,添加一个判断就可以了
if (!isExitAppFalg) { e.Cancel = true; //最小化到托盘 NormalToMinimized(); }
这样就把实现功能所带了的副作用给解决了。
补充:根据网友们的指正,我这里确实画蛇添足了。 FormClosingEventArgs 这个类里面有一个CloseReason枚举,枚举的各个值
0:无法判断
1:操作系统关闭窗口
2:多文档页面的父窗口在关闭
3:用户关闭,点击关闭按钮或者按下alt+F4
4:任务管理器正在关闭应用程序
5:此窗口的归属窗口正在关闭
6 :应用程序的exit被调用
在FormClosing事件中只要判断一下窗口是由哪一种原因关闭的就可以了;