I'm trying to adjust my monitor brightness programmatically. After little bit of research, I came up with this link, and wrote the following code (mostly copy paste from other links that one lead me).
#include "Windows.h"
#include "WinUser.h"
#include "PhysicalMonitorEnumerationAPI.h"
#include "HighLevelMonitorConfigurationAPI.h"
#include <strsafe.h>
void ShowError(LPTSTR lpszFunction);
int main()
{
HMONITOR hMonitor = NULL;
DWORD cPhysicalMonitors;
LPPHYSICAL_MONITOR pPhysicalMonitors = NULL;
HWND hWnd = GetDesktopWindow();
// Get the monitor handle.
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
// Get the number of physical monitors.
BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors);
if (bSuccess)
{
// Allocate the array of PHYSICAL_MONITOR structures.
pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
if (pPhysicalMonitors != NULL)
{
// Get the array.
bSuccess = GetPhysicalMonitorsFromHMONITOR( hMonitor, cPhysicalMonitors, pPhysicalMonitors);
// Get physical monitor handle.
HANDLE hPhysicalMonitor = pPhysicalMonitors[0].hPhysicalMonitor;
LPDWORD pdwMinimumBrightness = NULL;
LPDWORD pdwCurrentBrightness = NULL;
LPDWORD pdwMaximumBrightness = NULL;
bSuccess = GetMonitorBrightness(hPhysicalMonitor, pdwMinimumBrightness, pdwCurrentBrightness, pdwMaximumBrightness);
if (bSuccess == FALSE)
{
ShowError(TEXT("GetMonitorBrightness"));
}
// Close the monitor handles.
bSuccess = DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);
// Free the array.
free(pPhysicalMonitors);
}
}
return 0;
}
void ShowError(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
This code crashes when executing this line:
bSuccess = GetMonitorBrightness(hPhysicalMonitor, pdwMinimumBrightness, pdwCurrentBrightness, pdwMaximumBrightness);
According to documentation, that function might not be supported.
If this function is supported, the GetMonitorCapabilities function returns the MC_CAPS_BRIGHTNESS flag.
So, in order to check that, I add the following block to my code, just before calling GetMonitorBrightness
.
LPDWORD pdwMonitorCapabilities = NULL;
LPDWORD pdwSupportedColorTemperatures = NULL;
bSuccess = GetMonitorCapabilities(hPhysicalMonitor, pdwMonitorCapabilities, pdwSupportedColorTemperatures);
if (bSuccess == FALSE)
{
ShowError(TEXT("GetMonitorCapabilities"));
}
Unfortunately after I added that block, I received the following error:
Again, according to documentation, GetMonitorCapabilities
function fails if the monitor does not support DDC/CI.
Then I checked if my monitor is supporting DDC/CI, and found out that it is. Moreover, when I manually disable DDC/CI support from monitor settings, previous error message switches to following one, so now I'm pretty sure my monitor has DDC/CI support.
I feel like I'm doing everything correct but apparently I'm not. In short, GetMonitorCapabilities
function fails with an error message that I can't give any meaning, and GetMonitorBrightness
function gets crashed.
Notes:
My monitor is Dell U2713H.
I'm on 64 bit Windows 7.
I'm using Microsoft Visual C++ Compiler 12.0 (x86)
LPDWORD
that got me confused. It is working perfectly now. – Bibliotherapy