Skip to content

Instantly share code, notes, and snippets.

@GeeLaw
Created March 23, 2024 03:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save GeeLaw/11799094e137a4f60590a5b7162ba933 to your computer and use it in GitHub Desktop.
Save GeeLaw/11799094e137a4f60590a5b7162ba933 to your computer and use it in GitHub Desktop.
Compute the display orientation of the current thread using plain old Win32 API.
/* SPDX-License-Identifier: MIT
Copyright (c) 2024 by Ji Luo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
Echoes the current display resolution and orientations.
See
Raymond Chen,
"Using the DisplayInformation class from a desktop Win32 application, part 2",
https://devblogs.microsoft.com/oldnewthing/20240321-00/?p=109558
cl.exe /std:c++20 dispornt.cpp && cls && dispornt.exe
*/
#include<cstdio>
#include<cstdint>
#include<windows.h>
#pragma comment(lib, "user32")
typedef unsigned DisplayOrientations;
constexpr DisplayOrientations DO_None = 0;
constexpr DisplayOrientations DO_L = 1;
constexpr DisplayOrientations DO_P = 2;
constexpr DisplayOrientations DO_LF = 4;
constexpr DisplayOrientations DO_PF = 8;
char const * const DO_Names[] =
{ "L", "P", "LF", "PF", nullptr };
int main()
{
while (true)
{
DEVMODEW dm { .dmSize = sizeof(DEVMODEW) };
if (!EnumDisplaySettingsExW(
nullptr,
ENUM_CURRENT_SETTINGS,
&dm,
EDS_RAWMODE | EDS_ROTATEDMODE)
)
{
std::fputs("EnumDisplaySettingsExW failed.\n", stderr);
return -1;
}
if ((dm.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT))
!= (DM_PELSWIDTH | DM_PELSHEIGHT)
)
{
std::fputs("Returned result does not contain resolution.\n", stderr);
return -2;
}
dm.dmDisplayOrientation &= (
(dm.dmFields & DM_DISPLAYORIENTATION) == DM_DISPLAYORIENTATION
? 3 : 0
); // ^^^ I am not sure if this guard is necessary.
// Infer the orientation at rotation degree 0.
auto const initial = (
// dmPelsWidth <=> dmPelsHeight is landscape/portrait after rotation.
// dmDisplayOrientation is rotation / (-pi/2).
((dm.dmPelsWidth > dm.dmPelsHeight) ^ (dm.dmDisplayOrientation & 1))
? DO_L
: ((dm.dmPelsWidth < dm.dmPelsHeight) ^ (dm.dmDisplayOrientation & 1))
? DO_P
: (DO_L | DO_P)
/* ^^^
** The documentation does not specify what happens
** when the resolution is square.
** Since DisplayOrientations is a [Flags] enumeration,
** the sane result is a bitwise combination of both.
*/
);
// Compute the orientation at current rotation.
// The significance of bits in DisplayOrientation
// is modulo 4 (plus 1 for every 90 degree clockwise),
// consistent with the numeric value of dmDisplayOrientation.
auto const current = ((
(initial << dm.dmDisplayOrientation) |
(initial >> (4 - dm.dmDisplayOrientation))
) & 15u);
// Boring exercise of printing...
std::printf("w=%u, h=%u, o=degree(%d)\n",
(unsigned)dm.dmPelsWidth,
(unsigned)dm.dmPelsHeight,
(int)dm.dmDisplayOrientation * 90
);
std::fputs("DisplayOrientations = ", stdout);
bool already1 = false;
for (int i = 0; DO_Names[i]; ++i)
{
if (current & (1u << i))
{
if (already1)
{
std::putchar(',');
std::putchar(' ');
}
already1 = true;
std::fputs(DO_Names[i], stdout);
}
}
std::puts(already1 ? "\n" : "N\n");
Sleep(1000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment