1e42bc8e4f
[Git2Git] Git Train: Merge of building/rs_onecore_dep_uxp/201117-2002 into official/rs_onecore_dep_uxp Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_onecore_dep_uxp 526043ab6050397506b3cdb77e6a43b5ca9a2e9a Related work items: MSFT-29990377
330 lines
11 KiB
C++
330 lines
11 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include <precomp.h>
|
|
|
|
#include <windowsinternalstring.h>
|
|
|
|
using namespace wil;
|
|
using namespace wistd;
|
|
using namespace std;
|
|
using namespace Windows::Internal;
|
|
|
|
#define CONSOLE_WINDOW_FLAGS (WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL)
|
|
#define CONSOLE_WINDOW_EX_FLAGS (WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES | WS_EX_APPWINDOW)
|
|
|
|
void PrintRect(LPCWSTR pwszLabel, RECT& rc)
|
|
{
|
|
LocalMemNativeString foo;
|
|
foo.InitializeFormat(L" L: %5d R: %5d T: %5d B: %5d (W: %5d H: %5d)", rc.left, rc.right, rc.top, rc.bottom, rc.right - rc.left, rc.bottom - rc.top);
|
|
|
|
wcout << pwszLabel << " (exclusive rect)" << endl;
|
|
wcout << foo.Get() << endl;
|
|
}
|
|
|
|
void PrintRect(LPCWSTR pwszLabel, SMALL_RECT& rc)
|
|
{
|
|
LocalMemNativeString foo;
|
|
foo.InitializeFormat(L" L: %5d R: %5d T: %5d B: %5d (W: %5d H: %5d)", rc.Left, rc.Right, rc.Top, rc.Bottom, rc.Right - rc.Left + 1, rc.Bottom - rc.Top + 1);
|
|
|
|
wcout << pwszLabel << " (inclusive rect)" << endl;
|
|
wcout << foo.Get() << endl;
|
|
}
|
|
|
|
void PrintSize(LPCWSTR pwszLabel, COORD& sz)
|
|
{
|
|
LocalMemNativeString foo;
|
|
foo.InitializeFormat(L"%37s(W: %5d H: %5d)", L"", sz.X, sz.Y);
|
|
|
|
wcout << pwszLabel << endl;
|
|
wcout << foo.Get() << endl;
|
|
}
|
|
|
|
void PrintSize(LPCWSTR pwszLabel, SIZE& sz)
|
|
{
|
|
LocalMemNativeString foo;
|
|
foo.InitializeFormat(L"%37s(W: %5d H: %5d)", L"", sz.cx, sz.cy);
|
|
|
|
wcout << pwszLabel << endl;
|
|
wcout << foo.Get() << endl;
|
|
}
|
|
|
|
HRESULT PrintMonitorInfo(LPCWSTR pwszLabel, HMONITOR hmon)
|
|
{
|
|
MONITORINFOEXW mi;
|
|
mi.cbSize = sizeof(mi);
|
|
RETURN_IF_WIN32_BOOL_FALSE(GetMonitorInfoW(hmon, &mi));
|
|
|
|
bool const IsPrimary = mi.dwFlags & MONITORINFOF_PRIMARY;
|
|
|
|
wcout << pwszLabel << endl;
|
|
wcout << "- Monitor Name: " << mi.szDevice << endl;
|
|
wcout << "- Is Primary? " << IsPrimary << endl;
|
|
PrintRect(L"- Monitor Rect:", mi.rcMonitor);
|
|
PrintRect(L"- Work Rect:", mi.rcWork);
|
|
|
|
SIZE sz;
|
|
RETURN_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, (UINT*)&sz.cx, (UINT*)&sz.cy));
|
|
PrintSize(L"Effective DPI:", sz);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CALLBACK MonitorEnumProc(
|
|
_In_ HMONITOR hMonitor,
|
|
_In_ HDC /*hdcMonitor*/,
|
|
_In_ LPRECT /*lprcMonitor*/,
|
|
_In_ LPARAM /*dwData*/
|
|
)
|
|
{
|
|
PrintMonitorInfo(L"--- Monitor ---", hMonitor);
|
|
wcout << endl;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL s_AdjustWindowRectEx(_Inout_ LPRECT prc, const DWORD dwStyle, const BOOL fMenu, const DWORD dwExStyle)
|
|
{
|
|
return AdjustWindowRectEx(prc, dwStyle, fMenu, dwExStyle);
|
|
}
|
|
|
|
BOOL s_UnadjustWindowRectEx(_Inout_ LPRECT prc, const DWORD dwStyle, const BOOL fMenu, const DWORD dwExStyle)
|
|
{
|
|
RECT rc;
|
|
SetRectEmpty(&rc);
|
|
BOOL fRc = s_AdjustWindowRectEx(&rc, dwStyle, fMenu, dwExStyle);
|
|
if (fRc)
|
|
{
|
|
prc->left -= rc.left;
|
|
prc->top -= rc.top;
|
|
prc->right -= rc.right;
|
|
prc->bottom -= rc.bottom;
|
|
}
|
|
return fRc;
|
|
}
|
|
|
|
BOOL s_AdjustWindowRectExForDpi(_Inout_ LPRECT prc, const DWORD dwStyle, const BOOL fMenu, const DWORD dwExStyle, _In_ UINT dpi)
|
|
{
|
|
return AdjustWindowRectExForDpi(prc, dwStyle, fMenu, dwExStyle, dpi);
|
|
}
|
|
|
|
BOOL s_UnadjustWindowRectExForDpi(_Inout_ LPRECT prc, const DWORD dwStyle, const BOOL fMenu, const DWORD dwExStyle, _In_ UINT dpi)
|
|
{
|
|
RECT rc;
|
|
SetRectEmpty(&rc);
|
|
BOOL fRc = s_AdjustWindowRectExForDpi(&rc, dwStyle, fMenu, dwExStyle, dpi);
|
|
if (fRc)
|
|
{
|
|
prc->left -= rc.left;
|
|
prc->top -= rc.top;
|
|
prc->right -= rc.right;
|
|
prc->bottom -= rc.bottom;
|
|
}
|
|
return fRc;
|
|
}
|
|
|
|
int __cdecl wmain(int /*argc*/, WCHAR* /*argv*/[])
|
|
{
|
|
// set this or we'll get false values when asking for the DPI.
|
|
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
|
|
|
HANDLE hOut = CreateFileW(L"CONOUT$",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE,
|
|
0,
|
|
OPEN_EXISTING,
|
|
0,
|
|
0);
|
|
|
|
RETURN_IF_HANDLE_INVALID(hOut);
|
|
|
|
HWND hwnd = GetConsoleWindow();
|
|
wcout << "Console Window Handle: " << hwnd << endl;
|
|
|
|
HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
RETURN_IF_HANDLE_NULL(hmon);
|
|
|
|
UINT dpix;
|
|
UINT dpiy;
|
|
RETURN_IF_FAILED(GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy));
|
|
|
|
RECT rc = { 0 };
|
|
RETURN_IF_WIN32_BOOL_FALSE(GetWindowRect(hwnd, &rc));
|
|
|
|
PrintRect(L"Window Rect:", rc);
|
|
|
|
RECT rcWindow = rc;
|
|
|
|
RETURN_IF_WIN32_BOOL_FALSE(s_UnadjustWindowRectEx(&rc, CONSOLE_WINDOW_FLAGS, FALSE, CONSOLE_WINDOW_EX_FLAGS));
|
|
PrintRect(L"Adjusted Window Rect (unscaled):", rc);
|
|
|
|
rc = rcWindow;
|
|
RETURN_IF_WIN32_BOOL_FALSE(s_UnadjustWindowRectExForDpi(&rc, CONSOLE_WINDOW_FLAGS, FALSE, CONSOLE_WINDOW_EX_FLAGS, dpix));
|
|
PrintRect(L"Adjusted Window Rect (scaled):", rc);
|
|
|
|
SIZE szClient;
|
|
szClient.cx = rc.right - rc.left;
|
|
szClient.cy = rc.bottom - rc.top;
|
|
|
|
RETURN_IF_WIN32_BOOL_FALSE(GetClientRect(hwnd, &rc));
|
|
|
|
PrintRect(L"Client Rect:", rc);
|
|
|
|
SIZE sz = { 0 };
|
|
sz.cx = GetSystemMetrics(SM_CXHSCROLL);
|
|
sz.cy = GetSystemMetrics(SM_CYVSCROLL);
|
|
|
|
PrintSize(L"Scroll Bar Reservations (unscaled):", sz);
|
|
|
|
HMODULE hUser32 = LoadLibraryW(L"user32.dll");
|
|
typedef int (*PfnGetDpiMetrics)(int nIndex, int dpi);
|
|
bool fGotMetrics = false;
|
|
|
|
if (hUser32 != nullptr)
|
|
{
|
|
pfn = (PfnGetDpiMetrics)GetProcAddress(hUser32, "GetSystemMetricsForDpi");
|
|
|
|
if (pfn != nullptr)
|
|
{
|
|
sz.cx = (SHORT)pfn(SM_CXVSCROLL, dpix);
|
|
sz.cy = (SHORT)pfn(SM_CYHSCROLL, dpiy);
|
|
fGotMetrics = true;
|
|
}
|
|
}
|
|
|
|
if (!fGotMetrics)
|
|
{
|
|
sz.cx = (SHORT)GetSystemMetrics(SM_CXVSCROLL);
|
|
sz.cy = (SHORT)GetSystemMetrics(SM_CYHSCROLL);
|
|
}
|
|
|
|
PrintSize(L"Scroll Bar Reservations (scaled):", sz);
|
|
|
|
SIZE szScrollScaled = sz;
|
|
|
|
COORD coordFont = GetConsoleFontSize(hOut, 0);
|
|
|
|
PrintSize(L"Font Size (unscaled):", coordFont);
|
|
|
|
sz.cx = MulDiv(coordFont.X, dpix, 96);
|
|
sz.cy = MulDiv(coordFont.Y, dpiy, 96);
|
|
|
|
PrintSize(L"Font Size (scaled):", sz);
|
|
|
|
SIZE szFontScaled = sz;
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFOEX csbiex = { 0 };
|
|
csbiex.cbSize = sizeof(csbiex);
|
|
|
|
if (!GetConsoleScreenBufferInfoEx(hOut, &csbiex))
|
|
{
|
|
wcout << GetLastError() << endl;
|
|
}
|
|
|
|
PrintRect(L"Viewport (chars):", csbiex.srWindow);
|
|
PrintSize(L"Max Window Size (chars):", csbiex.dwMaximumWindowSize);
|
|
PrintSize(L"Cursor Pos (chars):", csbiex.dwCursorPosition);
|
|
PrintSize(L"Buffer Size (chars):", csbiex.dwSize);
|
|
|
|
PrintMonitorInfo(L"Primary Monitor Data:", hmon);
|
|
|
|
wcout << endl;
|
|
|
|
wcout << "All monitors data:" << endl;
|
|
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, NULL);
|
|
|
|
wcout << "------ MATH ------" << endl;
|
|
|
|
if (szFontScaled.cx != 0 && szFontScaled.cy != 0)
|
|
{
|
|
SIZE szCharFit;
|
|
szCharFit.cx = szClient.cx / szFontScaled.cx;
|
|
szCharFit.cy = szClient.cy / szFontScaled.cy;
|
|
SIZE szCharLeftover;
|
|
szCharLeftover.cx = szClient.cx % szFontScaled.cx;
|
|
szCharLeftover.cy = szClient.cy % szFontScaled.cy;
|
|
bool fHorizScroll = (csbiex.dwSize.X > (szClient.cx / szFontScaled.cx));
|
|
bool fVertScroll = (csbiex.dwSize.Y > (szClient.cy / szFontScaled.cy));
|
|
|
|
wcout << "Start with adjusted window dimensions (scaled for DPI). We take the outer window rect and ask the system to scale it down to what we could use for a client." << endl
|
|
<< endl;
|
|
wcout << "Width: " << endl;
|
|
wcout << " Window Adjusted: " << szClient.cx << endl;
|
|
wcout << " / Font : " << szFontScaled.cx << endl;
|
|
wcout << " = " << szCharFit.cx << " chars";
|
|
wcout << " with " << szCharLeftover.cx << " pixels leftover" << endl;
|
|
wcout << "This is the number of characters we could fit in the window if Vertical doesn't need its scroll bar." << endl;
|
|
wcout << "Now check if we will need to steal some of Vertical's space for our Horizontal scroll bar." << endl;
|
|
wcout << " Is < buffer of : " << csbiex.dwSize.X << endl;
|
|
wcout << " H-scroll needed= " << fHorizScroll << endl;
|
|
wcout << endl;
|
|
wcout << "Height: " << endl;
|
|
wcout << " Window Adjusted: " << szClient.cy << endl;
|
|
wcout << " / Font : " << szFontScaled.cy << endl;
|
|
wcout << " = " << szCharFit.cy << " chars";
|
|
wcout << " with " << szCharLeftover.cy << " pixels leftover" << endl;
|
|
wcout << "This is the number of characters we could fit in the window if Horizontal doesn't need its scroll bar." << endl;
|
|
wcout << "Now check if we will need to steal some of Horizontal's space for our Vertical scroll bar." << endl;
|
|
wcout << " Is < buffer of : " << csbiex.dwSize.Y << endl;
|
|
wcout << " V-scroll needed= " << fVertScroll << endl;
|
|
wcout << endl;
|
|
|
|
SIZE szAvailableClient;
|
|
szAvailableClient = szClient;
|
|
|
|
SIZE szRemoveBars;
|
|
szRemoveBars.cx = fVertScroll ? szScrollScaled.cx : 0;
|
|
szRemoveBars.cy = fHorizScroll ? szScrollScaled.cy : 0;
|
|
|
|
szAvailableClient.cx -= szRemoveBars.cx;
|
|
szAvailableClient.cy -= szRemoveBars.cy;
|
|
|
|
SIZE szCharFinal;
|
|
szCharFinal.cx = szAvailableClient.cx / szFontScaled.cx;
|
|
szCharFinal.cy = szAvailableClient.cy / szFontScaled.cy;
|
|
|
|
SIZE szCharLeftoverFinal;
|
|
szCharLeftoverFinal.cx = szAvailableClient.cx % szFontScaled.cx;
|
|
szCharLeftoverFinal.cy = szAvailableClient.cy % szFontScaled.cy;
|
|
|
|
wcout << "Now math out the space we actually have for the viewport with scroll bars if necessary." << endl
|
|
<< endl;
|
|
wcout << "Width: " << endl;
|
|
wcout << " Window Adjusted: " << szClient.cx << endl;
|
|
wcout << " - Vert Scroll : " << szRemoveBars.cx << endl;
|
|
wcout << " = " << szAvailableClient.cx << endl;
|
|
wcout << " / Font : " << szFontScaled.cx << endl;
|
|
wcout << " = " << szCharFinal.cx << " chars";
|
|
wcout << " with " << szCharLeftoverFinal.cx << " pixels leftover" << endl;
|
|
wcout << endl;
|
|
wcout << "Height: " << endl;
|
|
wcout << " Window Adjusted: " << szClient.cy << endl;
|
|
wcout << " - Horiz Scroll : " << szRemoveBars.cy << endl;
|
|
wcout << " = " << szAvailableClient.cy << endl;
|
|
wcout << " / Font : " << szFontScaled.cy << endl;
|
|
wcout << " = " << szCharFinal.cy << " chars";
|
|
wcout << " with " << szCharLeftoverFinal.cy << " pixels leftover" << endl;
|
|
|
|
wcout << endl;
|
|
wcout << "------ TEST PATTERN ------" << endl;
|
|
sz = szCharFinal;
|
|
|
|
for (LONG rows = 0; rows < sz.cy; rows++)
|
|
{
|
|
LONG foo = 0;
|
|
|
|
for (LONG cols = 0; cols < sz.cx; cols++)
|
|
{
|
|
wcout << foo % 10;
|
|
foo++;
|
|
}
|
|
wcout << endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wcout << "Your font has a 0 size in it. That's sad. No more math for me." << endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|