如何在 TForm 以外的控件中捕获 WM_DEVICECHANGE?

2023-12-15

直到今天我一直在使用以下代码来捕获WM_DEVICECHANGE应用程序主窗体中的消息并且它运行良好。但是,如果我尝试在自定义控件中使用它,我不会收到有关设备插入或删除的通知。怎么了 ?

  TDriveBar = class(TCustomPanel)
  private
    procedure WMDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;  
  end;

implementation

procedure TDriveBar.WMDeviceChange(var Msg: TMessage);
const DBT_DEVICEARRIVAL = $8000;
      DBT_DEVICEREMOVECOMPLETE = $8004;
      DBT_DEVTYP_VOLUME = 2;

type PDEV_BROADCAST_HDR = ^DEV_BROADCAST_HDR;
     DEV_BROADCAST_HDR = record
      dbch_size: dword;
      dbch_devicetype: dword;
      dbch_reserved: dword;
     end;

begin
 case Msg.WParam of

  DBT_DEVICEREMOVECOMPLETE:
   if PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype = DBT_DEVTYP_VOLUME then UpdateDrives;

  DBT_DEVICEARRIVAL:
   if PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype = DBT_DEVTYP_VOLUME then UpdateDrives;

 end;
end;

操作系统发送wm_DeviceChange向所有顶级窗口发送消息。应用程序的主窗体是顶级窗口,但您的控件不是,这就是窗体接收消息而您的控件不接收消息的原因。

对于任意设备类型,您有两种选择:

  1. Use AllocateHWnd创建一个仅包含消息的顶级窗口,该窗口将通过调用与控件关联的函数来响应消息。这将为您提供与主表单收到的相同的基本信息。

    为您的控件编写一个与签名相匹配的方法TWndMethod,这就是AllocateHWnd需要。它可能看起来像这样:

    procedure TDriveBar.DeviceWindowProc(var Message: TMessage);
    begin
      case Message.Msg of
        wm_DeviceChange: begin
          case Message.WParam of
            DBT_DEVICEREMOVECOMPLETE, DBT_DEVICEARRIVAL:
              if PDEV_BROADCAST_HDR(Message.LParam).dbch_devicetype = DBT_DEVTYP_VOLUME then
                UpdateDrives;
          end;
        end;
      end;
      Message.Result := DefWindowProc(FDeviceWnd, Message.Msg, Message.WParam, Message.LParam);
    end;
    

    然后在创建消息窗口时使用该方法:

    FDeviceWnd := AllocateHWnd(DeviceWindowProc);
    
  2. Call RegisterDeviceNotification告诉操作系统您的控件的窗口也想要接收通知。 (确保你处理好你的控件CreateWnd and DestroyWnd方法,以便如果重新创建控件,您可以使用控件的新窗口句柄更新通知注册。)这将为您提供比默认值更详细的信息wm_DeviceChange消息提供,但仅适用于您在注册窗口句柄时指定的设备类型。

但是,您对以下更改感兴趣volumes。备注为RegisterDeviceNotification对此有话要说(强调):

The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE事件会自动广播到端口设备的所有顶级窗口。因此,没有必要调用RegisterDeviceNotification对于端口,如果dbch_devicetype成员是DBT_DEVTYP_PORT. 音量通知也会广播到顶级窗口,因此如果出现以下情况,该功能将失败dbch_devicetype is DBT_DEVTYP_VOLUME.

这消除了通知注册作为您的一个选项,因此您的情况唯一的解决方案是使用AllocateHWnd.

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

