Skip to content

Commit

Permalink
Per Monitor DPI v2 に対応 (issue #31)
Browse files Browse the repository at this point in the history
  • Loading branch information
DBCTRADO committed Oct 28, 2017
1 parent ba3181a commit 25d5d7d
Show file tree
Hide file tree
Showing 30 changed files with 429 additions and 130 deletions.
4 changes: 4 additions & 0 deletions src/ComUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "ComUtility.h"
#include "Dialog.h"
#include "DialogUtil.h"
#include "DPIUtil.h"
#include "TVTestInterface.h"
#include "resource.h"
#include "Common/DebugDef.h"
Expand Down Expand Up @@ -537,6 +538,9 @@ HRESULT ShowPropertyPageFrame(
ppPropPages[i]->SetObjects(1, &pObject);
}

// TVTest DTV Video Decoder のダイアログが欠けるのでとりあえず System DPI とする
SystemDPIBlock SystemDPI;

CPropertyPageFrame Frame(ppPropPages, NumPages, pPageSite);

Frame.Show(hwndOwner, hinst);
Expand Down
124 changes: 104 additions & 20 deletions src/DPIUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,13 @@
#include "TVTest.h"
#include "DPIUtil.h"
#include "Util.h"
#include <ShellScalingApi.h>
#include "Common/DebugDef.h"


extern "C"
{

// from <ShellScalingApi.h>
#ifndef DPI_ENUMS_DECLARED
typedef enum MONITOR_DPI_TYPE {
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;
#endif

STDAPI GetDpiForMonitor(
HMONITOR hmonitor,
MONITOR_DPI_TYPE dpiType,
UINT *dpiX,
UINT *dpiY
);

WINUSERAPI UINT WINAPI GetDpiForSystem(void);
WINUSERAPI UINT WINAPI GetDpiForWindow(HWND hwnd);
WINUSERAPI BOOL WINAPI EnableNonClientDpiScaling(HWND hwnd);
Expand All @@ -69,6 +53,14 @@ WINUSERAPI int WINAPI GetSystemMetricsForDpi(
WINUSERAPI DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext(
DPI_AWARENESS_CONTEXT dpiContext
);
WINUSERAPI DPI_AWARENESS_CONTEXT WINAPI GetThreadDpiAwarenessContext();
WINUSERAPI DPI_AWARENESS_CONTEXT WINAPI GetWindowDpiAwarenessContext(
HWND hwnd
);
WINUSERAPI BOOL WINAPI AreDpiAwarenessContextsEqual(
DPI_AWARENESS_CONTEXT dpiContextA,
DPI_AWARENESS_CONTEXT dpiContextB
);

}

Expand All @@ -92,6 +84,30 @@ DPI_AWARENESS_CONTEXT MySetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT Conte
}


DPI_AWARENESS_CONTEXT MyGetThreadDpiAwarenessContext()
{
if (Util::OS::IsWindows10AnniversaryUpdateOrLater()) {
auto pGetThreadDpiAwarenessContext =
GET_MODULE_FUNCTION(TEXT("user32.dll"), GetThreadDpiAwarenessContext);
if (pGetThreadDpiAwarenessContext != nullptr)
return pGetThreadDpiAwarenessContext();
}
return nullptr;
}


bool MyAreDpiAwarenessContextsEqual(DPI_AWARENESS_CONTEXT Context1, DPI_AWARENESS_CONTEXT Context2)
{
if (Util::OS::IsWindows10AnniversaryUpdateOrLater()) {
auto pAreDpiAwarenessContextsEqual =
GET_MODULE_FUNCTION(TEXT("user32.dll"), AreDpiAwarenessContextsEqual);
if (pAreDpiAwarenessContextsEqual != nullptr)
return pAreDpiAwarenessContextsEqual(Context1, Context2) != FALSE;
}
return Context1 == Context2;
}


}


Expand Down Expand Up @@ -184,13 +200,13 @@ int GetSystemMetricsWithDPI(int Index, int DPI, bool fFallbackScaling)
if (Util::OS::IsWindows10AnniversaryUpdateOrLater()) {
auto pGetSystemMetricsForDpi =
GET_MODULE_FUNCTION(TEXT("user32.dll"), GetSystemMetricsForDpi);
if (pGetSystemMetricsForDpi == nullptr)
if (pGetSystemMetricsForDpi != nullptr)
return pGetSystemMetricsForDpi(Index, DPI);
}

int Value = ::GetSystemMetrics(Index);
if (fFallbackScaling && Value != 0)
Value = ::MulDiv(Value, GetSystemDPI(), 96);
Value = ::MulDiv(Value, DPI, GetSystemDPI());

return Value;
}
Expand Down Expand Up @@ -222,8 +238,66 @@ bool AdjustWindowRectWithDPI(RECT *pRect, DWORD Style, DWORD ExStyle, bool fMenu
}


