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

发布于 2024-10-24 11:30:48 字数 800 浏览 1 评论 0原文

我有一个 .net 2.0 Windows 窗体应用程序。

我已经重写了 WndProc 方法来捕获表单上的用户活动

Ex:

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

提前致谢

I have a .net 2.0 windows forms application.

I have overridden the WndProc method to capture the user activities on the form

Ex:

const int HTCLOSE           = 0x0014;
bool m_bCloseButtonActive   = false;

if (m.Msg == WM_NCHITTEST)
{
    base.WndProc(ref m);
    m_bCloseButtonActive = (m.Result.ToInt32() == HTCLOSE);
}

Based on the value of m_bCloseButtonActive i take further actions.

The issue now i face is my form doesn't close as it is not able to capture the Close button clicked event in the Operating systems Vista and above(even Windows 7).

i.e the condition m.Result.ToInt32() == HTCLOSE is never true and my form never closes when i click the close button.

My application works in previous OS (Windows 2000, XP, XP Embedded).
Also an interesting thing is that it works when i specify

Application.VisualStyleState = System.Windows.Forms.VisualStyles.VisualStyleState.ClientAreaEnabled;

Any idea whats going on in here. Is this something related to the Desktop Windows Manager, my application is not able to trap the close button clicked event.

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少跟Wǒ拽 2024-10-31 11:30:48

在我看来,命中测试消息并不是执行此操作的适当方法。例如,如果用户通过系统菜单或通过 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 事件?

Hit test messages doesn't seem to me to be the appropriate way to do this. For example, what if the user closes the form through the system menu, or through the Alt+F4 shortcut?

I think that you should be responding to WM_SYSCOMMAND messages with wParam == SC_CLOSE.

Windows Aero is fundamentally different when it comes to the handling of the non-client area which explains why it works in 2000/XP and when you disable DWM. But using WM_SYSCOMMAND works in all versions of Windows.

Note that you need to read the MSDN documentation for WM_SYSCOMMAND quite carefully because the message parameters contain extra information that needs to be masked out. To detect the close button you need code like this:

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);
}

If you want to change the behaviour when the user closes the form, why don't you handle the Closing event?

金兰素衣 2024-10-31 11:30:48

这终于起作用了......我使用 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;
    }
   }

This finally worked ... I used WM_NCMOUSEMOVE instead of the non client HITTEST information
The WParam contained all the related events.

This link helped :
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;
    }
   }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文