mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-04 14:29:04 +08:00
Examples: DPI: Portable DPI related helpers in the _Win32 examples. Using one in examples's main.cpp, the GetDpiScale functions are not wired anywhere for now. (#1542, #1676)
This commit is contained in:
parent
10030ff3ec
commit
a2fbcc9ad4
@ -95,6 +95,8 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
ImGui_ImplWin32_EnableDpiAwareness();
|
||||
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
|
||||
RegisterClassEx(&wc);
|
||||
|
@ -96,27 +96,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
// FIXME-DPI: For now we just want to call SetProcessDpiAwareness(PROCESS_PER_MONITOR_AWARE) without requiring SDK 8.1 or 10
|
||||
void SetupDpiAwareness()
|
||||
{
|
||||
typedef enum PROCESS_DPI_AWARENESS
|
||||
{
|
||||
PROCESS_DPI_UNAWARE = 0,
|
||||
PROCESS_SYSTEM_DPI_AWARE = 1,
|
||||
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
||||
} PROCESS_DPI_AWARENESS;
|
||||
if (HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"))
|
||||
{
|
||||
typedef HRESULT(WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
|
||||
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
::FreeLibrary(shcore_dll);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
SetupDpiAwareness();
|
||||
ImGui_ImplWin32_EnableDpiAwareness();
|
||||
|
||||
// Create application window
|
||||
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
|
||||
|
@ -271,6 +271,84 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------
|
||||
// DPI handling
|
||||
// Those in theory should be simple calls but Windows has multiple ways to handle DPI, and most of them
|
||||
// require recent Windows versions at runtime or recent Windows SDK at compile-time. Neither we want to depend on.
|
||||
// So we dynamically select and load those functions to avoid dependencies. This is the scheme successfully
|
||||
// used by GLFW (from which we borrowed some of the code here) and other applications aiming to be portable.
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
// FIXME-DPI: For now we just call SetProcessDpiAwareness(PROCESS_PER_MONITOR_AWARE) without requiring SDK 8.1 or 10.
|
||||
// We may allow/aim calling the most-recent-available version, e.g. Windows 10 Creators Update has SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
// At this point ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it ourselves.
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0,{ 0 }, sp };
|
||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
return VerifyVersionInfoW(&osvi, mask, cond);
|
||||
}
|
||||
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WINBLUE
|
||||
#define IsWindows10OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WIN10
|
||||
|
||||
#ifndef DPI_ENUMS_DECLARED
|
||||
typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
|
||||
typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
|
||||
#endif
|
||||
typedef HRESULT(WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib+dll, Windows 8.1
|
||||
typedef HRESULT(WINAPI * PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib+dll, Windows 8.1
|
||||
|
||||
void ImGui_ImplWin32_EnableDpiAwareness()
|
||||
{
|
||||
if (IsWindows8Point1OrGreater())
|
||||
{
|
||||
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
|
||||
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetProcessDPIAware();
|
||||
}
|
||||
}
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
|
||||
{
|
||||
UINT xdpi = 96, ydpi = 96;
|
||||
if (IsWindows8Point1OrGreater())
|
||||
{
|
||||
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
|
||||
if (PFN_GetDpiForMonitor GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"))
|
||||
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
||||
}
|
||||
else
|
||||
{
|
||||
const HDC dc = ::GetDC(NULL);
|
||||
xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
|
||||
ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
|
||||
::ReleaseDC(NULL, dc);
|
||||
}
|
||||
IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
|
||||
return xdpi / 96.0f;
|
||||
}
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
|
||||
{
|
||||
HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||
}
|
||||
|
||||
float ImGui_ImplWin32_GetDpiScaleForRect(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
RECT viewport_rect = { (UINT)x1, (UINT)y1, (UINT)x2, (UINT)y2 };
|
||||
HMONITOR monitor = ::MonitorFromRect(&viewport_rect, MONITOR_DEFAULTTONEAREST);
|
||||
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------
|
||||
// Platform Windows
|
||||
// --------------------------------------------------------------------------------------------------------
|
||||
|
@ -5,6 +5,12 @@ IMGUI_API bool ImGui_ImplWin32_Init(void* hwnd);
|
||||
IMGUI_API void ImGui_ImplWin32_Shutdown();
|
||||
IMGUI_API void ImGui_ImplWin32_NewFrame();
|
||||
|
||||
// DPI-related helpers (which run and compile without requiring 8.1 or 10, neither Windows version, neither associated SDK)
|
||||
IMGUI_API void ImGui_ImplWin32_EnableDpiAwareness();
|
||||
IMGUI_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
|
||||
IMGUI_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
|
||||
IMGUI_API float ImGui_ImplWin32_GetDpiScaleForRect(int x1, int y1, int x2, int y2);
|
||||
|
||||
// Handler for Win32 messages, update mouse/keyboard data.
|
||||
// You may or not need this for your implementation, but it can serve as reference for handling inputs.
|
||||
// Intentionally commented out to avoid dragging dependencies on <windows.h> types. You can copy the extern declaration in your code.
|
||||
|
@ -13804,13 +13804,13 @@ static void ScaleWindow(ImGuiWindow* window, float scale)
|
||||
// Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!)
|
||||
void ImGui::ScaleWindowsInViewport(ImGuiViewport* viewport, float scale)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (viewport->Window)
|
||||
{
|
||||
ScaleWindow(viewport->Window, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
for (int i = 0; i != g.Windows.Size; i++)
|
||||
if (g.Windows[i]->Viewport == viewport)
|
||||
ScaleWindow(g.Windows[i], scale);
|
||||
@ -13992,7 +13992,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
{
|
||||
ImGui::BulletText("Pos: (%.0f,%.0f)", viewport->Pos.x, viewport->Pos.y);
|
||||
ImGui::BulletText("Flags: 0x%04X", viewport->Flags);
|
||||
ImGui::BulletText("PlatformOsDesktopPos: (%.0f,%.0f)", viewport->PlatformOsDesktopPos.x, viewport->PlatformOsDesktopPos.y);
|
||||
ImGui::BulletText("PlatformOsDesktopPos: (%.0f,%.0f); DpiScale: %.0f%%", viewport->PlatformOsDesktopPos.x, viewport->PlatformOsDesktopPos.y, viewport->PlatformDpiScale * 100.0f);
|
||||
for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[0].Size; draw_list_i++)
|
||||
Funcs::NodeDrawList(NULL, viewport->DrawDataBuilder.Layers[0][draw_list_i], "DrawList");
|
||||
ImGui::TreePop();
|
||||
|
Loading…
Reference in New Issue
Block a user