| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    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 6 End-User License
 -    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
 - 
 -    End User License Agreement: www.juce.com/juce-6-licence
 -    Privacy Policy: www.juce.com/juce-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
 - {
 - 
 - extern int64 getMouseEventTime();
 - 
 - JUCE_DECLARE_UUID_GETTER (IOleObject,       "00000112-0000-0000-C000-000000000046")
 - JUCE_DECLARE_UUID_GETTER (IOleWindow,       "00000114-0000-0000-C000-000000000046")
 - JUCE_DECLARE_UUID_GETTER (IOleInPlaceSite,  "00000119-0000-0000-C000-000000000046")
 - 
 - namespace ActiveXHelpers
 - {
 -     //==============================================================================
 -     struct JuceIStorage   : public ComBaseClassHelper<IStorage>
 -     {
 -         JuceIStorage() {}
 - 
 -         JUCE_COMRESULT CreateStream (const WCHAR*, DWORD, DWORD, DWORD, IStream**)           { return E_NOTIMPL; }
 -         JUCE_COMRESULT OpenStream (const WCHAR*, void*, DWORD, DWORD, IStream**)             { return E_NOTIMPL; }
 -         JUCE_COMRESULT CreateStorage (const WCHAR*, DWORD, DWORD, DWORD, IStorage**)         { return E_NOTIMPL; }
 -         JUCE_COMRESULT OpenStorage (const WCHAR*, IStorage*, DWORD, SNB, DWORD, IStorage**)  { return E_NOTIMPL; }
 -         JUCE_COMRESULT CopyTo (DWORD, IID const*, SNB, IStorage*)                            { return E_NOTIMPL; }
 -         JUCE_COMRESULT MoveElementTo (const OLECHAR*,IStorage*, const OLECHAR*, DWORD)       { return E_NOTIMPL; }
 -         JUCE_COMRESULT Commit (DWORD)                                                        { return E_NOTIMPL; }
 -         JUCE_COMRESULT Revert()                                                              { return E_NOTIMPL; }
 -         JUCE_COMRESULT EnumElements (DWORD, void*, DWORD, IEnumSTATSTG**)                    { return E_NOTIMPL; }
 -         JUCE_COMRESULT DestroyElement (const OLECHAR*)                                       { return E_NOTIMPL; }
 -         JUCE_COMRESULT RenameElement (const WCHAR*, const WCHAR*)                            { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetElementTimes (const WCHAR*, FILETIME const*, FILETIME const*, FILETIME const*)    { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetClass (REFCLSID)                                                   { return S_OK; }
 -         JUCE_COMRESULT SetStateBits (DWORD, DWORD)                                           { return E_NOTIMPL; }
 -         JUCE_COMRESULT Stat (STATSTG*, DWORD)                                                { return E_NOTIMPL; }
 -     };
 - 
 -     //==============================================================================
 -     struct JuceOleInPlaceFrame   : public ComBaseClassHelper<IOleInPlaceFrame>
 -     {
 -         JuceOleInPlaceFrame (HWND hwnd)   : window (hwnd) {}
 - 
 -         JUCE_COMRESULT GetWindow (HWND* lphwnd)                                 { *lphwnd = window; return S_OK; }
 -         JUCE_COMRESULT ContextSensitiveHelp (BOOL)                              { return E_NOTIMPL; }
 -         JUCE_COMRESULT GetBorder (LPRECT)                                       { return E_NOTIMPL; }
 -         JUCE_COMRESULT RequestBorderSpace (LPCBORDERWIDTHS)                     { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetBorderSpace (LPCBORDERWIDTHS)                         { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetActiveObject (IOleInPlaceActiveObject* a, LPCOLESTR)  { activeObject = a; return S_OK; }
 -         JUCE_COMRESULT InsertMenus (HMENU, LPOLEMENUGROUPWIDTHS)                { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetMenu (HMENU, HOLEMENU, HWND)                          { return S_OK; }
 -         JUCE_COMRESULT RemoveMenus (HMENU)                                      { return E_NOTIMPL; }
 -         JUCE_COMRESULT SetStatusText (LPCOLESTR)                                { return S_OK; }
 -         JUCE_COMRESULT EnableModeless (BOOL)                                    { return S_OK; }
 -         JUCE_COMRESULT TranslateAccelerator (LPMSG, WORD)                       { return E_NOTIMPL; }
 - 
 -         HRESULT OfferKeyTranslation (LPMSG lpmsg)
 -         {
 -             if (activeObject != nullptr)
 -                 return activeObject->TranslateAcceleratorW (lpmsg);
 - 
 -             return S_FALSE;
 -         }
 - 
 -         HWND window;
 -         ComSmartPtr<IOleInPlaceActiveObject> activeObject;
 -     };
 - 
 -     //==============================================================================
 -     struct JuceIOleInPlaceSite   : public ComBaseClassHelper<IOleInPlaceSite>
 -     {
 -         JuceIOleInPlaceSite (HWND hwnd)
 -             : window (hwnd),
 -               frame (new JuceOleInPlaceFrame (window))
 -         {}
 - 
 -         ~JuceIOleInPlaceSite()
 -         {
 -             frame->Release();
 -         }
 - 
 -         JUCE_COMRESULT GetWindow (HWND* lphwnd)      { *lphwnd = window; return S_OK; }
 -         JUCE_COMRESULT ContextSensitiveHelp (BOOL)   { return E_NOTIMPL; }
 -         JUCE_COMRESULT CanInPlaceActivate()          { return S_OK; }
 -         JUCE_COMRESULT OnInPlaceActivate()           { return S_OK; }
 -         JUCE_COMRESULT OnUIActivate()                { return S_OK; }
 - 
 -         JUCE_COMRESULT GetWindowContext (LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO lpFrameInfo)
 -         {
 -             /* Note: If you call AddRef on the frame here, then some types of object (e.g. web browser control) cause leaks..
 -                If you don't call AddRef then others crash (e.g. QuickTime).. Bit of a catch-22, so letting it leak is probably preferable.
 -             */
 -             if (lplpFrame != nullptr) { frame->AddRef(); *lplpFrame = frame; }
 -             if (lplpDoc != nullptr)   *lplpDoc = nullptr;
 -             lpFrameInfo->fMDIApp = FALSE;
 -             lpFrameInfo->hwndFrame = window;
 -             lpFrameInfo->haccel = nullptr;
 -             lpFrameInfo->cAccelEntries = 0;
 -             return S_OK;
 -         }
 - 
 -         JUCE_COMRESULT Scroll (SIZE)                 { return E_NOTIMPL; }
 -         JUCE_COMRESULT OnUIDeactivate (BOOL)         { return S_OK; }
 -         JUCE_COMRESULT OnInPlaceDeactivate()         { return S_OK; }
 -         JUCE_COMRESULT DiscardUndoState()            { return E_NOTIMPL; }
 -         JUCE_COMRESULT DeactivateAndUndo()           { return E_NOTIMPL; }
 -         JUCE_COMRESULT OnPosRectChange (LPCRECT)     { return S_OK; }
 - 
 -         LRESULT offerEventToActiveXControl (::MSG& msg)
 -         {
 -             if (frame != nullptr)
 -                 return frame->OfferKeyTranslation (&msg);
 - 
 -             return S_FALSE;
 -         }
 - 
 -         HWND window;
 -         JuceOleInPlaceFrame* frame;
 -     };
 - 
 -     //==============================================================================
 -     struct JuceIOleClientSite  : public ComBaseClassHelper<IOleClientSite>
 -     {
 -         JuceIOleClientSite (HWND window)  : inplaceSite (new JuceIOleInPlaceSite (window))
 -         {}
 - 
 -         ~JuceIOleClientSite()
 -         {
 -             inplaceSite->Release();
 -         }
 - 
 -         JUCE_COMRESULT QueryInterface (REFIID type, void** result)
 -         {
 -             if (type == __uuidof (IOleInPlaceSite))
 -             {
 -                 inplaceSite->AddRef();
 -                 *result = static_cast<IOleInPlaceSite*> (inplaceSite);
 -                 return S_OK;
 -             }
 - 
 -             return ComBaseClassHelper <IOleClientSite>::QueryInterface (type, result);
 -         }
 - 
 -         JUCE_COMRESULT SaveObject()                                  { return E_NOTIMPL; }
 -         JUCE_COMRESULT GetMoniker (DWORD, DWORD, IMoniker**)         { return E_NOTIMPL; }
 -         JUCE_COMRESULT GetContainer (LPOLECONTAINER* ppContainer)    { *ppContainer = nullptr; return E_NOINTERFACE; }
 -         JUCE_COMRESULT ShowObject()                                  { return S_OK; }
 -         JUCE_COMRESULT OnShowWindow (BOOL)                           { return E_NOTIMPL; }
 -         JUCE_COMRESULT RequestNewObjectLayout()                      { return E_NOTIMPL; }
 - 
 -         LRESULT offerEventToActiveXControl (::MSG& msg)
 -         {
 -             if (inplaceSite != nullptr)
 -                 return inplaceSite->offerEventToActiveXControl (msg);
 - 
 -             return S_FALSE;
 -         }
 - 
 -         JuceIOleInPlaceSite* inplaceSite;
 -     };
 - 
 -     //==============================================================================
 -     static Array<ActiveXControlComponent*> activeXComps;
 - 
 -     static HWND getHWND (const ActiveXControlComponent* const component)
 -     {
 -         HWND hwnd = {};
 -         const IID iid = __uuidof (IOleWindow);
 - 
 -         if (auto* window = (IOleWindow*) component->queryInterface (&iid))
 -         {
 -             window->GetWindow (&hwnd);
 -             window->Release();
 -         }
 - 
 -         return hwnd;
 -     }
 - 
 -     static void offerActiveXMouseEventToPeer (ComponentPeer* peer, HWND hwnd, UINT message, LPARAM lParam)
 -     {
 -         switch (message)
 -         {
 -             case WM_MOUSEMOVE:
 -             case WM_LBUTTONDOWN:
 -             case WM_MBUTTONDOWN:
 -             case WM_RBUTTONDOWN:
 -             case WM_LBUTTONUP:
 -             case WM_MBUTTONUP:
 -             case WM_RBUTTONUP:
 -             {
 -                 RECT activeXRect, peerRect;
 -                 GetWindowRect (hwnd, &activeXRect);
 -                 GetWindowRect ((HWND) peer->getNativeHandle(), &peerRect);
 - 
 -                 peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse,
 -                                         { (float) (GET_X_LPARAM (lParam) + activeXRect.left - peerRect.left),
 -                                           (float) (GET_Y_LPARAM (lParam) + activeXRect.top  - peerRect.top) },
 -                                         ComponentPeer::getCurrentModifiersRealtime(),
 -                                         MouseInputSource::invalidPressure,
 -                                         MouseInputSource::invalidOrientation,
 -                                         getMouseEventTime());
 -                 break;
 -             }
 - 
 -             default:
 -                 break;
 -         }
 -     }
 - }
 - 
 - //==============================================================================
 - class ActiveXControlComponent::Pimpl  : public ComponentMovementWatcher
 -                                      #if JUCE_WIN_PER_MONITOR_DPI_AWARE
 -                                       , public ComponentPeer::ScaleFactorListener
 -                                      #endif
 - {
 - public:
 -     Pimpl (HWND hwnd, ActiveXControlComponent& activeXComp)
 -         : ComponentMovementWatcher (&activeXComp),
 -           owner (activeXComp),
 -           storage (new ActiveXHelpers::JuceIStorage()),
 -           clientSite (new ActiveXHelpers::JuceIOleClientSite (hwnd))
 -     {
 -     }
 - 
 -     ~Pimpl()
 -     {
 -         if (control != nullptr)
 -         {
 -             control->Close (OLECLOSE_NOSAVE);
 -             control->Release();
 -         }
 - 
 -         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 != nullptr)
 -         {
 -            #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
 -     {
 -         if (controlHWND != nullptr)
 -             ShowWindow (controlHWND, shouldBeVisible ? SW_SHOWNA : SW_HIDE);
 -     }
 - 
 -     //==============================================================================
 -     using ComponentMovementWatcher::componentMovedOrResized;
 - 
 -     void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override
 -     {
 -         if (auto* peer = owner.getTopLevelComponent()->getPeer())
 -             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
 -     }
 - 
 -     using ComponentMovementWatcher::componentVisibilityChanged;
 - 
 -     void componentVisibilityChanged() override
 -     {
 -         setControlVisible (owner.isShowing());
 -         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)
 -     {
 -         for (auto* ax : ActiveXHelpers::activeXComps)
 -         {
 -             if (ax->control != nullptr && ax->control->controlHWND == hwnd)
 -             {
 -                 switch (message)
 -                 {
 -                     case WM_MOUSEMOVE:
 -                     case WM_LBUTTONDOWN:
 -                     case WM_MBUTTONDOWN:
 -                     case WM_RBUTTONDOWN:
 -                     case WM_LBUTTONUP:
 -                     case WM_MBUTTONUP:
 -                     case WM_RBUTTONUP:
 -                     case WM_LBUTTONDBLCLK:
 -                     case WM_MBUTTONDBLCLK:
 -                     case WM_RBUTTONDBLCLK:
 -                         if (ax->isShowing())
 -                         {
 -                             if (auto* peer = ax->getPeer())
 -                             {
 -                                 ActiveXHelpers::offerActiveXMouseEventToPeer (peer, hwnd, message, lParam);
 - 
 -                                 if (! ax->areMouseEventsAllowed())
 -                                     return 0;
 -                             }
 -                         }
 -                         break;
 - 
 -                     default:
 -                         break;
 -                 }
 - 
 -                 return CallWindowProc (ax->control->originalWndProc, hwnd, message, wParam, lParam);
 -             }
 -         }
 - 
 -         return DefWindowProc (hwnd, message, wParam, lParam);
 -     }
 - 
 -     ActiveXControlComponent& owner;
 -     HWND controlHWND = {};
 -     IStorage* storage = nullptr;
 -     ActiveXHelpers::JuceIOleClientSite* clientSite = nullptr;
 -     IOleObject* control = nullptr;
 -     WNDPROC originalWndProc = nullptr;
 - };
 - 
 - //==============================================================================
 - ActiveXControlComponent::ActiveXControlComponent()
 - {
 -     ActiveXHelpers::activeXComps.add (this);
 - }
 - 
 - ActiveXControlComponent::~ActiveXControlComponent()
 - {
 -     deleteControl();
 -     ActiveXHelpers::activeXComps.removeFirstMatchingValue (this);
 - }
 - 
 - void ActiveXControlComponent::paint (Graphics& g)
 - {
 -     if (control == nullptr)
 -         g.fillAll (Colours::lightgrey);
 - }
 - 
 - bool ActiveXControlComponent::createControl (const void* controlIID)
 - {
 -     deleteControl();
 - 
 -     if (auto* peer = getPeer())
 -     {
 -         auto controlBounds = peer->getAreaCoveredBy (*this);
 -         auto hwnd = (HWND) peer->getNativeHandle();
 - 
 -         std::unique_ptr<Pimpl> newControl (new Pimpl (hwnd, *this));
 - 
 -         HRESULT hr = OleCreate (*(const IID*) controlIID, __uuidof (IOleObject), 1 /*OLERENDER_DRAW*/, nullptr,
 -                                 newControl->clientSite, newControl->storage,
 -                                 (void**) &(newControl->control));
 - 
 -         if (hr == S_OK)
 -         {
 -             newControl->control->SetHostNames (L"JUCE", nullptr);
 - 
 -             if (OleSetContainedObject (newControl->control, TRUE) == S_OK)
 -             {
 -                 RECT rect;
 -                 rect.left   = controlBounds.getX();
 -                 rect.top    = controlBounds.getY();
 -                 rect.right  = controlBounds.getRight();
 -                 rect.bottom = controlBounds.getBottom();
 - 
 -                 if (newControl->control->DoVerb (OLEIVERB_SHOW, nullptr, newControl->clientSite, 0, hwnd, &rect) == S_OK)
 -                 {
 -                     control.reset (newControl.release());
 -                     control->controlHWND = ActiveXHelpers::getHWND (this);
 - 
 -                     if (control->controlHWND != nullptr)
 -                     {
 -                         control->setControlBounds (controlBounds);
 - 
 -                         control->originalWndProc = (WNDPROC) GetWindowLongPtr ((HWND) control->controlHWND, GWLP_WNDPROC);
 -                         SetWindowLongPtr ((HWND) control->controlHWND, GWLP_WNDPROC, (LONG_PTR) Pimpl::activeXHookWndProc);
 -                     }
 - 
 -                     return true;
 -                 }
 -             }
 -         }
 -     }
 -     else
 -     {
 -         // the component must have already been added to a real window when you call this!
 -         jassertfalse;
 -     }
 - 
 -     return false;
 - }
 - 
 - void ActiveXControlComponent::deleteControl()
 - {
 -     control = nullptr;
 - }
 - 
 - void* ActiveXControlComponent::queryInterface (const void* iid) const
 - {
 -     void* result = nullptr;
 - 
 -     if (control != nullptr && control->control != nullptr
 -          && SUCCEEDED (control->control->QueryInterface (*(const IID*) iid, &result)))
 -         return result;
 - 
 -     return nullptr;
 - }
 - 
 - void ActiveXControlComponent::setMouseEventsAllowed (const bool eventsCanReachControl)
 - {
 -     mouseEventsAllowed = eventsCanReachControl;
 - }
 - 
 - intptr_t ActiveXControlComponent::offerEventToActiveXControl (void* ptr)
 - {
 -     if (control != nullptr && control->clientSite != nullptr)
 -         return (intptr_t) control->clientSite->offerEventToActiveXControl (*reinterpret_cast<::MSG*> (ptr));
 - 
 -     return S_FALSE;
 - }
 - 
 - intptr_t ActiveXControlComponent::offerEventToActiveXControlStatic (void* ptr)
 - {
 -     for (auto* ax : ActiveXHelpers::activeXComps)
 -     {
 -         auto result = ax->offerEventToActiveXControl (ptr);
 - 
 -         if (result != S_FALSE)
 -             return result;
 -     }
 - 
 -     return S_FALSE;
 - }
 - 
 - LRESULT juce_offerEventToActiveXControl (::MSG& msg)
 - {
 -     if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
 -         return ActiveXControlComponent::offerEventToActiveXControlStatic (&msg);
 - 
 -     return S_FALSE;
 - }
 - 
 - } // namespace juce
 
 
  |