Skip to content

Instantly share code, notes, and snippets.

@Aetopia
Created February 19, 2024 09:14
Show Gist options
  • Save Aetopia/cb85bb441637dfa4ee7515b210875fea to your computer and use it in GitHub Desktop.
Save Aetopia/cb85bb441637dfa4ee7515b210875fea to your computer and use it in GitHub Desktop.
Simple command line app to switch display modes on Windows via a CLI.
#include <windows.h>
LONG DisplayConfigSetDisplayMode(DISPLAYCONFIG_PATH_INFO *pPath, PDEVMODEW pDevMode, DWORD dwFlags)
{
DISPLAYCONFIG_SOURCE_DEVICE_NAME dcSourceDeviceName = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME),
.adapterId = pPath->sourceInfo.adapterId,
.id = pPath->sourceInfo.id}};
DisplayConfigGetDeviceInfo(&dcSourceDeviceName.header);
return ChangeDisplaySettingsExW(dcSourceDeviceName.viewGdiDeviceName, pDevMode, NULL, dwFlags, NULL);
}
VOID DisplayConfigOutputDisplayName(DISPLAYCONFIG_PATH_INFO *pPath)
{
DISPLAYCONFIG_SOURCE_DEVICE_NAME dcSourceDeviceName = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME),
.adapterId = pPath->sourceInfo.adapterId,
.id = pPath->sourceInfo.id}};
DisplayConfigGetDeviceInfo(&dcSourceDeviceName.header);
DISPLAYCONFIG_TARGET_DEVICE_NAME dcTargetDeviceName = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
.size = sizeof(DISPLAYCONFIG_TARGET_DEVICE_NAME),
.adapterId = pPath->targetInfo.adapterId,
.id = pPath->targetInfo.id}};
DisplayConfigGetDeviceInfo(&dcTargetDeviceName.header);
__builtin_printf("%ls\n", dcTargetDeviceName.flags.friendlyNameFromEdid
? dcTargetDeviceName.monitorFriendlyDeviceName
: dcSourceDeviceName.viewGdiDeviceName);
}
VOID DisplayConfigOutputDisplayModes(DISPLAYCONFIG_PATH_INFO *pPath)
{
DISPLAYCONFIG_SOURCE_DEVICE_NAME dcSourceDeviceName = {.header = {.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME,
.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME),
.adapterId = pPath->sourceInfo.adapterId,
.id = pPath->sourceInfo.id}};
DisplayConfigGetDeviceInfo(&dcSourceDeviceName.header);
DEVMODEW dm = {.dmSize = sizeof(DEVMODEW)};
DWORD iModeNum = 0;
while (EnumDisplaySettingsW(dcSourceDeviceName.viewGdiDeviceName, iModeNum, &dm))
{
if (!dm.dmDisplayFixedOutput)
__builtin_printf("\t%ld x %ld @ %ld Hz%s\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmDisplayFrequency,
dm.dmDisplayFlags ? " (Interlaced)" : "");
iModeNum++;
}
}
int wmain(int argc, wchar_t *wargv[])
{
UINT fArgument = 0;
if (CompareStringOrdinal(L"/enumerate", -1, wargv[1], -1, TRUE) == CSTR_EQUAL && argc == 2)
fArgument = 1;
else if (CompareStringOrdinal(L"/get", -1, wargv[1], -1, TRUE) == CSTR_EQUAL && argc == 3)
fArgument = 2;
else if (CompareStringOrdinal(L"/set", -1, wargv[1], -1, TRUE) == CSTR_EQUAL && argc == 7)
fArgument = 3;
else if (CompareStringOrdinal(L"/save", -1, wargv[1], -1, TRUE) == CSTR_EQUAL && argc == 7)
fArgument = 4;
else
{
__builtin_printf("DisplayConfig:\n\n"
"\t/Enumerate\n\t\tEnumerate displays.\n\n"
"\t/Get <Index>\n\t\tObtain display modes for a given display.\n\n"
"\t/Set <Index> <Width> <Height> <Refresh Rate> <Orientation>\n\t\tSet the display mode with "
"specified parameters.\n\n"
"\t/Save <Index> <Width> <Height> <Refresh Rate> <Orientation>\n\t\tSaves the specified "
"display mode to the registry.\n\n");
return 0;
}
UINT numPathArrayElements = 0, numModeInfoArrayElements = 0;
GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, &numModeInfoArrayElements);
HANDLE hHeap = GetProcessHeap();
DISPLAYCONFIG_PATH_INFO *pathArray = HeapAlloc(hHeap, 0, sizeof(DISPLAYCONFIG_PATH_INFO) * numPathArrayElements);
DISPLAYCONFIG_MODE_INFO *modeInfoArray =
HeapAlloc(hHeap, 0, sizeof(DISPLAYCONFIG_MODE_INFO) * numModeInfoArrayElements);
QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &numPathArrayElements, pathArray, &numModeInfoArrayElements,
modeInfoArray, NULL);
switch (fArgument)
{
case 1: {
for (UINT32 nIndex = 0; nIndex < numPathArrayElements; nIndex++)
{
__builtin_printf("%d : ", nIndex);
DisplayConfigOutputDisplayName(&pathArray[nIndex]);
}
}
break;
case 2: {
LONG nIndex = _wtol(wargv[2]);
if (numPathArrayElements - 1 >= nIndex)
DisplayConfigOutputDisplayModes(&pathArray[nIndex]);
else
__builtin_printf("Error: Invalid Display Index.");
}
break;
case 3:
case 4: {
LONG nIndex = _wtol(wargv[2]);
DEVMODEW dm = {.dmSize = sizeof(DEVMODEW),
.dmPelsWidth = _wtol(wargv[3]),
.dmPelsHeight = _wtol(wargv[4]),
.dmDisplayFrequency = _wtol(wargv[5]),
.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYORIENTATION};
if (CompareStringOrdinal(L"landscape", -1, wargv[6], -1, TRUE) == CSTR_EQUAL)
dm.dmDisplayOrientation = DMDO_DEFAULT;
else if (CompareStringOrdinal(L"landscape-flipped", -1, wargv[6], -1, TRUE) == CSTR_EQUAL)
dm.dmDisplayOrientation = DMDO_180;
else if (CompareStringOrdinal(L"portrait", -1, wargv[6], -1, TRUE) == CSTR_EQUAL)
dm.dmDisplayOrientation = DMDO_90;
else if (CompareStringOrdinal(L"portrait-flipped", -1, wargv[6], -1, TRUE) == CSTR_EQUAL)
dm.dmDisplayOrientation = DMDO_270;
if (numPathArrayElements - 1 >= nIndex)
if (DisplayConfigSetDisplayMode(&pathArray[nIndex], &dm, CDS_TEST))
__builtin_printf("Error: Invalid Display Mode.");
else
DisplayConfigSetDisplayMode(&pathArray[nIndex], &dm, fArgument == 3 ? 0 : CDS_UPDATEREGISTRY);
else
__builtin_printf("Error: Invalid Display Index.");
}
break;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment