Функция EnumDisplayDevices не работает для меня - PullRequest
4 голосов
/ 02 марта 2012

Я пытаюсь получить информацию о моих мониторах программно.Содержимое циклов сейчас не важно, они просто содержат отладочные операторы, которые будут напечатаны при выполнении условия цикла.Прямо сейчас, код внешнего цикла выполняется три раза, а код внутреннего цикла никогда не доступен, что означает, что условие 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++;
    }

Ответы [ 2 ]

9 голосов
/ 02 марта 2012

Проблема заключается в передаче dd во внутренний вызов при использовании члена dd в качестве входной строки. Я знаю, что это не имеет смысла, но я подозреваю, что, поскольку dd является выходным параметром, API записывает в него, а затем просматривает содержимое входного параметра после того, как он на нем набросал. Это может произойти, если они выполнили что-то вроде memset'а, установив выходной параметр в 0 перед выполнением для здравомыслия.

Просто убедитесь, что дело не в отправке непустого дд, я сделал второй дд с точно такими же битами, и все по-прежнему работает нормально. Это определенно псевдоним памяти.

#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
0 голосов
/ 02 марта 2012

Если вы программируете специально для Win7 и более поздних версий, возможно, вы захотите взглянуть на QueryDisplayConfig и связанные с ним функции.

...