2015-06-21 127 views
13

我試圖通過Windows API獲取/設置顯示器的亮度級別。我已經嘗試了Low-Level Monitor Configuration FunctionsHigh-Level Monitor Configuration Functions,但他們似乎都在同一個地方。在這兩種情況下,獲取HMONITOR手柄並從HMONITOR獲取物理監視器手柄都沒有問題,但是一旦我嘗試查詢DDC/CI功能,就會看到一條錯誤消息:「An error occurred while transmitting data to the device on the I2C bus.使用Windows顯示器配置功能時發生I2C錯誤

對於高級函數,此錯誤爲GetMonitorCapabilities,對於低級函數爲GetCapabilitiesStringLength。他們都造成相同的錯誤。

這使我相信,也許我的顯示器不支持DDC/CI,但我知道我的筆記本電腦的顯示屏亮度可以通過控制面板來改變,所以它必須通過某種方式的軟件進行控制。另外,我可以在PowerShell腳本中成功使用WMI類來獲取/設置this頁面上描述的亮度。我讀過的大部分內容都表明,大多數現代筆記本電腦屏幕都支持DDC/CI。

有什麼方法可以找出是什麼導致這個錯誤或獲得更多關於它的信息?我目前在Windows 7的Visual Studio 2013中使用C++。如果我無法獲取當前的方法,我可能會在我的C++程序中使用WMI,但我想我會先問這裏。

這是我目前擁有的代碼:

#include "stdafx.h" 
#include <windows.h> 
#include <highlevelmonitorconfigurationapi.h> 
#include <lowlevelmonitorconfigurationapi.h> 
#include <physicalmonitorenumerationapi.h> 
#include <iostream> 
#include <string> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    DWORD minBrightness, curBrightness, maxBrightness; 
    HWND curWin = GetConsoleWindow(); 
    if (curWin == NULL) { 
    std::cout << "Problem getting a handle to the window." << std::endl; 
    return 1; 
    } 

    // Call MonitorFromWindow to get the HMONITOR handle 
    HMONITOR curMon = MonitorFromWindow(curWin, MONITOR_DEFAULTTONULL); 
    if (curMon == NULL) { 
    std::cout << "Problem getting the display monitor" << std::endl; 
    return 1; 
    } 

    // Call GetNumberOfPhysicalMonitorsFromHMONITOR to get the needed array size 
    DWORD monitorCount; 
    if (!GetNumberOfPhysicalMonitorsFromHMONITOR(curMon, &monitorCount)) { 
    std::cout << "Problem getting the number of physical monitors" << std::endl; 
    return 1; 
    } 

    // Call GetPhysicalMonitorsFromHMONITOR to get a handle to the physical monitor 
    LPPHYSICAL_MONITOR physicalMonitors = (LPPHYSICAL_MONITOR)malloc(monitorCount*sizeof(PHYSICAL_MONITOR)); 
    if (physicalMonitors == NULL) { 
    std::cout << "Unable to malloc the physical monitor array." << std::endl; 
    return 1; 
    } 
    if (!GetPhysicalMonitorsFromHMONITOR(curMon, monitorCount, physicalMonitors)) { 
    std::cout << "Problem getting the physical monitors." << std::endl; 
    return 1; 
    } 

    std::cout << "Num Monitors: " << monitorCount << std::endl; // This prints '1' as expected. 
    wprintf(L"%s\n", physicalMonitors[0].szPhysicalMonitorDescription); // This prints "Generic PnP Monitor" as expected 

    // Call GetMonitorCapabilities to find out which functions it supports 
    DWORD monCaps; 
    DWORD monColorTemps; 
    // The following function call fails with the error "An error occurred while transmitting data to the device on the I2C bus." 
    if (!GetMonitorCapabilities(physicalMonitors[0].hPhysicalMonitor, &monCaps, &monColorTemps)) { 
    std::cout << "Problem getting the monitor's capabilities." << std::endl; 
    DWORD errNum = GetLastError(); 
    DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; 
    LPVOID buffer; 
    FormatMessage(flags, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&buffer, 0, NULL); 
    wprintf(L"%s\n", buffer); 
    return 1; 
    } 
    // Same error when I use GetCapabilitiesStringLength(...) here. 

    // More code that is currently never reached... 

    return 0; 
} 

編輯:我也應該注意到,physicalMonitors[0].hPhysicalMonitor爲0,即使監視器數量和文字說明是有效的和GetPhysicalMonitorsFromHMONITOR函數成功返回。任何想法爲什麼這可能是?

+0

您是否嘗試直接調用GetMonitorBrightness/SetMonitorBrightness?您並不一定需要查詢功能 –

+0

您是否曾嘗試使用同一臺顯示器在不同視頻卡上顯示代碼,或者您是否知道通過此api工作的顯示器? i2c層完全由卡上的硬件通過與顯示器的互連進行通信來處理。您需要驅動程序支持將api命令傳遞給板載i2c主設備。根據卡製造商這可能或可能沒有正確實施。注意:WHQL認證要求對監視器實施I2C直通。您的設備和驅動程序已通過認證 – caskey

回答

8

這是一個「靠不住硬件」問題,談到了I2C總線是視頻適配器和顯示器之間的邏輯互連。主要用於插播&播放。底層的錯誤代碼是0xC01E0582,STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA。它由視頻微型端口驅動程序中的DxgkDdiI2CTransmitDataToDisplay() helper function生成。這是供應商的視頻驅動程序工作來配置它,提供令總線發癢的功能以及實現基本GetMonitorCapabilities()的IOCTL。

顯然你是設備驅動程序的土地在這裏,沒有什麼可以做,這個失敗在你的C++程序。您可以通過從視頻適配器製造商處查找驅動程序更新來隨機旋轉命運。但是顯示器在這裏出現故障的可能性非零。先試試另一個。

+0

感謝您的幫助,並指出我更詳細的錯誤代碼。有沒有更「最佳實踐」的方式來做我想做的事情?或者,有沒有一種很好的方式來從軟件中做到這一點? –

+1

不知道*爲什麼*您必須編寫此代碼。聽起來你是不吉利的。 –

1

我知道它不好回覆,但我想你應該知道。

您面臨的問題是因爲您的顯示器上禁用了D​​DC/CI,所以您應該轉到顯示器設置並檢查DDC/CI是否被禁用,如果是,那麼您必須啓用它並運行再次編碼。它會工作。如果你無法找到DDC/CI選項(某些顯示器有一個單獨的啓用/禁用DDC/CI的按鈕,如Benq的T71W顯示器有一個單獨的向下箭頭按鈕來啓用/禁用DDC/CI),那麼你應該請參閱您的顯示器使用手冊或聯繫製造商。

希望有所幫助。並抱歉遲到回覆。

祝你好運。 :)