2012-03-01 46 views
4

我試圖以編程方式在我的監視器上獲取信息。循環的內容現在並不重要,它們只包含在滿足循環條件時將打印的調試語句。現在,外部循環代碼執行三次,而內部循環代碼從未被訪問,這意味着(內部)循環的while條件從不爲真,這意味着調用失敗。EnumDisplayDevices函數不適合我

我在這裏的問題是,在Windows API稱,關於此功能:

爲了獲得一個顯示器上lpDevice,第一個電話EnumDisplayDevices>設置爲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++; 
    } 

回答

9

問題是在使用'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 
+0

我剛剛寫完很多相同的東西。別名是問題。 – arx 2012-03-01 22:06:43

+0

不知道這是自發布代碼以來發生了什麼變化,但我發現在MSVC2015中,我必須使用%S而不是%s,因爲DeviceName,DeviceString等是WCHAR數組,我猜想包含/ 0數據在每秒字符中。 – scone 2016-02-09 00:24:17