使用.NET在Windows Vista及更高版本中捕获WndProc消息

时间:2011-03-21 09:38:44

标签: c# windows windows-7 wndproc windows-messages

我有一个.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_bClos​​eButtonActive的值,我采取进一步行动。

我现在遇到的问题是我的表单没有关闭,因为它无法捕获操作系统Vista及更高版本(甚至是Windows 7)中的关闭按钮单击事件。

即条件 m.Result.ToInt32()== HTCLOSE 永远不会出现,当我点击关闭按钮时,我的表单永远不会关闭。

我的应用程序适用于以前的操作系统(Windows 2000,XP,XP Embedded)。 另外一个有趣的事情是它在我指定

时有效
Application.VisualStyleState = System.Windows.Forms.VisualStyles.VisualStyleState.ClientAreaEnabled;

有什么想法在这里发生。这是与桌面Windows管理器相关的东西,我的应用程序无法捕获关闭按钮单击事件。

提前致谢

2 个答案:

答案 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包含所有相关事件。

此链接有助于: http://social.msdn.microsoft.com/Forums/en/windowsuidevelopment/thread/9a8a63c8-79b5-43a8-82eb-f659be947add

const int WM_NCMOUSEMOVE = 0x00A0;

  if (m.Msg == WM_NCMOUSEMOVE)
    {
    base.WndProc(ref m);
    if ((m.WParam.ToInt32() == HTCLOSE))
    {
      m_bCloseButtonActive = true;
    }
   }