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;
}
#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)


+ 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. */
void resizeToFit();
/** @internal */
void paint (Graphics&) override;
private:
class 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
{
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())


Loading…
Cancel
Save