int GetScrollBarWidth(HWND hwnd)
{
if (IsWindowPerMonitorDPIV2(hwnd))
return GetSystemMetricsWithDPI(SM_CXVSCROLL, GetWindowDPI(hwnd));

return ::GetSystemMetrics(SM_CXVSCROLL);
}


DPI_AWARENESS_CONTEXT GetWindowDPIAwareness(HWND hwnd)
{
if (Util::OS::IsWindows10AnniversaryUpdateOrLater()) {
auto pGetWindowDpiAwarenessContext = GET_MODULE_FUNCTION(TEXT("user32.dll"), GetWindowDpiAwarenessContext);
if (pGetWindowDpiAwarenessContext != nullptr)
return pGetWindowDpiAwarenessContext(hwnd);
}

if (Util::OS::IsWindows8_1OrLater()) {
HMODULE hLib = Util::LoadSystemLibrary(TEXT("shcore.dll"));
if (hLib != nullptr) {
auto pGetProcessDpiAwareness = GET_LIBRARY_FUNCTION(hLib, GetProcessDpiAwareness);
PROCESS_DPI_AWARENESS Awareness;
if ((pGetProcessDpiAwareness != nullptr)
&& (pGetProcessDpiAwareness(nullptr, &Awareness) == S_OK)) {
::FreeLibrary(hLib);
switch (Awareness) {
case PROCESS_DPI_UNAWARE: return DPI_AWARENESS_CONTEXT_UNAWARE;
case PROCESS_SYSTEM_DPI_AWARE: return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
case PROCESS_PER_MONITOR_DPI_AWARE: return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
}
}
::FreeLibrary(hLib);
}
}

return nullptr;
}


bool IsWindowPerMonitorDPIV1(HWND hwnd)
{
return MyAreDpiAwarenessContextsEqual(GetWindowDPIAwareness(hwnd), DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
}


bool IsWindowPerMonitorDPIV2(HWND hwnd)
{
if (Util::OS::IsWindows10CreatorsUpdateOrLater()) {
auto pGetWindowDpiAwarenessContext = GET_MODULE_FUNCTION(TEXT("user32.dll"), GetWindowDpiAwarenessContext);
if (pGetWindowDpiAwarenessContext != nullptr) {
return MyAreDpiAwarenessContextsEqual(
pGetWindowDpiAwarenessContext(hwnd), DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
}
return false;
}


DPIBlockBase::DPIBlockBase(DPI_AWARENESS_CONTEXT Context)
: m_OldContext(MySetThreadDpiAwarenessContext(Context))
: m_OldContext((Context != nullptr) ? MySetThreadDpiAwarenessContext(Context) : nullptr)
{
}

Expand All @@ -234,4 +308,14 @@ DPIBlockBase::~DPIBlockBase()
}


CommonDialogDPIBlock::CommonDialogDPIBlock()
: DPIBlockBase(
MyAreDpiAwarenessContextsEqual(
MyGetThreadDpiAwarenessContext(), DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) ?
nullptr :
DPI_AWARENESS_CONTEXT_SYSTEM_AWARE)
{
}


}
22 changes: 18 additions & 4 deletions src/DPIUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
#define TVTEST_DPI_UTIL_H


// from <windef.h> (SDK 10.0.14393.0)
// from <windef.h> (SDK 10.0.16299.0)
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
#endif
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
#endif


Expand All @@ -41,6 +44,10 @@ namespace TVTest
int GetSystemMetricsWithDPI(int Index, int DPI, bool fFallbackScaling = true);
bool SystemParametersInfoWithDPI(UINT Action, UINT Param, void *pParam, UINT Flags, int DPI);
bool AdjustWindowRectWithDPI(RECT *pRect, DWORD Style, DWORD ExStyle, bool fMenu, int DPI);
int GetScrollBarWidth(HWND hwnd);
DPI_AWARENESS_CONTEXT GetWindowDPIAwareness(HWND hwnd);
bool IsWindowPerMonitorDPIV1(HWND hwnd);
bool IsWindowPerMonitorDPIV2(HWND hwnd);

class DPIBlockBase
{
Expand All @@ -66,6 +73,13 @@ namespace TVTest
PerMonitorDPIBlock() : DPIBlockBase(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) {}
};

class CommonDialogDPIBlock
: public DPIBlockBase
{
public:
CommonDialogDPIBlock();
};

}


