我有一个.net 2.0 Windows窗体应用程序。
我已覆盖WndProc方法以捕获表单上的用户活动
例如:
const int HTCLOSE = 0x0014;
bool m_bCloseButtonActive = false;
if (m.Msg == WM_NCHITTEST)
{
base.WndProc(ref m);
m_bCloseButtonActive = (m.Result.ToInt32() == HTCLOSE);
}
根据m_bCloseButtonActive的值,我采取进一步行动。
我现在遇到的问题是我的表单没有关闭,因为它无法捕获操作系统Vista及更高版本(甚至是Windows 7)中的关闭按钮单击事件。
即条件 m.Result.ToInt32()== HTCLOSE 永远不会出现,当我点击关闭按钮时,我的表单永远不会关闭。
我的应用程序适用于以前的操作系统(Windows 2000,XP,XP Embedded)。 另外一个有趣的事情是它在我指定
时有效Application.VisualStyleState = System.Windows.Forms.VisualStyles.VisualStyleState.ClientAreaEnabled;
有什么想法在这里发生。这是与桌面Windows管理器相关的东西,我的应用程序无法捕获关闭按钮单击事件。
提前致谢
答案 0 :(得分:6)
在我看来,点击测试消息并不适合这样做。例如,如果用户通过系统菜单或通过Alt + F4快捷键关闭表单会怎样?
我认为您应该使用wParam == SC_CLOSE
回复WM_SYSCOMMAND
条消息。
Windows Aero在处理非客户端区域方面有着根本的不同,这解释了为什么它在2000 / XP中运行以及禁用DWM时的原因。但是使用WM_SYSCOMMAND
可以在所有版本的Windows中使用。
请注意,您需要非常仔细地阅读WM_SYSCOMMAND
的MSDN文档,因为消息参数包含需要屏蔽的额外信息。要检测关闭按钮,您需要这样的代码:
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND)
if ((m.WParam.ToInt32() & 0xFFF0) == SC_CLOSE)
MessageBox.Show("close button pressed");
}
base.WndProc(ref m);
}
如果您想在用户关闭表单时更改行为,为什么不处理Closing
事件?
答案 1 :(得分:-1)
这终于奏效......我使用了WM_NCMOUSEMOVE而不是非客户端HITTEST信息 WParam包含所有相关事件。
const int WM_NCMOUSEMOVE = 0x00A0;
if (m.Msg == WM_NCMOUSEMOVE)
{
base.WndProc(ref m);
if ((m.WParam.ToInt32() == HTCLOSE))
{
m_bCloseButtonActive = true;
}
}