如何在 TForm 以外的控件中捕获 WM_DEVICECHANGE? 的相关文章

  • Delphi 返回 TList 时出错

    我做了一个非常简单的应用程序 但我有一个我真的无法理解的问题 看一下这个基本代码 unit Unit1 interface uses Winapi Windows Winapi Messages System SysUtils System
  • 处理 TShellListView 后代中的文件放置

    我正在尝试创建 TShellListView 的后代 它接受从 Windows 资源管理器中删除的文件 我想在组件定义中处理拖 放操作 而不必在任何使用该组件的应用程序中实现它 我找到了接受从 Windows 资源管理器中拖放的文件的示例
  • 当responseText包含有效的Xml时,IXMLHttpRequest.responseXml为空,没有解析错误

    我正在从中获取一些 XML政府网站 http www bankofcanada ca stats assets rates rss noon en all xml http www bankofcanada ca stats assets
  • 在 Delphi 中使用 XML(将特定数据返回到变量)

    过去几天我一直在尝试使用 Delphi 2010 和 MSXML 我是一个极端的新手 需要一点指导 var MemoryStream TMemoryStream XMLPath String sName String XMLDoc vari
  • 将数据从一个数据集结构移动到另一个数据集结构的更快方法(在 TDatasetProvider 中)

    我有一个自定义的 TDatasetProvider 它允许为其提供的任何数据创建新字段 因此 假设您在原始数据集上获得了以下字段 客户ID Name Age 您需要使用显示位图在 DBGrid 上选择它 好吧 你可以 因为我的 DSP 可以
  • Delphi 5 中的 Oracle 数据库连接

    我正在使用 Delphi 5 版本 我想连接到 Oracle 数据库 我有 TDatabase 组件 我不知道如何通过 Delphi 连接到数据库 请提供连接数据库的步骤 谢谢 The TDatabase http docwiki emba
  • Delphi 6 命令行编译:无 DCU

    当对 dpr 文件使用 dcc32 时 它会生成一个 dll 但不会生成 dcu 项目级别 cfg 使用 N 开关设置路径 但指定的目录中没有任何内容 当 E 开关正在工作时 它必须看到 cfg 我尝试在调用 dcc32 之前对 dpr 文
  • 如何检查注册表项是否存在

    我不知道我的错误在哪里 它总是跳到else分支 但是密钥存在 我检查了几次 var reg TRegistry begin with TRegistry Create do try RootKey HKEY CURRENT USER Ope
  • 从创建 UI 的同一线程更新 VCL。为什么?

    我知道我必须调用 Synchronize 来从未创建控件或向窗口发送消息的线程更新 vcl 我经常听到 线程不安全 这个词 但我找不到关于正在发生的事情的实际解释 我知道应用程序可能会因访问冲突而崩溃 但我又不知道为什么 请阐明这个主题 V
  • 查找字符串是否在列表中的最佳方法(没有泛型)

    我想做这样的事情 Result MyString in string1 string2 string3 string4 这不能与字符串一起使用 我不想做这样的事情 Result MyString string1 or MyString st
  • C# 获取子窗口句柄

    我正在用 C 启动一个进程 然后使用 SendMessage 将 Windows 消息发送到该进程 通常我将消息发送到 Process MainWindowHandle 但在某些情况下 我可能需要找到子窗口句柄并向那里发送消息 我将如何在
  • 任意通用列表的通配符

    我有一个类 MyClass 它不是通用的 包含任意 TList 并对其执行某些操作 我希望用通用 TList 替换 TList 但 MyClass 必须保持非通用 由于 Delphi 是不变的 这样的事情是行不通的 list1 TList
  • Delphi 中是否有一些功能可以将带有 html 命名和编号实体的字符串转换为 unicode 文本?

    我从 mysql 数据库读取数据 该数据库由 php 脚本填充 所有特殊字符都会转换为命名或编号的 html 实体 例如 a m p 2 8 6 我知道没有办法将这些字符转换回 Delphi 中的原始字符作为 unicode 字符串 有没有
  • 读取存储在注册表中的 GUID 值

    我尝试读取存储为的 GUID 值binaryDelphi 注册表中的值 当我用BintoHex读取它时 但结果是相反的 看来我必须交换字节 但我认为 BinToHex 可以做到 我参考了这个线程 但找不到正确的解决方案 如何在 Delphi
  • 无法使用 Indy 从 Gmail 获取电子邮件

    I use TIdPOP3很多 而且效果很好 除了 GMail 帐户 不知怎的 它永远不起作用 我尝试了不同的组合和端口 无论是否使用 SSL 它总是返回不同的错误 我最近的尝试是在 Gmail 上创建 应用程序特定 密码 并尝试使用此密码
  • 如何使用 Delphi 播放单音或自定义波形?

    我查了一些代码 似乎一切都在创建一些数学函数波 但我想要一个单音 或者用自定义单音制作的自定义波 我读了这个如何生成不同频率的连续音调 https stackoverflow com questions 7742377 how can i
  • 使用 Delphi 的 7-Zip?

    我想使用 Delphi 的 7 Zip DLL 但一直找不到合适的文档或示例 有谁知道如何使用 Delphi 的 7 Zip DLL 自版本 1 102 起JEDI 代码库 http wiki delphi jedi org index p
  • 如何从后台线程有效地对 Delphi 6 框架或表单执行图像流预览?

    我有一个 Delphi 6 应用程序 用于接收和处理来自外部摄像头的图像流 我将代码放在后台线程上 因为它占用大量 CPU 而且我不希望它干扰在主线程上运行的用户界面代码 我想使用我从相机的 JPEG 帧创建的 TBitmap 来更新表单或
  • Delphi 中的非字母排序

    我正在尝试按特定顺序对字符串列表进行排序 我尝试用 B C A 来订购 而不是 A B C 我已经按照我需要的顺序声明了一个 const 数组 我尝试过 CustomSorte 但我不明白如何编写该函数 我现在正在尝试使用 for 循环 但
  • 当应用程序最小化时隐藏表单

    我有一个主表单和一个状态表单 当我的应用程序中的工作正在进行时 我会显示它们 如果工作完成我就打电话Hide状态表上出现 状态表消失 当我最小化主窗体而等待窗体可见时 就会出现问题 然后两种形式都被隐藏 这就是我想要的 但是 如果工作完成时

