Browse Source

Add support for DPI aware applications on Windows

tags/2021-05-28
ed 7 years ago
parent
commit
68fe75742f
7 changed files with 788 additions and 201 deletions
  1. +7
    -0
      modules/juce_gui_basics/juce_gui_basics.h
  2. +636
    -199
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  3. +56
    -0
      modules/juce_gui_extra/embedding/juce_ScopedDPIAwarenessDisabler.h
  4. +1
    -0
      modules/juce_gui_extra/juce_gui_extra.h
  5. +30
    -1
      modules/juce_gui_extra/native/juce_win32_ActiveXComponent.cpp
  6. +36
    -0
      modules/juce_opengl/native/juce_OpenGL_win32.h
  7. +22
    -1
      modules/juce_video/native/juce_win32_Video.h

+ 7
- 0
modules/juce_gui_basics/juce_gui_basics.h View File

@@ -111,6 +111,13 @@
#define JUCE_USE_XCURSOR 1
#endif
/** Config: JUCE_WIN_PER_MONITOR_DPI_AWARE
Enables per-monitor DPI awareness on Windows 8.1 and above.
*/
#ifndef JUCE_WIN_PER_MONITOR_DPI_AWARE
#define JUCE_WIN_PER_MONITOR_DPI_AWARE 1
#endif
//==============================================================================
namespace juce
{


+ 636
- 199
modules/juce_gui_basics/native/juce_win32_Windowing.cpp
File diff suppressed because it is too large
View File


+ 56
- 0
modules/juce_gui_extra/embedding/juce_ScopedDPIAwarenessDisabler.h View File

@@ -0,0 +1,56 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
#if (JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE) || DOXYGEN
//==============================================================================
/**
A Windows-specific class that temporarily sets the DPI awareness context of
the current thread to be DPI unaware and resets it to the previous context
when it goes out of scope.
If you create one of these before creating a top-level window, the window
will be DPI unaware and bitmap strectched by the OS on a display with >100%
scaling.
You shouldn't use this unless you really know what you are doing and
are dealing with native HWNDs.
*/
class JUCE_API ScopedDPIAwarenessDisabler
{
public:
ScopedDPIAwarenessDisabler();
~ScopedDPIAwarenessDisabler();
private:
void* previousContext = nullptr;
};
#endif
} // namespace juce

+ 1
- 0
modules/juce_gui_extra/juce_gui_extra.h View File

@@ -88,6 +88,7 @@
#include "embedding/juce_NSViewComponent.h"
#include "embedding/juce_UIViewComponent.h"
#include "embedding/juce_XEmbedComponent.h"
#include "embedding/juce_ScopedDPIAwarenessDisabler.h"
#include "misc/juce_AppleRemote.h"
#include "misc/juce_BubbleMessageComponent.h"
#include "misc/juce_ColourSelector.h"


+ 30
- 1
modules/juce_gui_extra/native/juce_win32_ActiveXComponent.cpp View File

