2015-06-21 5 views
13

Sto tentando di ottenere/impostare il livello di luminosità del monitor tramite l'API di Windows. Ho provato sia il Low-Level Monitor Configuration Functions e il High-Level Monitor Configuration Functions, ma entrambi sembrano rompere nello stesso posto. In entrambi i casi non ho problemi a ottenere l'handle di HMONITOR e ad ottenere l'handle del monitor fisico da HMONITOR, ma quando provo a interrogare le funzionalità DDC/CI, viene visualizzato un errore "An error occurred while transmitting data to the device on the I2C bus."Errore I2C quando si utilizzano le funzioni di configurazione del monitor di Windows

Le funzioni particolari che causano questo errore è GetMonitorCapabilities per le funzioni di alto livello e GetCapabilitiesStringLength per le funzioni di basso livello. Entrambi causano lo stesso errore.

Questo mi porta a credere che forse il mio monitor non supporta DDC/CI, ma so che la luminosità del monitor del mio portatile può essere cambiata attraverso il pannello di controllo, quindi in qualche modo deve essere controllata tramite software. Inoltre, posso utilizzare correttamente le classi WMI in uno script PowerShell per ottenere/impostare la luminosità come descritto nella pagina this. La maggior parte delle cose che ho letto suggeriscono che la maggior parte dei moderni schermi per laptop supporta DDC/CI.

C'è un modo per scoprire che cosa sta causando questo errore o per ottenere ulteriori informazioni su di esso? Attualmente sto lavorando in C++ in Visual Studio 2013 su Windows 7. Potrei probabilmente usare WMI nel mio programma C++ se non riesco a far funzionare questo metodo corrente, ma ho pensato di chiederlo prima.

Ecco il codice ho attualmente:

#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; 
} 

Edit: Anche Vorrei sottolineare che physicalMonitors[0].hPhysicalMonitor è 0, anche se il numero di monitor e descrizione del testo sono validi e la funzione GetPhysicalMonitorsFromHMONITOR restituisce con successo. Qualche idea sul perché questo potrebbe essere?

+0

Hai provato a chiamare direttamente GetMonitorBrightness/SetMonitorBrightness?Non hai assolutamente bisogno di richiedere le funzionalità –

+0

Hai provato questo codice con lo stesso monitor su una scheda video diversa o con un monitor che sai funzionare tramite questa API? Il livello i2c viene gestito interamente dall'hardware sulla scheda che comunica attraverso l'interconnessione al monitor. È necessario che il driver supporti il ​​passaggio dei comandi api al master i2c di bordo. A seconda della scheda, mfgr potrebbe essere stata implementata correttamente o meno. Nota: la certificazione WHQL richiede l'implementazione del passthrough I2C sul monitor. I tuoi dispositivi e driver sono certificati? – caskey

risposta

8

Questo è un problema "hardware insoddisfacente", il bus I2C di cui parla è la logica interconnessione tra la scheda video e il monitor. Utile principalmente per la riproduzione della spina &. Il codice di errore sottostante è 0xC01E0582, STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA. Viene generato da un DxgkDdiI2CTransmitDataToDisplay() helper function nel driver miniport video. È compito del video driver del fornitore configurarlo, fornendo le funzioni che solleticano il bus e implementare il sottocampo IOCTL GetMonitorCapabilities().

Ovviamente qui si trova il driver del dispositivo, non c'è nulla che si possa fare per questo errore nel programma C++. Puoi girare casualmente la ruota della fortuna cercando un aggiornamento del driver dal produttore della scheda video. Ma non zero probabilità che il monitor sia in errore qui. Prova prima un altro.

+0

Grazie per il vostro aiuto e per avermi indicato un codice di errore più dettagliato. Esiste un modo più "best practice" per fare ciò che sto cercando di fare? O semplicemente non c'è un ottimo modo per farlo dal software? –

+1

Non ho idea * perché * devi scrivere questo codice. Mi sembra che tu sia solo sfortunato. –

1

So che è il momento sbagliato per rispondere ma ho pensato che dovresti saperlo.

Il problema che si sta affrontando è dovuto al DDC/CI disabilitato sul monitor, quindi è necessario andare alle impostazioni del monitor e controllare se DDC/CI è disabilitato e se lo è, quindi è necessario abilitarlo ed eseguire il codice di nuovo. Funzionerebbe. Se non si è in grado di trovare l'opzione DDC/CI (alcuni monitor hanno un pulsante separato per abilitare/disabilitare DDC/CI come il monitor T71W di Benq ha un pulsante freccia in giù separato per abilitare/disabilitare DDC/CI) quindi si dovrebbe fare riferimento al manuale del monitor o contattare il produttore.

Spero che questo aiuti. e scusa per la risposta in ritardo.

Buona fortuna. :)