Browse Source

Windows: Improved support for DPI-aware embedded windows in HWNDComponent

tags/2021-05-28
ed 4 years ago
parent
commit
cb57904740
3 changed files with 65 additions and 61 deletions
  1. +40
    -38
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  2. +3
    -0
      modules/juce_gui_extra/embedding/juce_HWNDComponent.h
  3. +22
    -23
      modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp

+ 40
- 38
modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -547,44 +547,46 @@ JUCE_API double getScaleFactorForWindow (HWND h)
return 1.0; 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) static void setWindowPos (HWND hwnd, Rectangle<int> bounds, UINT flags, bool adjustTopLeft = false)


+ 3
- 0
modules/juce_gui_extra/embedding/juce_HWNDComponent.h View File

@@ -71,6 +71,9 @@ public:
/** Resizes this component to fit the HWND that it contains. */ /** Resizes this component to fit the HWND that it contains. */
void resizeToFit(); void resizeToFit();
/** @internal */
void paint (Graphics&) override;
private: private:
class Pimpl; class Pimpl;
std::unique_ptr<Pimpl> pimpl; std::unique_ptr<Pimpl> pimpl;


+ 22
- 23
modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp View File

@@ -26,6 +26,8 @@
namespace juce namespace juce
{ {
void setThreadDPIAwarenessForWindow (HWND);
class HWNDComponent::Pimpl : public ComponentMovementWatcher class HWNDComponent::Pimpl : public ComponentMovementWatcher
{ {
public: public:
@@ -44,27 +46,21 @@ public:
DestroyWindow (hwnd); 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 void componentPeerChanged() override
{ {
auto* peer = owner.getPeer(); auto* peer = owner.getPeer();
@@ -85,13 +81,13 @@ public:
InvalidateRect (hwnd, nullptr, 0); InvalidateRect (hwnd, nullptr, 0);
} }
using ComponentMovementWatcher::componentVisibilityChanged;
void componentVisibilityChanged() override void componentVisibilityChanged() override
{ {
componentPeerChanged(); componentPeerChanged();
} }
using ComponentMovementWatcher::componentVisibilityChanged;
void componentBroughtToFront (Component& comp) override void componentBroughtToFront (Component& comp) override
{ {
ComponentMovementWatcher::componentBroughtToFront (comp); ComponentMovementWatcher::componentBroughtToFront (comp);
@@ -101,11 +97,13 @@ public:
{ {
if (auto* peer = owner.getPeer()) if (auto* peer = owner.getPeer())
{ {
setThreadDPIAwarenessForWindow (hwnd);
RECT r; RECT r;
GetWindowRect (hwnd, &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 {}; return {};
@@ -120,7 +118,8 @@ private:
{ {
auto windowFlags = GetWindowLongPtr (hwnd, -16); auto windowFlags = GetWindowLongPtr (hwnd, -16);
windowFlags &= ~(WS_POPUP | WS_CHILD);
windowFlags &= ~WS_POPUP;
windowFlags |= WS_CHILD;
SetWindowLongPtr (hwnd, -16, windowFlags); SetWindowLongPtr (hwnd, -16, windowFlags);
SetParent (hwnd, (HWND) currentPeer->getNativeHandle()); SetParent (hwnd, (HWND) currentPeer->getNativeHandle());
@@ -131,6 +130,7 @@ private:
void removeFromParent() void removeFromParent()
{ {
ShowWindow (hwnd, SW_HIDE);
SetParent (hwnd, NULL); SetParent (hwnd, NULL);
} }
@@ -141,12 +141,11 @@ private:
}; };
//============================================================================== //==============================================================================
HWNDComponent::HWNDComponent()
{
}
HWNDComponent::HWNDComponent() {}
HWNDComponent::~HWNDComponent() {} HWNDComponent::~HWNDComponent() {}
void HWNDComponent::paint (Graphics&) {}
void HWNDComponent::setHWND (void* hwnd) void HWNDComponent::setHWND (void* hwnd)
{ {
if (hwnd != getHWND()) if (hwnd != getHWND())


Loading…
Cancel
Save