delphi - 需要在windows中解析HMONITOR --> deviceName(或deviceName --> HMONITOR)

标签 delphi winapi windows-7 delphi-7

编辑 - 请参阅末尾的更新

这适用于 Delphi 7.0 Build 4.453

摘要

我需要能够从作为 HMONITOR 的 TMonitor 对象(TScreen 组件中的 Monitors 数组中的一个元素)获取 Handle 属性,并将其转换为您在调用 EnumDisplaySettings 时使用的字符串。作为 lpszDeviceName 参数。

(我的最终目标是通过将解析的 lpszDeviceName 传递到对 EnumDisplaySettings 的调用中,从给定的 HMONITOR 值获取设备设置列表)。

详细信息

如上所述,Screen.Monitors[x].Handle 属性的类型为 HMONITOR,通常用于传递到 GetMonitorInfo函数,它返回几何信息,但不返回 lpszDeviceName。 (注意:有一个 TMonitorInfoEx 结构体有一个 szDevice 字段,但它在我的系统上似乎没有被填充,即使我将 cbSize 字段设置为适当的大小)。

或者,如果我可以使用 szDeviceName 来获取等效的 HMONITOR 值,我可以将其插入以下函数,该函数将在比较中使用它(我已插入对虚构函数的调用)在下面的代码中称为 hMonitorFromDeviceName )以指示如何使用它。

function GetMonitorDeviceName(hmon : HMONITOR) : string;
var
  DispDev : TDisplayDevice;
  deviceName : string;
  nDeviceIndex : integer;
begin
  Result := '';

  FillChar(DispDev, sizeof(DispDev),0);
  DispDev.cb := sizeof(DispDev);

  nDeviceIndex := 0;
  while (EnumDisplayDevices(nil, nDeviceIndex, DispDev, 0)) do
  begin

     if ( hMonitorFromDeviceName(DispDev.DeviceString) = hmon ) then
     begin
        Result := StrPas(DispDev.DeviceString);
        exit;
     end;

     inc(nDeviceIndex);

  end;
end;

更新

感谢 David Heffernan,我测试了他的解决方案,下面是一个从给定句柄获取监视器名称的示例函数:

function GetMonitorName(hmon : HMONITOR) : string;
type
  TMonitorInfoEx = record
    cbSize: DWORD;
    rcMonitor: TRect;
    rcWork: TRect;
    dwFlags: DWORD;
    szDevice: array[0..CCHDEVICENAME - 1] of AnsiChar;
end;
var
  DispDev : TDisplayDevice;
  deviceName : string;
   monInfo : TMonitorInfoEx;
begin
  Result := '';

  monInfo.cbSize := sizeof(monInfo);
  if GetMonitorInfo(hmon,@monInfo) then
  begin

    DispDev.cb := sizeof(DispDev);
     EnumDisplayDevices(@monInfo.szDevice, 0, DispDev, 0);
     Result := StrPas(DispDev.DeviceString);

  end;
end;

最佳答案

我认为您一定是错误地调用了GetMonitorInfo。这段代码:

{$APPTYPE CONSOLE}

uses
  SysUtils, MultiMon, Windows, Forms;

var
  i: Integer;
  MonitorInfo: TMonitorInfoEx;
begin
  MonitorInfo.cbSize := SizeOf(MonitorInfo);
  for i := 0 to Screen.MonitorCount-1 do
  begin
    if not GetMonitorInfo(Screen.Monitors[i].Handle, @MonitorInfo) then
      RaiseLastOSError;
    Writeln(MonitorInfo.szDevice);
  end;
  Readln;
end.

在我的机器上产生以下输出:

\\.\DISPLAY1
\\.\DISPLAY2

I suspect that your call to GetMonitorInfo is failing in some way and perhaps you are not checking the return value for errors.


Having searched QualityCentral I suspect you have fallen victim to a known bug in older versions of Delphi: QC#3239. This is reported fixed in version 10.0.2124.6661 which is Delphi 2006.


Your comments confirm this diagnosis. To fix the problem you'll need a new TMonitorInfoEx definition. Here's one that will work on your pre-Unicode Delphi:

type
  TMonitorInfoEx = record
    cbSize: DWORD;
    rcMonitor: TRect;
    rcWork: TRect;
    dwFlags: DWORD;
    szDevice: array[0..CCHDEVICENAME - 1] of AnsiChar;
  end;

如果您将其添加到上面的代码中(当然在声明变量之前),那么我相信它会解决您的问题。

<小时/>

有趣的是,即使在 XE3 中,这些结构也没有被正确翻译:QC#114460 。诚然,这个错误是相当良性的,因为它只影响 PMonitorInfoExATMonitorInfoExA,但这个错误让我在尝试解决这个问题时陷入困境!

关于delphi - 需要在windows中解析HMONITOR --> deviceName(或deviceName --> HMONITOR),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15746286/

相关文章:

visual-studio-2010 - Visual Studio 2012 中的 DEF 文件语法错误

delphi - 三重等式表达式求值

delphi - 任何 TControl 的下拉菜单

c# - 在没有进程引用它后删除 "in use"文件

windows-7 - 如何在 Windows 7 上使用 Python 3 和 httplib2 调用 AWS?

java - 安装sdk后启动Eclipse出错

c# - 在 VS 2008 中创建基于服务的数据库并在 Windows 7 上使用 SQL Server Express 2005 时出现用户实例失败错误

delphi - Indy的TIdHTTPProxyServer : How to filter requests?

delphi - 对于 "Form1.MousePreview:=true"这样的问题有解决方法吗?

c++ - 搜索 winapi 函数