@@ -547,44 +547,46 @@ JUCE_API double getScaleFactorForWindow (HWND h) | |||
return 1.0; | |||
} | |||
#if JUCE_WIN_PER_MONITOR_DPI_AWARE | |||
JUCE_API void setThreadDPIAwarenessForWindow (HWND nativeWindow) | |||
{ | |||
// NB. Using local functions here because we need to call this method from the plug-in wrappers | |||
// which don't load the DPI-awareness functions on startup | |||
static SetThreadDPIAwarenessContextFunc localSetThreadDPIAwarenessContext = nullptr; | |||
static GetWindowDPIAwarenessContextFunc localGetWindowDPIAwarenessContext = nullptr; | |||
static GetThreadDPIAwarenessContextFunc localGetThreadDPIAwarenessContext = nullptr; | |||
static GetAwarenessFromDpiAwarenessContextFunc localGetAwarenessFromDPIAwarenessContext = nullptr; | |||
static bool hasChecked = false; | |||
static bool loadedOK = false; | |||
if (! hasChecked) | |||
{ | |||
hasChecked = true; | |||
localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext"); | |||
localGetWindowDPIAwarenessContext = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext"); | |||
localGetThreadDPIAwarenessContext = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext"); | |||
localGetAwarenessFromDPIAwarenessContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext"); | |||
loadedOK = (localSetThreadDPIAwarenessContext != nullptr && localGetWindowDPIAwarenessContext != nullptr | |||
&& localGetThreadDPIAwarenessContext != nullptr && localGetAwarenessFromDPIAwarenessContext != nullptr); | |||
} | |||
if (loadedOK) | |||
{ | |||
auto dpiAwareWindow = localGetAwarenessFromDPIAwarenessContext (localGetWindowDPIAwarenessContext (nativeWindow)) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; | |||
auto dpiAwareThread = localGetAwarenessFromDPIAwarenessContext (localGetThreadDPIAwarenessContext()) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; | |||
if (dpiAwareWindow && ! dpiAwareThread) | |||
localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); | |||
else if (! dpiAwareWindow && dpiAwareThread) | |||
localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_UNAWARE); | |||
} | |||
} | |||
#endif | |||
JUCE_API void setThreadDPIAwarenessForWindow (HWND nativeWindow) | |||
{ | |||
#if JUCE_WIN_PER_MONITOR_DPI_AWARE | |||
// NB. Using local functions here because we need to call this method from the plug-in wrappers | |||
// which don't load the DPI-awareness functions on startup | |||
static SetThreadDPIAwarenessContextFunc localSetThreadDPIAwarenessContext = nullptr; | |||
static GetWindowDPIAwarenessContextFunc localGetWindowDPIAwarenessContext = nullptr; | |||
static GetThreadDPIAwarenessContextFunc localGetThreadDPIAwarenessContext = nullptr; | |||
static GetAwarenessFromDpiAwarenessContextFunc localGetAwarenessFromDPIAwarenessContext = nullptr; | |||
static bool hasChecked = false; | |||
static bool loadedOK = false; | |||
if (! hasChecked) | |||
{ | |||
hasChecked = true; | |||
localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext"); | |||
localGetWindowDPIAwarenessContext = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext"); | |||
localGetThreadDPIAwarenessContext = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext"); | |||
localGetAwarenessFromDPIAwarenessContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext"); | |||
loadedOK = (localSetThreadDPIAwarenessContext != nullptr && localGetWindowDPIAwarenessContext != nullptr | |||
&& localGetThreadDPIAwarenessContext != nullptr && localGetAwarenessFromDPIAwarenessContext != nullptr); | |||
} | |||
if (loadedOK) | |||
{ | |||
auto dpiAwareWindow = localGetAwarenessFromDPIAwarenessContext (localGetWindowDPIAwarenessContext (nativeWindow)) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; | |||
auto dpiAwareThread = localGetAwarenessFromDPIAwarenessContext (localGetThreadDPIAwarenessContext()) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; | |||
if (dpiAwareWindow && ! dpiAwareThread) | |||
localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); | |||
else if (! dpiAwareWindow && dpiAwareThread) | |||
localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_UNAWARE); | |||
} | |||
#else | |||
ignoreUnused (nativeWindow); | |||
#endif | |||
} | |||
//============================================================================== | |||
static void setWindowPos (HWND hwnd, Rectangle<int> bounds, UINT flags, bool adjustTopLeft = false) | |||
@@ -71,6 +71,9 @@ public: | |||
/** Resizes this component to fit the HWND that it contains. */ | |||
void resizeToFit(); | |||
/** @internal */ | |||
void paint (Graphics&) override; | |||
private: | |||
class Pimpl; | |||
std::unique_ptr<Pimpl> pimpl; | |||
@@ -26,6 +26,8 @@ | |||
namespace juce | |||
{ | |||
void setThreadDPIAwarenessForWindow (HWND); | |||
class HWNDComponent::Pimpl : public ComponentMovementWatcher | |||
{ | |||
public: | |||
@@ -44,27 +46,21 @@ public: | |||
DestroyWindow (hwnd); | |||
} | |||
using ComponentMovementWatcher::componentMovedOrResized; | |||
void componentMovedOrResized (bool wasMoved, bool wasResized) override | |||
void componentMovedOrResized (bool, bool) override | |||
{ | |||
auto* topComponent = owner.getTopLevelComponent(); | |||
if (auto* peer = owner.getPeer()) | |||
if (auto* peer = owner.getTopLevelComponent()->getPeer()) | |||
{ | |||
auto pos = topComponent->getLocalPoint (&owner, Point<int>()); | |||
auto area = (peer->getAreaCoveredBy (owner).toFloat() * peer->getPlatformScaleFactor()).toNearestInt(); | |||
auto scaled = (Rectangle<int> (pos.x, pos.y, owner.getWidth(), owner.getHeight()).toDouble() | |||
* peer->getPlatformScaleFactor()).getSmallestIntegerContainer(); | |||
setThreadDPIAwarenessForWindow (hwnd); | |||
DWORD windowFlags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER; | |||
if (! wasMoved) windowFlags |= SWP_NOMOVE; | |||
if (! wasResized) windowFlags |= SWP_NOSIZE; | |||
SetWindowPos (hwnd, nullptr, scaled.getX(), scaled.getY(), scaled.getWidth(), scaled.getHeight(), windowFlags); | |||
SetWindowPos (hwnd, nullptr, area.getX(), area.getY(), area.getWidth(), area.getHeight(), | |||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER); | |||
} | |||
} | |||
using ComponentMovementWatcher::componentMovedOrResized; | |||
void componentPeerChanged() override | |||
{ | |||
auto* peer = owner.getPeer(); | |||
@@ -85,13 +81,13 @@ public: | |||
InvalidateRect (hwnd, nullptr, 0); | |||
} | |||
using ComponentMovementWatcher::componentVisibilityChanged; | |||
void componentVisibilityChanged() override | |||
{ | |||
componentPeerChanged(); | |||
} | |||
using ComponentMovementWatcher::componentVisibilityChanged; | |||
void componentBroughtToFront (Component& comp) override | |||
{ | |||
ComponentMovementWatcher::componentBroughtToFront (comp); | |||
@@ -101,11 +97,13 @@ public: | |||
{ | |||
if (auto* peer = owner.getPeer()) | |||
{ | |||
setThreadDPIAwarenessForWindow (hwnd); | |||
RECT r; | |||
GetWindowRect (hwnd, &r); | |||
Rectangle<int> windowRectangle (r.right - r.left, r.bottom - r.top); | |||
return (Rectangle<int>::leftTopRightBottom (r.left, r.top, r.right, r.bottom).toDouble() | |||
/ peer->getPlatformScaleFactor()).getSmallestIntegerContainer(); | |||
return (windowRectangle.toFloat() / peer->getPlatformScaleFactor()).toNearestInt(); | |||
} | |||
return {}; | |||
@@ -120,7 +118,8 @@ private: | |||
{ | |||
auto windowFlags = GetWindowLongPtr (hwnd, -16); | |||
windowFlags &= ~(WS_POPUP | WS_CHILD); | |||
windowFlags &= ~WS_POPUP; | |||
windowFlags |= WS_CHILD; | |||
SetWindowLongPtr (hwnd, -16, windowFlags); | |||
SetParent (hwnd, (HWND) currentPeer->getNativeHandle()); | |||
@@ -131,6 +130,7 @@ private: | |||
void removeFromParent() | |||
{ | |||
ShowWindow (hwnd, SW_HIDE); | |||
SetParent (hwnd, NULL); | |||
} | |||
@@ -141,12 +141,11 @@ private: | |||
}; | |||
//============================================================================== | |||
HWNDComponent::HWNDComponent() | |||
{ | |||
} | |||
HWNDComponent::HWNDComponent() {} | |||
HWNDComponent::~HWNDComponent() {} | |||
void HWNDComponent::paint (Graphics&) {} | |||
void HWNDComponent::setHWND (void* hwnd) | |||
{ | |||
if (hwnd != getHWND()) | |||