随机推荐

  • 使用最简单的方法将数据(字符串)从子 VC 传递到父 VC

    使用最简单的方法将数据 字符串 从子视图控制器传递到父 VC 我尝试了几种方法 但迷失了 有人可以告诉我最好的方法吗 斯里坎特是正确的 如果您有从一个视图控制器 我们的 第一个 视图控制器 到另一个视图控制器 我们的 第二个 视图控制器 的
  • 单击坐标而不识别元素

    作为我的 Selenium 登录功能测试的一部分 我想通过识别按钮的坐标并指示 Selenium 单击这些坐标来单击按钮 这可以在不识别元素本身的情况下完成 通过 id xpath 等 我知道还有其他更有效的方法来运行单击命令 但我希望专门
  • 即使浏览器关闭,CodeIgniter 如何保留会话数据?

    我想知道 CodeIgniter 中的会话是如何工作的 当浏览器关闭时 会话不是应该自动终止吗 默认情况下 CodeIgniter 不会在浏览器关闭时销毁会话 config sess expire on close FALSE 相反 我们可
  • Chart.js 工具提示模板不起作用

    因此 我正在 Chart js 中使用条形图 并且尝试让自定义工具提示正常工作 环顾四周 似乎在这种情况下要做的事情是添加 tooltipTemplate test 到我的选项部分 这将在结果工具提示中的数据值后面显示单词 test 然而
  • 在 SQL 中存储用户定义数据的正确方法

    我想构建一个类似于 wufoo 的在线表单生成器 允许用户创建和发布自己的 Web 表单 每个提交内容都应保存到数据库中 用户稍后可以在数据库中检索提交内容 因为这些形式将是动态的 即 用户可以完全控制表单字段的数量和类型我正在尝试考虑一个
  • PHP - 当变量放入 url 时,include() 文件不起作用?

    在 PHP 中 我构建了一个网页 它使用 include 来加载网站的某些部分 然而 我现在遇到了一个类似的问题 当我使用如下网址时 data openov storingen php type actueel它给了我这个错误 Warnin
  • 如何通过 tasytpie API 将产品放入购物车?

    假设我们有这些模型 原始项目有所不同 但这将是常见任务 class Cart models Model owner models ForeignKey User products models ManyToManyField Product
  • excel vba - 多条件索引匹配

    我正在尝试在 vba 中执行多条件索引匹配函数 但我似乎无法得到结果 我使用的代码如下 wsDest Range wsDest Cells i X wsDest Cells i X Application WorksheetFunction
  • 如何使用 while 循环和拆分来汇总逗号和换行符分隔的 CSV 文件中的数据?

    Perl 脚本必须加载 CSV 数据文件并对文件中的所有数字求和 文件中只有数字 以逗号和换行符分隔 我已经完成了大部分代码 但我没有得到正确的总数 我可能会忽略某些事情或对一两个概念有根本性的误解 任何帮助将不胜感激 全部汇总的 CSV
  • 如何在 TForm 以外的控件中捕获 WM_DEVICECHANGE?

    直到今天我一直在使用以下代码来捕获WM DEVICECHANGE应用程序主窗体中的消息并且它运行良好 但是 如果我尝试在自定义控件中使用它 我不会收到有关设备插入或删除的通知 怎么了 TDriveBar class TCustomPanel