【问题标题】:EnumDisplayDevices function not working for meEnumDisplayDevices 功能对我不起作用
【发布时间】:2012-03-20 10:13:04
【问题描述】:

我正在尝试以编程方式在我的显示器上获取信息。循环的内容现在并不重要,它们只包含在满足循环条件时将打印的调试语句。现在,外层循环代码执行了 3 次,而内层循环代码从未被访问过,这意味着(内层)循环的 while 条件永远不会为真,即调用失败。

我的问题是 Windows API 说,关于这个功能:

要获取有关显示监视器的信息,首先调用 EnumDisplayDevices 并将 lpDevice >设置为 NULL。然后调用 EnumDisplayDevices 并将 lpDevice 设置为 DISPLAY_DEVICE.DeviceName >从第一次调用 EnumDisplayDevices 并将 iDevNum 设置为零。那么 >DISPLAY_DEVICE.DeviceString 就是监视器名称。

...但即使完全按照它所说的去做,第二个 EnumDisplayDevices 调用总是失败?有什么见解???

我也在 windows xp 和 windows 7 上作为服务级别应用程序执行此操作,并获得相同的结果。当我尝试打印 dd.DeviceName 时,它​​给了我一个地址(例如:0x12cfa4),但这一定是函数在第二次调用时所期望的,因为 MSDN 说只需传入您的显示设备指针并将 .DeviceName 附加到它...

使用 C++(使用 Qt)、Windows API/MSDN 调用。

    DISPLAY_DEVICE dd;

    dd.cb = sizeof(DISPLAY_DEVICE);

    DWORD deviceNum = 0;
    while( EnumDisplayDevices(NULL, deviceNum, &dd, 0) ){
        qWarning() << "We've entered the outer loop.";

        while( EnumDisplayDevices(dd.DeviceName, 0, &dd, 0)){
            qWarning() << "We've entered the inner loop.";
        }

        deviceNum++;
    }

【问题讨论】:

    标签: c++ qt winapi windows-7 msdn


    【解决方案1】:

    问题是在使用“dd”的成员作为输入字符串时将“dd”传递给内部调用。我知道这没有意义,但我怀疑由于 dd 是一个输出参数,API 正在写入它,但是在输入参数的内容在其上乱写之后查看。如果他们在执行前将输出参数 memset 设置为 0,则可能会发生这种情况。

    只要确保它不是关于发送非空 dd 的东西,我制作了第二个 dd,其中包含完全相同的位,并且一切正常。肯定是别名记忆。

    #include <windows.h>
    #include <stdio.h>
    
    #pragma comment(lib, "user32.lib")
    
    void DumpDevice(const DISPLAY_DEVICE& dd, size_t nSpaceCount )
    {
        printf("%*sDevice Name: %s\n", nSpaceCount, "", dd.DeviceName );
        printf("%*sDevice String: %s\n", nSpaceCount, "", dd.DeviceString );
        printf("%*sState Flags: %x\n", nSpaceCount, "", dd.StateFlags );
        printf("%*sDeviceID: %s\n", nSpaceCount, "", dd.DeviceID );
        printf("%*sDeviceKey: ...%s\n\n", nSpaceCount, "", dd.DeviceKey+42 );
    }
    
    int main()
    {
        DISPLAY_DEVICE dd;
    
        dd.cb = sizeof(DISPLAY_DEVICE);
    
        DWORD deviceNum = 0;
        while( EnumDisplayDevices(NULL, deviceNum, &dd, 0) ){
            DumpDevice( dd, 0 );
            DISPLAY_DEVICE newdd = {0};
            newdd.cb = sizeof(DISPLAY_DEVICE);
            DWORD monitorNum = 0;
            while ( EnumDisplayDevices(dd.DeviceName, monitorNum, &newdd, 0))
            {
                DumpDevice( newdd, 4 );
                monitorNum++;
            }
            puts("");
            deviceNum++;
        }
    
        return 0;
    }
    

    我现在使用的盒子只有 1 个监视器,所以我无法验证内部循环,但我怀疑这很好,因为 'newdd' 永远不会在调用中得到别名。您还说您处于服务环境中-我不确定该 winstation 是否会限制您看到的有关显示器的内容-因此这也可能是一个问题;但我怀疑您至少应该仍然能够看到物理设备。在我的机器上,我得到:

    Device Name: \\.\DISPLAY1
    Device String: NVIDIA GeForce GTX 580
    State Flags: 8000005
    DeviceID: PCI\VEN_10DE&DEV_1080&SUBSYS_15803842&REV_A1
    DeviceKey: ...\Control\Video\{B0CDD262-FCFB-4FD4-A03C-54621896C9CD}\0000
    
       Device Name: \\.\DISPLAY1\Monitor0
       Device String: Generic PnP Monitor
       State Flags: 3
       DeviceID: MONITOR\DEL4016\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002
       DeviceKey: ...\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002
    
    Device Name: \\.\DISPLAY2
    Device String: NVIDIA GeForce GTX 580
    State Flags: 0
    DeviceID: PCI\VEN_10DE&DEV_1080&SUBSYS_15803842&REV_A1
    DeviceKey: ...\Control\Video\{B0CDD262-FCFB-4FD4-A03C-54621896C9CD}\0001
    
    Device Name: \\.\DISPLAYV1
    Device String: RDPDD Chained DD
    State Flags: 8
    DeviceID:
    DeviceKey: ...\Control\Video\{DEB039CC-B704-4F53-B43E-9DD4432FA2E9}\0000
    
    Device Name: \\.\DISPLAYV2
    Device String: RDP Encoder Mirror Driver
    State Flags: 200008
    DeviceID:
    DeviceKey: ...\Control\Video\{42cf9257-1d96-4c9d-87f3-0d8e74595f78}\0000
    
    Device Name: \\.\DISPLAYV3
    Device String: RDP Reflector Display Driver
    State Flags: 200008
    DeviceID:
    DeviceKey: ...\Control\Video\{b043b95c-5670-4f10-b934-8ed0c8eb59a8}\0000
    

    【讨论】:

    • 我刚写完差不多一样的东西。别名是问题。
    • 不确定这是否是您发布代码后发生的变化,但我发现在 MSVC2015 中,我不得不使用 %S 而不是 %s,因为 DeviceName、DeviceString 等是WCHAR 数组,我猜每隔一个字符就包含 /0 数据。
    【解决方案2】:

    如果你是专门为 Win7 及更高版本编写代码,你可能想看看QueryDisplayConfig 和相关函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-26
      • 1970-01-01
      • 2021-07-04
      • 2021-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多