所有 Process* 方法和所有消息过滤器的目的是什么?

2023-11-26

我注意到 WinForms 有许多处理命令或按键的方法(Process*())并(预)过滤系统的消息,但我仍然不清楚它们各自的目的。

官方文档有些晦涩难懂,我还没有找到任何清晰完整的回应。

我讲以下几个方法:

  • PreFilterMessage(ref Message m)
  • ProcessCmdKey(ref Message msg, Keys keyData)
  • WndProc(ref Message m)
  • ProcessDialogKey(Keys keyData)
  • PreProcessMessage(ref Message msg)
  • ProcessKeyMessage(ref Message m)
  • ProcessKeyPreview(ref Message m)

有些用于拦截键(例如ProcessCmdKey or ProcessDialogKey)和一些用于拦截消息(彼此)。但为什么有这么多方法呢?它们的目的和用例是什么?

我认为每个方法的执行顺序是不同的。

这是我所知道的(或者我认为知道的):

  • PreFilterMessage:首先拦截消息。您可以在这里停止以下所有方法的消息分发!
  • ProcessCmdKey:拦截所有键,甚至组合键、特殊键和命令键。适合检测整个表单上的快捷键(如 Ctrl + D)。您可以在此处停止密钥的分发。
  • WndProc:过滤后第二次拦截消息?我仅用它来检测用户是否单击右上角的“X”,但我认为通过另一种方法这是可能的!
  • ProcessDialogKey:仅拦截一个键,可能在ProcessCmdKey并在控件的所有按键事件之前。
  • PreProcessMessage: 前WndProc之后PreFilterMessage?我不知道为什么要使用它。
  • ProcessKeyMessage:拦截关键消息。好像很少用。
  • ProcessKeyPreview:在预览事件之前拦截按键?也很少用。

深入地说,我认为这是正确的执行顺序:

  1. 前置过滤器
  2. Filter
  3. 预处理
  4. Process
  5. Events

为什么要这么多步骤?

任何信息或具体用例将不胜感激!


本机 Windows GUI 应用程序通常具有one消息循环,底层的 winapi 调用是 GetMessage()。但有many获取消息的windows,底层的winapi调用是DispatchMessage()。在您的 .NET 应用程序中,您有一次对 Application.Run() 的调用,但有许多 WndProc() 方法,每个控件一个。其中大多数隐藏在 .NET Framework 代码中,只有在覆盖它时才会暴露。

通常需要挂钩消息循环,在消息分派到控件并到达 WndProc() 之前拦截消息。最明显的原因是键盘快捷键,无论哪个控件具有焦点,您都希望对它们进行操作。这当然是very如果你不得不使用 KeyDown 的话会很痛苦every控件来检测快捷方式。还有一些不太明显的原因,例如,ActiveX 控件因必须与其主机进行协商而引人注目。

Winforms 给出lots拦截消息的扩展点。确实太多了,但不可避免的副作用是不想预测它们在哪些情况下可能有用。为了:

  • IMessageFilter.PreFilterMessage() 允许您在 GetMessage() 检索消息后立即查看消息。请记住,您只能看到发布到消息队列的消息,底层调用是 PostMessage(),您无法看到已发送的消息。这限制了它对用户输入、键盘和鼠标消息的可用性。很少修改这个,但是您可以使用它来使鼠标以不同的方式运行并检测用户正在与您的程序交互。例如,想要在一段时间不活动后自动注销用户的程序员可以使用它。
  • OnPreviewKeyDown() 和 PreviewKeyDown 事件。特定于具有焦点的控件。控件在测试快捷键之前拦截击键的一种方法。例如,您可以在光标键用于移动焦点之前以这种方式检测它们。重写 IsInputKey() 的替代方法。
  • 预处理消息()。与 PreFilterMessage 非常相似,但特定于具有焦点的控件。对于 ActiveX 控件来说很重要,但我个人从未使用过它。
  • ProcessCmdKey()。这是实现您自己的快捷键的主要方法。
  • IsInputKey() 允许控件投票决定是否应将通常用于导航的键发送到控件。例如,当您使用光标键时,您可以重写此方法。
  • ProcessDialogKey()。就像 ProcessCmdKey() 一样,但过滤了应该像输入键一样对待的击键。默认实现使键盘消息冒泡到父控件,让您可以选择重写 ProcessCmdKey() 的位置。我想不出你想要覆盖它的充分理由,而且除了阻止冒泡之外,从来没有这样做过。
  • IsInputChar(),与 IsInputKey 非常相似,但用于 KeyPress 事件。我自己从未使用过它,而是一种早期过滤输入的方法。
  • ProcessDialogChar() 可用于提供打字键快捷键击键行为。这很不寻常。
  • WndProc(),处理消息的主力方法。您可以覆盖它以允许控件响应现有事件未涵盖的消息。或者自定义现有本机控件的行为。
  • ProcessKeyEventArgs(),生成键盘事件(OnKeyDown、OnKeyUp、OnKeyPress)的通用方法,由 Control.WndProc() 调用。我想不出重写它的理由,尤其是实现了古怪的 Form.KeyPreview 属性(VB6 兼容属性),这可能是它被暴露的原因。

确实是一个曲折的迷宫。

为了保持理智,请始终重写 ProcessCmdKey() 来实现快捷键。重写 IsInputKey() 以使您的控件可以看到导航键。并且仅重写 WndProc() 即可自定义现有控件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

所有 Process* 方法和所有消息过滤器的目的是什么? 的相关文章

  • .NET 中是否有内置函数可以对密码进行哈希处理?

    我看到这个问题加密 散列数据库中的纯文本密码 https stackoverflow com questions 287517 encrypting hashing plain text passwords in database 我知道我
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • Windows C++ 中的键盘钩子还是什么?

    我希望构建自己的应用程序 它可以将键盘命令 消息 发送到 Windows 操作系统 例如 当我按下组合键 ctrl shift n 时 我希望启动 notepad exe 我怎样才能做到这一点 您对所使用的概念有什么建议吗 我读过 何时使用
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