@@ -231,6 +231,9 @@ namespace ActiveXHelpers
//==============================================================================
class ActiveXControlComponent::Pimpl : public ComponentMovementWatcher
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
, public ComponentPeer::ScaleFactorListener
#endif
{
public:
Pimpl (HWND hwnd, ActiveXControlComponent& activeXComp)
@@ -251,12 +254,26 @@ public:
clientSite->Release();
storage->Release();
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
for (int i = 0; i < ComponentPeer::getNumPeers(); ++i)
if (auto* peer = ComponentPeer::getPeer (i))
peer->removeScaleFactorListener (this);
#endif
}
void setControlBounds (Rectangle<int> newBounds) const
{
if (controlHWND != 0)
{
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
if (auto* peer = owner.getTopLevelComponent()->getPeer())
newBounds = (newBounds.toDouble() * peer->getPlatformScaleFactor()).toNearestInt();
#endif
MoveWindow (controlHWND, newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight(), TRUE);
}
}
void setControlVisible (bool shouldBeVisible) const
@@ -269,12 +286,17 @@ public:
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
{
if (auto* peer = owner.getTopLevelComponent()->getPeer())
setControlBounds (peer->getAreaCoveredBy(owner));
setControlBounds (peer->getAreaCoveredBy (owner));
}
void componentPeerChanged() override
{
componentMovedOrResized (true, true);
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
if (auto* peer = owner.getTopLevelComponent()->getPeer())
peer->addScaleFactorListener (this);
#endif
}
void componentVisibilityChanged() override
@@ -283,6 +305,13 @@ public:
componentPeerChanged();
}
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
void nativeScaleFactorChanged (double /*newScaleFactor*/) override
{
componentMovedOrResized (true, true);
}
#endif
// intercepts events going to an activeX control, so we can sneakily use the mouse events
static LRESULT CALLBACK activeXHookWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{


+ 36
- 0
modules/juce_opengl/native/juce_OpenGL_win32.h View File

@@ -31,6 +31,9 @@ extern ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component&, void*
//==============================================================================
class OpenGLContext::NativeContext
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
: public ComponentPeer::ScaleFactorListener
#endif
{
public:
NativeContext (Component& component,
@@ -87,6 +90,12 @@ public:
{
deleteRenderContext();
releaseDC();
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
for (int i = 0; i < ComponentPeer::getNumPeers(); ++i)
if (auto* peer = ComponentPeer::getPeer (i))
peer->removeScaleFactorListener (this);
#endif
}
bool initialiseOnRenderThread (OpenGLContext& c)
@@ -117,9 +126,17 @@ public:
void updateWindowPosition (Rectangle<int> bounds)
{
if (nativeWindow != nullptr)
{
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
if (safeComponent != nullptr)
if (auto* peer = safeComponent->getTopLevelComponent()->getPeer())
bounds = (bounds.toDouble() * peer->getPlatformScaleFactor()).toNearestInt();
#endif
SetWindowPos ((HWND) nativeWindow->getNativeHandle(), 0,
bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
}
bool createdOk() const noexcept { return getRawContext() != nullptr; }
@@ -134,6 +151,15 @@ public:
struct Locker { Locker (NativeContext&) {} };
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
void nativeScaleFactorChanged (double /*newScaleFactor*/) override
{
if (safeComponent != nullptr)
if (auto peer = safeComponent->getTopLevelComponent()->getPeer())
updateWindowPosition (peer->getAreaCoveredBy (*safeComponent));
}
#endif
private:
struct DummyComponent : public Component
{
@@ -150,6 +176,9 @@ private:
HGLRC renderContext;
HDC dc;
OpenGLContext* context = {};
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
Component::SafePointer<Component> safeComponent;
#endif
#define JUCE_DECLARE_WGL_EXTENSION_FUNCTION(name, returnType, params) \
typedef returnType (__stdcall *type_ ## name) params; type_ ## name name;
@@ -174,8 +203,15 @@ private:
nativeWindow.reset (createNonRepaintingEmbeddedWindowsPeer (*dummyComponent, topComp->getWindowHandle()));
if (auto* peer = topComp->getPeer())
{
updateWindowPosition (peer->getAreaCoveredBy (component));
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
peer->addScaleFactorListener (this);
safeComponent = Component::SafePointer<Component> (&component);
#endif
}
nativeWindow->setVisible (true);
dc = GetDC ((HWND) nativeWindow->getNativeHandle());
}


+ 22
- 1
modules/juce_video/native/juce_win32_Video.h View File

@@ -159,6 +159,9 @@ namespace VideoRenderers
//==============================================================================
struct VideoComponent::Pimpl : public Component
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
, public ComponentPeer::ScaleFactorListener
#endif
{
Pimpl (VideoComponent& ownerToUse, bool)
: owner (ownerToUse),
@@ -174,6 +177,12 @@ struct VideoComponent::Pimpl : public Component
close();
context = nullptr;
componentWatcher = nullptr;
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
for (int i = 0; i < ComponentPeer::getNumPeers(); ++i)
if (auto* peer = ComponentPeer::getPeer (i))
peer->removeScaleFactorListener (this);
#endif
}
Result loadFromString (const String& fileOrURLPath)
@@ -300,7 +309,7 @@ struct VideoComponent::Pimpl : public Component
if (getWidth() > 0 && getHeight() > 0)
if (auto* peer = getTopLevelComponent()->getPeer())
context->updateWindowPosition (peer->getAreaCoveredBy (*this));
context->updateWindowPosition ((peer->getAreaCoveredBy (*this).toDouble() * peer->getPlatformScaleFactor()).toNearestInt());
}
void updateContextVisibility()
@@ -332,6 +341,14 @@ struct VideoComponent::Pimpl : public Component
owner.onErrorOccurred (errorMessage);
}
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
void nativeScaleFactorChanged (double /*newScaleFactor*/) override
{
if (videoLoaded)
updateContextPosition();
}
#endif
File currentFile;
URL currentURL;
@@ -755,6 +772,10 @@ private:
hwnd = nativeWindow->hwnd;
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
topLevelPeer->addScaleFactorListener (&component);
#endif
if (hwnd != 0)
{
hdc = GetDC (hwnd);


Loading…
Cancel
Save