0

我有一个 .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 管理器有关,我的应用程序无法捕获关闭按钮单击事件。

提前致谢

4

2 回答 2

6

在我看来,命中测试消息不是执行此操作的合适方法。例如,如果用户通过系统菜单或 Alt+F4 快捷键关闭表单怎么办?

我认为您应该使用 回复WM_SYSCOMMAND消息wParam == SC_CLOSE

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事件呢?

于 2011-03-21T09:43:23.860 回答
-1

这终于奏效了......我使用 WM_NCMOUSEMOVE 而不是非客户端 HITTEST 信息 WParam 包含所有相关事件。

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

常量 int WM_NCMOUSEMOVE = 0x00A0;

  if (m.Msg == WM_NCMOUSEMOVE)
    {
    base.WndProc(ref m);
    if ((m.WParam.ToInt32() == HTCLOSE))
    {
      m_bCloseButtonActive = true;
    }
   }
于 2011-03-21T15:10:16.303 回答