mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Windows: Added HWNDComponent to juce_gui_extra
This commit is contained in:
parent
94cc9c48a4
commit
a0fd7793b7
7 changed files with 260 additions and 7 deletions
|
|
@ -30,7 +30,7 @@ namespace juce
|
|||
moved and resized to follow the movements of this component.
|
||||
|
||||
Of course, since the view is a native object, it'll obliterate any
|
||||
juce components that may overlap this component, but that's life.
|
||||
JUCE components that may overlap this component, but that's life.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
|
|
|
|||
84
modules/juce_gui_extra/embedding/juce_HWNDComponent.h
Normal file
84
modules/juce_gui_extra/embedding/juce_HWNDComponent.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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 || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A Windows-specific class that can create and embed a HWND inside itself.
|
||||
|
||||
To use it, create one of these, put it in place and make sure it's visible in a
|
||||
window, then use setHWND() to assign a HWND to it. The window will then be
|
||||
moved and resized to follow the movements of this component.
|
||||
|
||||
Of course, since the window is a native object, it'll obliterate any
|
||||
JUCE components that may overlap this component, but that's life.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API HWNDComponent : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Create an initially-empty container. */
|
||||
HWNDComponent();
|
||||
|
||||
/** Destructor. */
|
||||
~HWNDComponent() override;
|
||||
|
||||
/** Assigns a HWND to this peer.
|
||||
|
||||
The window will be retained and released by this component for as long as
|
||||
it is needed. To remove the current HWND, just call setHWND (nullptr).
|
||||
|
||||
Note: A void* is used here to avoid including the Windows headers as
|
||||
part of JuceHeader.h, but the method expects a HWND.
|
||||
*/
|
||||
void setHWND (void* hwnd);
|
||||
|
||||
/** Returns the current HWND.
|
||||
|
||||
Note: A void* is returned here to avoid the needing to include the Windows
|
||||
headers, so you should just cast the return value to a HWND.
|
||||
*/
|
||||
void* getHWND() const;
|
||||
|
||||
/** Resizes this component to fit the HWND that it contains. */
|
||||
void resizeToFit();
|
||||
|
||||
private:
|
||||
class Pimpl;
|
||||
std::unique_ptr<Pimpl> pimpl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HWNDComponent)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -30,7 +30,7 @@ namespace juce
|
|||
moved and resized to follow the movements of this component.
|
||||
|
||||
Of course, since the view is a native object, it'll obliterate any
|
||||
juce components that may overlap this component, but that's life.
|
||||
JUCE components that may overlap this component, but that's life.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
|
|
@ -50,7 +50,7 @@ public:
|
|||
it is needed. To remove the current view, just call setView (nullptr).
|
||||
|
||||
Note: A void* is used here to avoid including the cocoa headers as
|
||||
part of the juce.h, but the method expects an NSView*.
|
||||
part of JuceHeader.h, but the method expects an NSView*.
|
||||
*/
|
||||
void setView (void* nsView);
|
||||
|
||||
|
|
@ -61,7 +61,6 @@ public:
|
|||
*/
|
||||
void* getView() const;
|
||||
|
||||
|
||||
/** Resizes this component to fit the view that it contains. */
|
||||
void resizeToFitView();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace juce
|
|||
moved and resized to follow the movements of this component.
|
||||
|
||||
Of course, since the view is a native object, it'll obliterate any
|
||||
juce components that may overlap this component, but that's life.
|
||||
JUCE components that may overlap this component, but that's life.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
|
|
@ -50,7 +50,7 @@ public:
|
|||
it is needed. To remove the current view, just call setView (nullptr).
|
||||
|
||||
Note: A void* is used here to avoid including the cocoa headers as
|
||||
part of the juce.h, but the method expects an UIView*.
|
||||
part of JuceHeader.h, but the method expects an UIView*.
|
||||
*/
|
||||
void setView (void* uiView);
|
||||
|
||||
|
|
@ -61,7 +61,6 @@ public:
|
|||
*/
|
||||
void* getView() const;
|
||||
|
||||
|
||||
/** Resizes this component to fit the view that it contains. */
|
||||
void resizeToFitView();
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@
|
|||
//==============================================================================
|
||||
#elif JUCE_WINDOWS
|
||||
#include "native/juce_win32_ActiveXComponent.cpp"
|
||||
#include "native/juce_win32_HWNDComponent.cpp"
|
||||
#if JUCE_WEB_BROWSER
|
||||
#include "native/juce_win32_WebBrowserComponent.cpp"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
#include "embedding/juce_UIViewComponent.h"
|
||||
#include "embedding/juce_XEmbedComponent.h"
|
||||
#include "embedding/juce_ScopedDPIAwarenessDisabler.h"
|
||||
#include "embedding/juce_HWNDComponent.h"
|
||||
#include "misc/juce_AppleRemote.h"
|
||||
#include "misc/juce_BubbleMessageComponent.h"
|
||||
#include "misc/juce_ColourSelector.h"
|
||||
|
|
|
|||
169
modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp
Normal file
169
modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
class HWNDComponent::Pimpl : public ComponentMovementWatcher
|
||||
{
|
||||
public:
|
||||
Pimpl (HWND h, Component& comp)
|
||||
: ComponentMovementWatcher (&comp),
|
||||
hwnd (h),
|
||||
owner (comp)
|
||||
{
|
||||
if (owner.isShowing())
|
||||
componentPeerChanged();
|
||||
}
|
||||
|
||||
~Pimpl() override
|
||||
{
|
||||
removeFromParent();
|
||||
DestroyWindow (hwnd);
|
||||
}
|
||||
|
||||
void componentMovedOrResized (bool wasMoved, bool wasResized) override
|
||||
{
|
||||
auto* topComponent = owner.getTopLevelComponent();
|
||||
|
||||
if (auto* peer = owner.getPeer())
|
||||
{
|
||||
auto pos = topComponent->getLocalPoint (&owner, Point<int>());
|
||||
|
||||
auto scaled = (Rectangle<int> (pos.x, pos.y, owner.getWidth(), owner.getHeight()).toDouble()
|
||||
* peer->getPlatformScaleFactor()).getSmallestIntegerContainer();
|
||||
|
||||
DWORD windowFlags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER;
|
||||
if (! wasMoved) windowFlags |= SWP_NOMOVE;
|
||||
if (! wasResized) windowFlags |= SWP_NOSIZE;
|
||||
|
||||
SetWindowPos (hwnd, 0, scaled.getX(), scaled.getY(), scaled.getWidth(), scaled.getHeight(), windowFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void componentPeerChanged() override
|
||||
{
|
||||
auto* peer = owner.getPeer();
|
||||
|
||||
if (currentPeer != peer)
|
||||
{
|
||||
removeFromParent();
|
||||
currentPeer = peer;
|
||||
|
||||
addToParent();
|
||||
}
|
||||
|
||||
auto isShowing = owner.isShowing();
|
||||
|
||||
ShowWindow (hwnd, isShowing ? SW_SHOWNA : SW_HIDE);
|
||||
|
||||
if (isShowing)
|
||||
InvalidateRect (hwnd, 0, 0);
|
||||
}
|
||||
|
||||
void componentVisibilityChanged() override
|
||||
{
|
||||
componentPeerChanged();
|
||||
}
|
||||
|
||||
void componentBroughtToFront (Component& comp) override
|
||||
{
|
||||
ComponentMovementWatcher::componentBroughtToFront (comp);
|
||||
}
|
||||
|
||||
Rectangle<int> getHWNDBounds() const
|
||||
{
|
||||
if (auto* peer = owner.getPeer())
|
||||
{
|
||||
RECT r;
|
||||
GetWindowRect (hwnd, &r);
|
||||
|
||||
return (Rectangle<int>::leftTopRightBottom (r.left, r.top, r.right, r.bottom).toDouble()
|
||||
/ peer->getPlatformScaleFactor()).getSmallestIntegerContainer();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
HWND hwnd;
|
||||
|
||||
private:
|
||||
void addToParent()
|
||||
{
|
||||
if (currentPeer != nullptr)
|
||||
{
|
||||
auto windowFlags = GetWindowLongPtr (hwnd, -16);
|
||||
|
||||
windowFlags &= ~(WS_POPUP | WS_CHILD);
|
||||
|
||||
SetWindowLongPtr (hwnd, -16, windowFlags);
|
||||
SetParent (hwnd, (HWND) currentPeer->getNativeHandle());
|
||||
|
||||
componentMovedOrResized (true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void removeFromParent()
|
||||
{
|
||||
SetParent (hwnd, NULL);
|
||||
}
|
||||
|
||||
Component& owner;
|
||||
ComponentPeer* currentPeer = nullptr;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
HWNDComponent::HWNDComponent()
|
||||
{
|
||||
}
|
||||
|
||||
HWNDComponent::~HWNDComponent() {}
|
||||
|
||||
void HWNDComponent::setHWND (void* hwnd)
|
||||
{
|
||||
if (hwnd != getHWND())
|
||||
{
|
||||
pimpl.reset();
|
||||
|
||||
if (hwnd != nullptr)
|
||||
pimpl.reset (new Pimpl ((HWND) hwnd, *this));
|
||||
}
|
||||
}
|
||||
|
||||
void* HWNDComponent::getHWND() const
|
||||
{
|
||||
return pimpl == nullptr ? nullptr : (void*) pimpl->hwnd;
|
||||
}
|
||||
|
||||
void HWNDComponent::resizeToFit()
|
||||
{
|
||||
if (pimpl != nullptr)
|
||||
setBounds (pimpl->getHWNDBounds());
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
Loading…
Add table
Add a link
Reference in a new issue