2015-06-21 125 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),那么你应该请参阅您的显示器使用手册或联系制造商。

希望有所帮助。并抱歉迟到回复。

祝你好运。 :)