屏蔽Winform的关闭按钮与“创建窗口句柄时出错”

首先,先介绍下如何屏蔽Winform的关闭按钮,就是在点关闭时,并不是直接关闭程序,而是提示是否真的关闭或者最小化。
前段时间要实现这个功能,所以就在网上搜罗了下。Winform的关闭操作其实是发一个关闭的消息。所以,要想不关闭窗口,只要截获这个消息就可以了。
那么如何截获呢?
可以用WndProc来得到并处理Window系统注销或关闭的消息:
protected override void WndProc(ref Message m)
        
{
            
const int WM_SYSCOMMAND = 0x0112;
            
const int SC_CLOSE = 0xF060;
            
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)   // 用户点击关闭按钮
            {
                
this.WindowState = FormWindowState.Minimized;   // 最小化
                return;
            }

            
base.WndProc(ref m);   // 调用基类的窗体事件
        }
上面的方法就是点击关闭按钮后不退出程序,而是最小化。
另外,也可以用Closeing事件,事件里的参数e有个Cancel,当e.Cancel=true的时候也会不关闭程序及系统(或注销)。


这个方法是满足了我的要求,但是我昨天又想用在另一个Winform程序的时候,把代码添加过去,并做了适当的修改:
protected override void WndProc(ref Message m)
        
{
            
const int WM_SYSCOMMAND = 0x0112;
            
const int SC_CLOSE = 0xF060;
            
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)   // 用户点击关闭按钮
            {
                
if (DialogResult.No == MessageBox.Show("确定退出?""退出", MessageBoxButtons.YesNo))
                
{
                    
// 不关闭
                    return;
                }

            }

            
//base.WndProc(ref m);   // 调用基类的窗体事件
        }
这里我是先提示是否确定要退出程序,如果选是才真的退出,否则不做任何处理。我把最后的一条语句注释掉了。
这时问题就出现了:出现了“创建窗口句柄时出错”的Win32Exception。
后来把baseWndProc(ref m)的注释取消掉,就行了。   具体原因还不清楚,知道的朋友讲解下。
希望,能给有类似困扰的朋友有所帮助。

汇聚杭州外卖:外卖汇
posted @ 2008-04-08 09:28 随风逝去(叶进) 阅读(1936) 评论(18)  编辑 收藏 所属分类: A. C#.NET

  回复  引用  查看    
#1楼 2008-04-08 09:45 | ZH-CN      
关注~
  回复  引用  查看    
#2楼 [楼主]2008-04-08 09:56 | 随风逝去(叶进)      
@ZH-CN
谢谢哦!呵呵
  回复  引用  查看    
#3楼 2008-04-08 10:11 | 队长      
哥们,不加base.WndProc(ref m);的话,窗体就啥消息都处理不了了
这样写比较妥当:
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
{
//your code
}
else
{
base.WndProc(ref m);
}
  回复  引用  查看    
#4楼 [楼主]2008-04-08 10:20 | 随风逝去(叶进)      
@队长
恩,是的,这样可读性确实好很多。
哦! 明白了!

谢谢队长
  回复  引用  查看    
#5楼 2008-04-08 10:54 | 天生俪姿      
一开始粘的代码似乎见过。
另外说一下。楼主的简介那里好像有点串位了。

  回复  引用  查看    
#6楼 2008-04-08 10:54 | 天生俪姿      
我的分辨率为1024*768
  回复  引用  查看    
#7楼 2008-04-08 11:04 | dudu      
请调整一下摘要中的图片。
  回复  引用  查看    
#8楼 2008-04-08 11:09 | zoti      
不是有個事件嗎?
FormClosing
  回复  引用  查看    
#9楼 [楼主]2008-04-08 11:13 | 随风逝去(叶进)      
@天生俪姿
@dudu
把摘要中的图片去掉了!
  回复  引用  查看    
#10楼 [楼主]2008-04-08 11:14 | 随风逝去(叶进)      
@zoti
是可以设置FormClosing事件中的e.Cancel=true
  回复  引用    
#11楼 2008-04-08 11:27 | Gavin Lv [未注册用户]
不用这么复杂吧,我一般是在Closing中判断Environment.HasShutdownStarted


protected overrides void OnClosing(EventArgs e)
{
if (!Environment.HasShutdownStarted)
{
e.Cancel = true;
this.WindowState = FormWindowState.Minimized;
}
}
  回复  引用  查看    
#12楼 2008-04-08 11:33 | 王孟军!      
关注...
  回复  引用  查看    
#13楼 2008-04-08 11:35 | 飞无痕落无声      
--引用--------------------------------------------------
Gavin Lv: 不用这么复杂吧,我一般是在Closing中判断Environment.HasShutdownStarted


protected overrides void OnClosing(EventArgs e)
{
if (!Environment.HasShutdownStarted)
{
e.Cancel = true;
this.WindowState = FormWindowState.Minimized;
}
}
--------------------------------------------------------
楼主的方法是揭示了关闭事件的真相,你那样用法虽然简单,但是却被MICROSOFT给蒙蔽了。
  回复  引用  查看    
#14楼 2008-04-08 13:44 | winkingzhang      
-------------------------------
后来把base.WndProc(ref m)的注释取消掉,就行了。
具体原因还不清楚,知道的朋友讲解下。
-------------------------------
这里WndProc是Windows消息处理函数,lz不调base的话,所有的消息到这里就不会处理,当然这里有些是可以不处理的,但是WM_CREATE和WM_NCCREATE是必须传给系统处理的,否则窗体时不能创建出来的。

  回复  引用  查看    
#15楼 [楼主]2008-04-08 15:11 | 随风逝去(叶进)      
@winkingzhang
是的! 谢谢你!
  回复  引用  查看    
#16楼 2008-04-08 18:01 | Ryan Yu      
感谢楼主分享:)
  回复  引用  查看    
#17楼 2008-04-09 10:12 | 阿鸟      
......哪那么麻烦咯....
  回复  引用  查看    
#18楼 [楼主]2008-04-09 10:43 | 随风逝去(叶进)      
@阿鸟
是的! 可以设置FormClosing事件中的e.Cancel=true来取消关闭操作!
Free Web Counter
Free Web Counter