|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-7 by Raw Material Software ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the
- GNU General Public License, as published by the Free Software Foundation;
- either version 2 of the License, or (at your option) any later version.
-
- JUCE is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with JUCE; if not, visit www.gnu.org/licenses or write to the
- Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- Boston, MA 02111-1307 USA
-
- ------------------------------------------------------------------------------
-
- If you'd like to release a closed-source product which uses JUCE, commercial
- licenses are also available: visit www.rawmaterialsoftware.com/juce for
- more information.
-
- ==============================================================================
- */
-
- // (This file gets included by juce_win32_NativeCode.cpp, rather than being
- // compiled on its own).
- #if JUCE_INCLUDED_FILE
-
-
- //==============================================================================
- class JuceIStorage : public IStorage
- {
- int refCount;
-
- public:
- JuceIStorage() : refCount (1) {}
-
- virtual ~JuceIStorage()
- {
- jassert (refCount == 0);
- }
-
- HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
- {
- if (id == IID_IUnknown || id == IID_IStorage)
- {
- AddRef();
- *result = this;
- return S_OK;
- }
-
- *result = 0;
- return E_NOINTERFACE;
- }
-
- ULONG __stdcall AddRef() { return ++refCount; }
- ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
-
- HRESULT __stdcall CreateStream (const WCHAR*, DWORD, DWORD, DWORD, IStream**) { return E_NOTIMPL; }
- HRESULT __stdcall OpenStream (const WCHAR*, void*, DWORD, DWORD, IStream**) { return E_NOTIMPL; }
- HRESULT __stdcall CreateStorage (const WCHAR*, DWORD, DWORD, DWORD, IStorage**) { return E_NOTIMPL; }
- HRESULT __stdcall OpenStorage (const WCHAR*, IStorage*, DWORD, SNB, DWORD, IStorage**) { return E_NOTIMPL; }
- HRESULT __stdcall CopyTo (DWORD, IID const*, SNB, IStorage*) { return E_NOTIMPL; }
- HRESULT __stdcall MoveElementTo (const OLECHAR*,IStorage*, const OLECHAR*, DWORD) { return E_NOTIMPL; }
- HRESULT __stdcall Commit (DWORD) { return E_NOTIMPL; }
- HRESULT __stdcall Revert() { return E_NOTIMPL; }
- HRESULT __stdcall EnumElements (DWORD, void*, DWORD, IEnumSTATSTG**) { return E_NOTIMPL; }
- HRESULT __stdcall DestroyElement (const OLECHAR*) { return E_NOTIMPL; }
- HRESULT __stdcall RenameElement (const WCHAR*, const WCHAR*) { return E_NOTIMPL; }
- HRESULT __stdcall SetElementTimes (const WCHAR*, FILETIME const*, FILETIME const*, FILETIME const*) { return E_NOTIMPL; }
- HRESULT __stdcall SetClass (REFCLSID) { return S_OK; }
- HRESULT __stdcall SetStateBits (DWORD, DWORD) { return E_NOTIMPL; }
- HRESULT __stdcall Stat (STATSTG*, DWORD) { return E_NOTIMPL; }
-
- juce_UseDebuggingNewOperator
- };
-
-
- class JuceOleInPlaceFrame : public IOleInPlaceFrame
- {
- int refCount;
- HWND window;
-
- public:
- JuceOleInPlaceFrame (HWND window_)
- : refCount (1),
- window (window_)
- {
- }
-
- virtual ~JuceOleInPlaceFrame()
- {
- jassert (refCount == 0);
- }
-
- HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
- {
- if (id == IID_IUnknown || id == IID_IOleInPlaceFrame)
- {
- AddRef();
- *result = this;
- return S_OK;
- }
-
- *result = 0;
- return E_NOINTERFACE;
- }
-
- ULONG __stdcall AddRef() { return ++refCount; }
- ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
-
- HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; }
- HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; }
- HRESULT __stdcall GetBorder (LPRECT) { return E_NOTIMPL; }
- HRESULT __stdcall RequestBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; }
- HRESULT __stdcall SetBorderSpace (LPCBORDERWIDTHS) { return E_NOTIMPL; }
- HRESULT __stdcall SetActiveObject (IOleInPlaceActiveObject*, LPCOLESTR) { return S_OK; }
- HRESULT __stdcall InsertMenus (HMENU, LPOLEMENUGROUPWIDTHS) { return E_NOTIMPL; }
- HRESULT __stdcall SetMenu (HMENU, HOLEMENU, HWND) { return S_OK; }
- HRESULT __stdcall RemoveMenus (HMENU) { return E_NOTIMPL; }
- HRESULT __stdcall SetStatusText (LPCOLESTR) { return S_OK; }
- HRESULT __stdcall EnableModeless (BOOL) { return S_OK; }
- HRESULT __stdcall TranslateAccelerator(LPMSG, WORD) { return E_NOTIMPL; }
-
- juce_UseDebuggingNewOperator
- };
-
-
- class JuceIOleInPlaceSite : public IOleInPlaceSite
- {
- int refCount;
- HWND window;
- JuceOleInPlaceFrame* frame;
-
- public:
- JuceIOleInPlaceSite (HWND window_)
- : refCount (1),
- window (window_)
- {
- frame = new JuceOleInPlaceFrame (window);
- }
-
- virtual ~JuceIOleInPlaceSite()
- {
- jassert (refCount == 0);
- frame->Release();
- }
-
- HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
- {
- if (id == IID_IUnknown || id == IID_IOleInPlaceSite)
- {
- AddRef();
- *result = this;
- return S_OK;
- }
-
- *result = 0;
- return E_NOINTERFACE;
- }
-
- ULONG __stdcall AddRef() { return ++refCount; }
- ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
-
- HRESULT __stdcall GetWindow (HWND* lphwnd) { *lphwnd = window; return S_OK; }
- HRESULT __stdcall ContextSensitiveHelp (BOOL) { return E_NOTIMPL; }
- HRESULT __stdcall CanInPlaceActivate() { return S_OK; }
- HRESULT __stdcall OnInPlaceActivate() { return S_OK; }
- HRESULT __stdcall OnUIActivate() { return S_OK; }
-
- HRESULT __stdcall GetWindowContext (LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc, LPRECT, LPRECT, LPOLEINPLACEFRAMEINFO lpFrameInfo)
- {
- frame->AddRef();
- *lplpFrame = frame;
- *lplpDoc = 0;
- lpFrameInfo->fMDIApp = FALSE;
- lpFrameInfo->hwndFrame = window;
- lpFrameInfo->haccel = 0;
- lpFrameInfo->cAccelEntries = 0;
- return S_OK;
- }
-
- HRESULT __stdcall Scroll (SIZE) { return E_NOTIMPL; }
- HRESULT __stdcall OnUIDeactivate (BOOL) { return S_OK; }
- HRESULT __stdcall OnInPlaceDeactivate() { return S_OK; }
- HRESULT __stdcall DiscardUndoState() { return E_NOTIMPL; }
- HRESULT __stdcall DeactivateAndUndo() { return E_NOTIMPL; }
- HRESULT __stdcall OnPosRectChange (LPCRECT) { return S_OK; }
-
- juce_UseDebuggingNewOperator
- };
-
-
- class JuceIOleClientSite : public IOleClientSite
- {
- int refCount;
- JuceIOleInPlaceSite* inplaceSite;
-
- public:
- JuceIOleClientSite (HWND window)
- : refCount (1)
- {
- inplaceSite = new JuceIOleInPlaceSite (window);
- }
-
- virtual ~JuceIOleClientSite()
- {
- jassert (refCount == 0);
- inplaceSite->Release();
- }
-
- HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
- {
- if (id == IID_IUnknown || id == IID_IOleClientSite)
- {
- AddRef();
- *result = this;
- return S_OK;
- }
- else if (id == IID_IOleInPlaceSite)
- {
- inplaceSite->AddRef();
- *result = inplaceSite;
- return S_OK;
- }
-
- *result = 0;
- return E_NOINTERFACE;
- }
-
- ULONG __stdcall AddRef() { return ++refCount; }
- ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
-
- HRESULT __stdcall SaveObject() { return E_NOTIMPL; }
- HRESULT __stdcall GetMoniker (DWORD, DWORD, IMoniker**) { return E_NOTIMPL; }
- HRESULT __stdcall GetContainer (LPOLECONTAINER* ppContainer) { *ppContainer = 0; return E_NOINTERFACE; }
- HRESULT __stdcall ShowObject() { return S_OK; }
- HRESULT __stdcall OnShowWindow (BOOL) { return E_NOTIMPL; }
- HRESULT __stdcall RequestNewObjectLayout() { return E_NOTIMPL; }
-
- juce_UseDebuggingNewOperator
- };
-
- //==============================================================================
- class ActiveXControlData : public ComponentMovementWatcher
- {
- ActiveXControlComponent* const owner;
- bool wasShowing;
-
- public:
- HWND controlHWND;
- IStorage* storage;
- IOleClientSite* clientSite;
- IOleObject* control;
-
- //==============================================================================
- ActiveXControlData (HWND hwnd,
- ActiveXControlComponent* const owner_)
- : ComponentMovementWatcher (owner_),
- owner (owner_),
- wasShowing (owner_ != 0 && owner_->isShowing()),
- controlHWND (0),
- storage (new JuceIStorage()),
- clientSite (new JuceIOleClientSite (hwnd)),
- control (0)
- {
- }
-
- ~ActiveXControlData()
- {
- if (control != 0)
- {
- control->Close (OLECLOSE_NOSAVE);
- control->Release();
- }
-
- clientSite->Release();
- storage->Release();
- }
-
- //==============================================================================
- void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
- {
- Component* const topComp = owner->getTopLevelComponent();
-
- if (topComp->getPeer() != 0)
- {
- int x = 0, y = 0;
- owner->relativePositionToOtherComponent (topComp, x, y);
-
- owner->setControlBounds (Rectangle (x, y, owner->getWidth(), owner->getHeight()));
- }
- }
-
- void componentPeerChanged()
- {
- const bool isShowingNow = owner->isShowing();
-
- if (wasShowing != isShowingNow)
- {
- wasShowing = isShowingNow;
-
- owner->setControlVisible (isShowingNow);
- }
- }
-
- void componentVisibilityChanged (Component&)
- {
- componentPeerChanged();
- }
-
- static bool doesWindowMatch (const ActiveXControlComponent* const ax, HWND hwnd)
- {
- return ((ActiveXControlData*) ax->control) != 0
- && ((ActiveXControlData*) ax->control)->controlHWND == hwnd;
- }
- };
-
- //==============================================================================
- static VoidArray activeXComps;
-
- static HWND getHWND (const ActiveXControlComponent* const component)
- {
- HWND hwnd = 0;
-
- const IID iid = IID_IOleWindow;
- IOleWindow* const window = (IOleWindow*) component->queryInterface (&iid);
-
- if (window != 0)
- {
- window->GetWindow (&hwnd);
- window->Release();
- }
-
- return hwnd;
- }
-
- static void offerActiveXMouseEventToPeer (ComponentPeer* const peer, HWND hwnd, UINT message, LPARAM lParam)
- {
- RECT activeXRect, peerRect;
- GetWindowRect (hwnd, &activeXRect);
- GetWindowRect ((HWND) peer->getNativeHandle(), &peerRect);
-
- const int mx = GET_X_LPARAM (lParam) + activeXRect.left - peerRect.left;
- const int my = GET_Y_LPARAM (lParam) + activeXRect.top - peerRect.top;
- const int64 mouseEventTime = getMouseEventTime();
-
- const int oldModifiers = currentModifiers;
- ModifierKeys::getCurrentModifiersRealtime(); // to update the mouse button flags
-
- switch (message)
- {
- case WM_MOUSEMOVE:
- if (ModifierKeys (currentModifiers).isAnyMouseButtonDown())
- peer->handleMouseDrag (mx, my, mouseEventTime);
- else
- peer->handleMouseMove (mx, my, mouseEventTime);
- break;
-
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- peer->handleMouseDown (mx, my, mouseEventTime);
- break;
-
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- peer->handleMouseUp (oldModifiers, mx, my, mouseEventTime);
- break;
-
- default:
- break;
- }
- }
-
- // 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 (int i = activeXComps.size(); --i >= 0;)
- {
- const ActiveXControlComponent* const ax = (const ActiveXControlComponent*) activeXComps.getUnchecked(i);
-
- if (ActiveXControlData::doesWindowMatch (ax, 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())
- {
- ComponentPeer* const peer = ax->getPeer();
-
- if (peer != 0)
- {
- offerActiveXMouseEventToPeer (peer, hwnd, message, lParam);
-
- if (! ax->areMouseEventsAllowed())
- return 0;
- }
- }
- break;
-
- default:
- break;
- }
-
- return CallWindowProc ((WNDPROC) (ax->originalWndProc), hwnd, message, wParam, lParam);
- }
- }
-
- return DefWindowProc (hwnd, message, wParam, lParam);
- }
-
- ActiveXControlComponent::ActiveXControlComponent()
- : originalWndProc (0),
- control (0),
- mouseEventsAllowed (true)
- {
- activeXComps.add (this);
- }
-
- ActiveXControlComponent::~ActiveXControlComponent()
- {
- deleteControl();
- activeXComps.removeValue (this);
- }
-
- void ActiveXControlComponent::paint (Graphics& g)
- {
- if (control == 0)
- g.fillAll (Colours::lightgrey);
- }
-
- bool ActiveXControlComponent::createControl (const void* controlIID)
- {
- deleteControl();
- ComponentPeer* const peer = getPeer();
-
- // the component must have already been added to a real window when you call this!
- jassert (dynamic_cast <Win32ComponentPeer*> (peer) != 0);
-
- if (dynamic_cast <Win32ComponentPeer*> (peer) != 0)
- {
- int x = 0, y = 0;
- relativePositionToOtherComponent (getTopLevelComponent(), x, y);
-
- HWND hwnd = (HWND) peer->getNativeHandle();
-
- ActiveXControlData* const info = new ActiveXControlData (hwnd, this);
-
- HRESULT hr;
- if ((hr = OleCreate (*(const IID*) controlIID, IID_IOleObject, 1 /*OLERENDER_DRAW*/, 0,
- info->clientSite, info->storage,
- (void**) &(info->control))) == S_OK)
- {
- info->control->SetHostNames (L"Juce", 0);
-
- if (OleSetContainedObject (info->control, TRUE) == S_OK)
- {
- RECT rect;
- rect.left = x;
- rect.top = y;
- rect.right = x + getWidth();
- rect.bottom = y + getHeight();
-
- if (info->control->DoVerb (OLEIVERB_SHOW, 0, info->clientSite, 0, hwnd, &rect) == S_OK)
- {
- control = info;
- setControlBounds (Rectangle (x, y, getWidth(), getHeight()));
-
- info->controlHWND = getHWND (this);
-
- if (info->controlHWND != 0)
- {
- originalWndProc = (void*) (pointer_sized_int) GetWindowLongPtr ((HWND) info->controlHWND, GWLP_WNDPROC);
- SetWindowLongPtr ((HWND) info->controlHWND, GWLP_WNDPROC, (LONG_PTR) activeXHookWndProc);
- }
-
- return true;
- }
- }
- }
-
- delete info;
- }
-
- return false;
- }
-
- void ActiveXControlComponent::deleteControl()
- {
- ActiveXControlData* const info = (ActiveXControlData*) control;
-
- if (info != 0)
- {
- delete info;
- control = 0;
- originalWndProc = 0;
- }
- }
-
- void* ActiveXControlComponent::queryInterface (const void* iid) const
- {
- ActiveXControlData* const info = (ActiveXControlData*) control;
-
- void* result = 0;
-
- if (info != 0 && info->control != 0
- && info->control->QueryInterface (*(const IID*) iid, &result) == S_OK)
- return result;
-
- return 0;
- }
-
- void ActiveXControlComponent::setControlBounds (const Rectangle& newBounds) const
- {
- HWND hwnd = ((ActiveXControlData*) control)->controlHWND;
-
- if (hwnd != 0)
- MoveWindow (hwnd, newBounds.getX(), newBounds.getY(), newBounds.getWidth(), newBounds.getHeight(), TRUE);
- }
-
- void ActiveXControlComponent::setControlVisible (const bool shouldBeVisible) const
- {
- HWND hwnd = ((ActiveXControlData*) control)->controlHWND;
-
- if (hwnd != 0)
- ShowWindow (hwnd, shouldBeVisible ? SW_SHOWNA : SW_HIDE);
- }
-
- void ActiveXControlComponent::setMouseEventsAllowed (const bool eventsCanReachControl)
- {
- mouseEventsAllowed = eventsCanReachControl;
- }
-
- #endif
|