Expand Down
40 changes: 22 additions & 18 deletions src/Dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ CBasicDialog::CBasicDialog()
, m_CurrentDPI(0)
, m_hOriginalFont(nullptr)
, m_fInitializing(false)
, m_fOwnDPIScaling(false)
{
SetStyleScaling(&m_StyleScaling);
}
Expand Down Expand Up @@ -190,9 +191,6 @@ int CBasicDialog::ShowDialog(HWND hwndOwner, HINSTANCE hinst, LPCTSTR pszTemplat
if (m_hDlg != nullptr)
return -1;

// ダイアログは Per-Monitor DPI 対応
PerMonitorDPIBlock DPIBlock;

return (int)::DialogBoxParam(
hinst, pszTemplate, hwndOwner, DialogProc,
reinterpret_cast<LPARAM>(this));
Expand All @@ -204,9 +202,6 @@ bool CBasicDialog::CreateDialogWindow(HWND hwndOwner, HINSTANCE hinst, LPCTSTR p
if (m_hDlg != nullptr)
return false;

// ダイアログは Per-Monitor DPI 対応
PerMonitorDPIBlock DPIBlock;

if (::CreateDialogParam(
hinst, pszTemplate, hwndOwner, DialogProc,
reinterpret_cast<LPARAM>(this)) == nullptr)
Expand All @@ -229,6 +224,7 @@ INT_PTR CALLBACK CBasicDialog::DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
if (uMsg == WM_INITDIALOG) {
pThis = reinterpret_cast<CBasicDialog*>(lParam);
pThis->m_hDlg = hDlg;
pThis->m_fOwnDPIScaling = IsWindowPerMonitorDPIV1(hDlg);
::SetProp(hDlg, TEXT("This"), pThis);
} else {
pThis = GetThis(hDlg);
Expand Down Expand Up @@ -270,13 +266,15 @@ INT_PTR CBasicDialog::HandleMessage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM
case WM_DESTROY:
StorePosition();

if (!m_ItemList.empty()) {
for (const auto &e : m_ItemList)
SetWindowFont(e.hwnd, m_hOriginalFont, FALSE);
m_ItemList.clear();
if (m_fOwnDPIScaling) {
if (!m_ItemList.empty()) {
for (const auto &e : m_ItemList)
SetWindowFont(e.hwnd, m_hOriginalFont, FALSE);
m_ItemList.clear();
}
if (m_hOriginalFont != nullptr)
SetWindowFont(hDlg, m_hOriginalFont, FALSE);
}
if (m_hOriginalFont != nullptr)
SetWindowFont(hDlg, m_hOriginalFont, FALSE);
break;
}

Expand Down Expand Up @@ -349,13 +347,17 @@ void CBasicDialog::InitDialog()
InitStyleScaling(m_hDlg, false);
}

m_OriginalDPI = m_pStyleScaling->GetSystemDPI();
if (IsWindowPerMonitorDPIV2(m_hDlg))
m_OriginalDPI = GetWindowDPI(m_hDlg);
else
m_OriginalDPI = m_pStyleScaling->GetSystemDPI();
m_CurrentDPI = m_OriginalDPI;
m_hOriginalFont = GetWindowFont(m_hDlg);
::GetObject(m_hOriginalFont, sizeof(LOGFONT), &m_lfOriginalFont);

InitializeUI();

if (m_pStyleScaling->GetDPI() != m_OriginalDPI) {
if (m_fOwnDPIScaling && m_pStyleScaling->GetDPI() != m_OriginalDPI) {
RealizeStyle();

RECT rc;
Expand All @@ -377,8 +379,7 @@ void CBasicDialog::ApplyStyle()
if (m_hDlg != nullptr) {
const int DPI = m_pStyleScaling->GetDPI();

LOGFONT lf;
::GetObject(m_hOriginalFont, sizeof(LOGFONT), &lf);
LOGFONT lf = m_lfOriginalFont;
LONG Height = ::MulDiv(abs(lf.lfHeight), DPI, m_OriginalDPI);
lf.lfHeight = lf.lfHeight < 0 ? -Height : Height;
lf.lfWidth = 0;
Expand All @@ -389,7 +390,7 @@ void CBasicDialog::ApplyStyle()

void CBasicDialog::RealizeStyle()
{
if (m_hDlg != nullptr) {
if (m_hDlg != nullptr && m_fOwnDPIScaling) {
const int DPI = m_pStyleScaling->GetDPI();

if (m_CurrentDPI != DPI) {
Expand Down Expand Up @@ -473,7 +474,10 @@ INT_PTR CResizableDialog::HandleMessage(HWND hDlg, UINT uMsg, WPARAM wParam, LPA
{
RECT rc;

m_BaseDPI = m_pStyleScaling->GetSystemDPI();
if (IsWindowPerMonitorDPIV2(hDlg))
m_BaseDPI = GetWindowDPI(hDlg);
else
m_BaseDPI = m_pStyleScaling->GetSystemDPI();

::GetClientRect(hDlg, &rc);
m_OriginalClientSize.cx = rc.right;
Expand Down
2 changes: 2 additions & 0 deletions src/Dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ namespace TVTest
int m_OriginalDPI;
int m_CurrentDPI;
HFONT m_hOriginalFont;
LOGFONT m_lfOriginalFont;
DrawUtil::CFont m_Font;
bool m_fInitializing;
bool m_fOwnDPIScaling;

static CBasicDialog *GetThis(HWND hDlg);
static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
Expand Down
Loading

0 comments on commit 25d5d7d

Please sign in to comment.