// Copyright (C) Microsoft Corporation 1996-1997, All Rights reserved. #include "header.h" #include "contain.h" #include "autocont.h" #include "htmlpriv.h" #include "htmlhelp.h" #include "strtable.h" #include #include "unicode.h" static const WCHAR gszHHRegKey[] = L"Software\\Microsoft\\HtmlHelp"; // pointer to external IServiceProvider (fix for HelpCenter) // IServiceProvider *g_pExternalHostServiceProvider = NULL; #ifdef _DEBUG #undef THIS_FILE static const char THIS_FILE[] = __FILE__; #endif /* * CContainer::CContainer * CContainer::~CContainer * * Constructor Parameters: */ CContainer::CContainer() { m_cRef = 0; m_pIStorage = NULL; m_pOleObject = NULL; m_pIAdviseSink = NULL; m_pIOleInPlaceSite = NULL; m_pIOleClientSite = NULL; m_pIOleInPlaceFrame = NULL; m_pIOleControlSite = NULL; m_pWebBrowser = NULL; m_pWebBrowserApp = NULL; m_pIDispatch = NULL; m_pIOleItemContainer = NULL; // m_pCallback = NULL; m_pIE3CmdTarget = NULL; m_dwEventCookie = 0; m_pWebBrowserEvents = NULL; m_pCDocHostUIHandler = NULL; m_pCDocHostShowUI = NULL; m_pInPlaceActive = 0; #ifdef _DEBUG m_fDeleting = FALSE; #endif } CContainer::~CContainer(void) { #ifdef _DEBUG ASSERT(!m_fDeleting) m_fDeleting = TRUE; #endif // if (m_pInPlaceActive) // m_pInPlaceActive->Release(); // do this before we release m_pIAdviseSink // Reset the View Advise LPVIEWOBJECT2 lpViewObject2; if (m_pOleObject && SUCCEEDED(m_pOleObject->QueryInterface(IID_IViewObject2, (LPVOID FAR *) &lpViewObject2))) { lpViewObject2->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, NULL ); lpViewObject2->Release(); } if (m_pIAdviseSink) m_pIAdviseSink->Release(); if (m_pIOleInPlaceSite) m_pIOleInPlaceSite->Release(); if (m_pIOleClientSite) m_pIOleClientSite->Release(); if (m_pIOleInPlaceFrame) m_pIOleInPlaceFrame->Release(); if (m_pIOleItemContainer) m_pIOleItemContainer->Release(); if (m_pIOleControlSite) delete m_pIOleControlSite; // if (m_pIPropNoteSink) // delete m_pIPropNoteSink; if (m_pIE3CmdTarget) m_pIE3CmdTarget->Release(); if ( m_pCDocHostUIHandler ) m_pCDocHostUIHandler->Release(); if ( m_pCDocHostShowUI ) m_pCDocHostShowUI->Release(); if (m_pWebBrowserApp) { m_pWebBrowserApp->Quit(); delete m_pWebBrowserApp; } if (m_pIStorage) m_pIStorage->Release(); if (m_pOleObject) m_pOleObject->Release(); return; } HRESULT CContainer::ShutDown(void) { if (m_pIDispatch) { // Unhook event interface, delete our interface object // LPCONNECTIONPOINTCONTAINER pCPC; if (SUCCEEDED(m_pOleObject->QueryInterface(IID_IConnectionPointContainer, (void **) &pCPC))) { LPCONNECTIONPOINT pCP; if (SUCCEEDED(pCPC->FindConnectionPoint(IID_IDispatch, &pCP))) { pCP->Unadvise(m_dwEventCookie); pCP->Release(); } // Cleanup pCPC->Release() ; } // Cleanup m_pIDispatch pointer m_pIDispatch->Release(); m_pIDispatch = NULL; // part of fix for 4373 } if(m_pOleObject) { m_pOleObject->Close(OLECLOSE_NOSAVE); m_pOleObject->SetClientSite(NULL); } delete this; return S_OK; } /* * CContainer::QueryInterface * * Purpose: * IUnknown members for CContainer object. */ STDMETHODIMP CContainer::QueryInterface(REFIID riid, LPVOID * ppv) { #ifdef DEBUG char sz[256]; wsprintf(sz,"CContainer::QueryInterface('{%8.8X-%4.4X-%4.4X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X}',...);\r\n", riid.Data1, riid.Data2, riid.Data3, riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6],riid.Data4[7]); OutputDebugString(sz); #endif *ppv=NULL; if ((IID_IUnknown == riid) || (IID_IServiceProvider == riid)) *ppv = this; else if (IID_IOleClientSite == riid) *ppv = m_pIOleClientSite; else if (IID_IAdviseSink2==riid || IID_IAdviseSink==riid) *ppv = m_pIAdviseSink; else if (IID_IOleWindow==riid || IID_IOleInPlaceSite==riid) *ppv = m_pIOleInPlaceSite; else if (IID_IOleItemContainer == riid || IID_IOleContainer == riid || IID_IParseDisplayName == riid) *ppv = m_pIOleItemContainer; else if (riid == DIID_DWebBrowserEvents) { DBWIN("QueryInterface for DIID_DWebBrowserEvents"); *ppv = (LPDISPATCH)m_pIDispatch; } else if (riid == DIID_DWebBrowserEvents2) { DBWIN("QueryInterface for DIID_DWebBrowserEvents2"); *ppv = (LPDISPATCH)m_pIDispatch; } else if (IID_IOleControlSite==riid) { DBWIN("QueryInterface for IID_IOleControlSite"); *ppv=m_pIOleControlSite; } else if ( riid == IID_IDocHostUIHandler ) { DBWIN("QueryInterface for IID_IDocHostUIHandler"); *ppv = m_pCDocHostUIHandler; } else if ( riid == IID_IDocHostShowUI ) { DBWIN("QueryInterface for IID_IDocHostShowUI"); *ppv = m_pCDocHostShowUI; } // BUGBUG what to do about this ? // Queries for IDispatch return the ambient properties interface *ppv=m_pIDispatch; else if (IID_IDispatch==riid) { DBWIN("QueryInterface for IID_IDispatch"); *ppv = (IDispatch*)m_pIDispatch; } //End CONTROLMOD if (*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP CContainer::QueryService(REFGUID rsid, REFIID riid, void ** pv) { HRESULT hr = E_NOINTERFACE; // Hack for HelpCenter... if (g_pExternalHostServiceProvider) { hr = g_pExternalHostServiceProvider->QueryService(rsid, riid, pv); } return hr; } STDMETHODIMP_(ULONG) CContainer::AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) CContainer::Release(void) { ULONG cRefT = --m_cRef; // we only delete when specifically told to // if (m_cRef == 0) // delete this; return cRefT; } HRESULT CContainer::Create(HWND hWnd, LPRECT lpRect, BOOL bInstallEventSink) { LPUNKNOWN pObj; CLSID clsidWB1 = { 0xeab22ac3, 0x30c1, 0x11cf, { 0xa7, 0xeb, 0x0, 0x0, 0xc0, 0x5b, 0xae, 0xb } }; CLSID clsidWB2 = { 0x8856f961, 0x340a, 0x11d0, { 0xa9, 0x6b, 0x0, 0xc0, 0x4f, 0xd7, 0x5, 0xa2 } }; UINT uRet = (UINT) E_FAIL; HRESULT hr; m_hWnd = hWnd; // Create storage, use OLE's temporary compound file support. (ie NULL as first arg.) if ((hr = StgCreateDocfile(NULL, (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE), 0, &m_pIStorage)) != S_OK) { DEBUG_ReportOleError(hr); return E_FAIL; } // Create the client site. m_pIOleClientSite = new CIOleClientSite(this); m_pIOleClientSite->AddRef(); // Create the control site. m_pIOleControlSite = new CIOleControlSite(this); m_pIOleControlSite->AddRef(); // Create the advise sink. m_pIAdviseSink = new CIAdviseSink(this); m_pIAdviseSink->AddRef(); // Create the InPlaceSite. m_pIOleInPlaceSite = new CIOleInPlaceSite(this); m_pIOleInPlaceSite->AddRef(); // Create the InPlaceFrame; m_pIOleInPlaceFrame = new CIOleInPlaceFrame(this); m_pIOleInPlaceFrame->AddRef(); // // We don't install a sink for the special printing instance. HtmlHelp bug 5550. // if ( bInstallEventSink ) { m_pIDispatch = new CAutomateContent(this); m_pIDispatch->AddRef(); } m_pIOleItemContainer = new CIOleItemContainer(this); m_pIOleItemContainer->AddRef(); /* * The OLE Control specifications mention that a a control might * implement IPersistStreamInit instead of IPersistStorage. In that * case you cannot use OleCreate on a control but must rather use * CoCreateInstance since OleCreate assumes that IPersistStorage is * available. With a control, you would have to create the object * first, then check if OLEMISC_SETCLIENTSITEFIRST is set, then send it * your IOleClientSite first. Then you check for IPersistStorage and * failing that, try IPersistStreamInit. * In this sample we do none of this and just assume controls are * normal embedded objects because there are questions as to dealing * with loading and initialization that are not resolved. */ // These are IE4 specific. // m_pCDocHostUIHandler = new CDocHostUIHandler(this); m_pCDocHostUIHandler->AddRef(); m_pCDocHostShowUI = new CDocHostShowUI(this); m_pCDocHostShowUI->AddRef(); // first try for the IE4 object, if that fails, try for the IE3 object. // if ((hr = OleCreate(clsidWB2, IID_IOleObject, OLERENDER_NONE, NULL, m_pIOleClientSite, m_pIStorage, (void**)&pObj)) != S_OK ) { if ((hr = OleCreate(clsidWB1, IID_IOleObject, OLERENDER_NONE, NULL, m_pIOleClientSite, m_pIStorage, (void**)&pObj)) != S_OK ) { m_pIStorage->Release(); m_pIOleClientSite->Release(); return hr; } m_bIE4 = FALSE; } else m_bIE4 = TRUE; if ((hr = pObj->QueryInterface(IID_IOleObject, (void **) &m_pOleObject)) == S_OK) { LPVIEWOBJECT2 lpViewObject2; // Set a View Advise if (SUCCEEDED(m_pOleObject->QueryInterface(IID_IViewObject2, (LPVOID FAR *) &lpViewObject2))) { lpViewObject2->SetAdvise(DVASPECT_CONTENT, ADVF_PRIMEFIRST, m_pIAdviseSink); lpViewObject2->Release(); } // 13-Oct-1997 [ralphw] Shouldn't need this... // m_pOleObject->SetHostNames(OLESTR("DevIV Package"), OLESTR("DevIV Container")); // inform object handler/DLL object that it is used in the embedding container's context OleSetContainedObject(m_pOleObject, TRUE); // Hook iDispatch up to COleDispatchDriver interface. LPDISPATCH pDispatch; if ((hr = m_pOleObject->QueryInterface(IID_IDispatch, (void **) &pDispatch)) == S_OK) { m_pWebBrowserApp = new IWebBrowserAppImpl(pDispatch); } // // We don't install a sink for the special printing instance. HtmlHelp bug 5550. // if ( bInstallEventSink ) { // Hook event interface. LPCONNECTIONPOINTCONTAINER pCPC; if (SUCCEEDED(hr = m_pOleObject->QueryInterface(IID_IConnectionPointContainer, (void **) &pCPC))) { LPCONNECTIONPOINT pCP; if (SUCCEEDED(pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &pCP))) { pCP->Advise((IDispatch*)m_pIDispatch, &m_dwEventCookie); pCP->Release(); } else if (SUCCEEDED(pCPC->FindConnectionPoint(DIID_DWebBrowserEvents, &pCP))) { pCP->Advise((IDispatch*)m_pIDispatch, &m_dwEventCookie); pCP->Release(); } pCPC->Release(); } } // Let's get an interface pointer to IOleCommandTarget hr = m_pOleObject->QueryInterface(IID_IOleCommandTarget, (void **)&m_pIE3CmdTarget); if (FAILED(hr)) m_pIE3CmdTarget = NULL; // Show the control. m_pOleObject->DoVerb(OLEIVERB_SHOW, NULL, m_pIOleClientSite, -1, m_hWnd, lpRect); uRet = S_OK; } pObj->Release(); // always release this ? if (uRet != S_OK) { m_pIStorage->Release(); m_pIOleClientSite->Release(); return uRet; } return uRet; } // // Called when the window containing IE is losing activation (focus). // void CContainer::UIDeactivateIE() { IOleInPlaceObject* pIOleInPlaceObject; HRESULT hr; if ( SUCCEEDED((hr = m_pOleObject->QueryInterface(IID_IOleInPlaceObject, (void**)&pIOleInPlaceObject))) ) { pIOleInPlaceObject->UIDeactivate(); pIOleInPlaceObject->Release(); } } void CContainer::SetFocus(BOOL bForceActivation) { HWND hwnd_child; TCHAR szClassName[150]; if (! m_pInPlaceActive || bForceActivation ) m_pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_pIOleClientSite, -1, m_hWnd, NULL); m_hwndChild = m_hWnd; while ((hwnd_child = GetWindow(m_hwndChild, GW_CHILD)) && IsWindowEnabled(hwnd_child) ) { m_hwndChild = hwnd_child; GetClassName(hwnd_child, szClassName, sizeof(szClassName)); if ( strstr(szClassName, "Internet Explorer") ) break; } if ( hwnd_child && !IsWindowEnabled(hwnd_child) ) m_hwndChild = GetParent(m_hwndChild); ::SetFocus(m_hwndChild); } // // This needs to be called from the apps message pump to give shdocvw a crack at accelerators // it implements. For example ^C for copy selected text. // // This function will return TRUE if shdocvw traslated the message and FALSE if it did not. // Note that you can run into trouble if the app and shdocvw share acclerators. We'll want to // always call TranslateAccelartor() from the message pump for the apps accelators and only if // it returns false will we call this function to give IE a crack at the message. // // mikecole // unsigned CContainer::TranslateMessage(MSG * pMsg) { if (m_pInPlaceActive) { if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_F1 ) return TAMSG_NOT_IE_ACCEL; if (pMsg->message == WM_KEYDOWN) { if (GetKeyState(VK_CONTROL)) { if (pMsg->wParam == 0x4F || pMsg->wParam == 0x4C || pMsg->wParam == 0x4E) return TAMSG_NOT_IE_ACCEL; } } if (m_pInPlaceActive->TranslateAccelerator(pMsg) == S_OK) return TAMSG_IE_ACCEL; else { if ( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) ) { if ( IsUIActive() && !m_bIE4) { // translateAccelerator does not work for the tab key in IE3, // so forward the VK_TAB key message to IE3 ForwardMessage(pMsg->message, pMsg->wParam, pMsg->lParam); return TAMSG_IE_ACCEL; } UIDeactivateIE(); SetFocus(); } } } return TAMSG_NOT_IE_ACCEL; } LRESULT CContainer::ForwardMessage(UINT msg, WPARAM wParam, LPARAM lParam) { HWND hwnd_child; HWND hwnd = m_hWnd; while ( (hwnd_child = GetWindow(hwnd, GW_CHILD)) && IsWindowEnabled(hwnd_child) ) hwnd = hwnd_child; if ( hwnd_child && !IsWindowEnabled(hwnd_child) ) hwnd = GetParent(hwnd); if (hwnd) return ::SendMessage(hwnd, msg, wParam, lParam); else return 0; } void CContainer::SizeIt(int width, int height) { IOleInPlaceObject* pIOleInPlaceObject; if ( m_bIE4 ) { if ( SUCCEEDED((m_pOleObject->QueryInterface(IID_IOleInPlaceObject, (void**)&pIOleInPlaceObject))) ) { RECT rc; rc.left = rc.top = 0; rc.bottom = height; rc.right = width; pIOleInPlaceObject->SetObjectRects(&rc,&rc); pIOleInPlaceObject->Release(); } } else { SIZEL sizel; sizel.cx = width; sizel.cy = height; HDC hdc = GetDC(NULL); SetMapMode(hdc, MM_HIMETRIC); DPtoLP(hdc, (LPPOINT) &sizel, 1); ReleaseDC(NULL, hdc); sizel.cy = abs(sizel.cy); m_pOleObject->SetExtent(DVASPECT_CONTENT, &sizel); } } /************************************************************************************** * AdviseSink code * * * CIAdviseSink implementation begins here! * **************************************************************************************/ /* * CIAdviseSink::CIAdviseSink * CIAdviseSink::~CIAdviseSink * * Parameters (Constructor): * pCContainer pCContainer of the Container we're in. * pUnkOuter LPUNKNOWN to which we delegate. */ CIAdviseSink::CIAdviseSink(PCONTAINER pCContainer) { m_cRef=0; m_pUnkOuter = m_pContainer = pCContainer; return; } CIAdviseSink::~CIAdviseSink(void) { return; } /* * CIAdviseSink::QueryInterface * CIAdviseSink::AddRef * CIAdviseSink::Release * * Purpose: * IUnknown members for CIAdviseSink object. */ STDMETHODIMP CIAdviseSink::QueryInterface(REFIID riid, LPVOID * ppv) { return m_pUnkOuter->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CIAdviseSink::AddRef(void) { m_pUnkOuter->AddRef(); return ++m_cRef; } STDMETHODIMP_(ULONG) CIAdviseSink::Release(void) { ULONG ul = --m_cRef; m_pUnkOuter->Release(); if (ul <= 0) delete this; return ul; } /* * CIAdviseSink::OnDataChange * * Unused since we don't IDataObject::Advise. */ STDMETHODIMP_(void) CIAdviseSink::OnDataChange(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM) { return; } /* * CIAdviseSink::OnViewChange * * Purpose: * Notifes the advise sink that presentation data changed in the * data object to which we're connected providing the right time * to update displays using such presentations. * * Parameters: * dwAspect DWORD indicating which aspect has changed. * lindex LONG indicating the piece that changed. * * Return Value: * None */ STDMETHODIMP_(void) CIAdviseSink::OnViewChange(DWORD dwAspect, LONG lindex) { //Repaint only if this is the right aspect //m_pContainer->Repaint(); return; } /* * CIAdviseSink::OnRename * * Purpose: * Informs the advise sink that a linked object has been renamed. * Generally only the OLE default handler cares about this. * * Parameters: * pmk LPMONIKER providing the new name of the object * * Return Value: * None */ STDMETHODIMP_(void) CIAdviseSink::OnRename(LPMONIKER pmk) { /* * As a container this is unimportant to us since it really * tells the handler's implementation of IOleLink that the * object's moniker has changed. Since we get this call * from the handler, we don't have to do anything ourselves. */ return; } /* * CIAdviseSink::OnSave * * Purpose: * Informs the advise sink that the OLE object has been saved * persistently. The primary purpose of this is for containers * that want to make optimizations for objects that are not in a * saved state, so on this you have to disable such optimizations. * * Parameters: * None * * Return Value: * None */ STDMETHODIMP_(void) CIAdviseSink::OnSave(void) { /* * A Container has nothing to do here as this notification is * only useful when we have an ADVFCACHE_ONSAVE advise set up, * which we don't. So we ignore it. */ return; } /* * CIAdviseSink::OnClose * * Purpose: * Informs the advise sink that the OLE object has closed and is * no longer bound in any way. * * Parameters: * None * * Return Value: * None */ STDMETHODIMP_(void) CIAdviseSink::OnClose(void) { /* * This doesn't have anything to do with us again as it's only * used to notify the handler's IOleLink implementation of the * change in the object. We don't have to do anything since * we'll also get an IOleClientSite::OnShowWindow(FALSE) to * tell us to repaint. */ return; } /* * CIAdviseSink2::OnLinkSrcChange * * Purpose: * Informs the advise sink that a linked compound document object * has changed its link source to the object identified by the * given moniker. This is generally only of interest to the OLE * default handler's implementation of linked objects. * * Parameters: * pmk LPMONIKER specifying the new link source. * * Return Value: * None */ STDMETHODIMP_(void) CIAdviseSink::OnLinkSrcChange(LPMONIKER pmk) { return; } /************************************************************************************** * * ClientSite code * * * CIOleClientSite implementation begins here! * **************************************************************************************/ /* * CIOleClientSite::CIOleClientSite * CIOleClientSite::~CIOleClientSite * * Parameters (Constructor): * pCContainer PCContainer of the container we're in. * pUnkOuter LPUNKNOWN to which we delegate. */ CIOleClientSite::CIOleClientSite(PCONTAINER pCContainer) { m_cRef=0; m_pUnkOuter = m_pContainer = pCContainer; return; } CIOleClientSite::~CIOleClientSite(void) { return; } /* * CIOleClientSite::QueryInterface * CIOleClientSite::AddRef * CIOleClientSite::Release * * Purpose: * IUnknown members for CIOleClientSite object. */ STDMETHODIMP CIOleClientSite::QueryInterface(REFIID riid, LPVOID * ppv) { return m_pUnkOuter->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CIOleClientSite::AddRef(void) { m_pUnkOuter->AddRef(); return ++m_cRef; } STDMETHODIMP_(ULONG) CIOleClientSite::Release(void) { ULONG ul = --m_cRef; m_pUnkOuter->Release(); if (ul <= 0) delete this; return ul; } /* * CIOleClientSite::SaveObject * * Purpose: * Requests that the container call OleSave for the object that * lives here. Typically this happens on server shutdown. * * Parameters: * None * * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::SaveObject(void) { // We're already set up with the tenant to save; this is trivial. //pCContainer->Update(); return NOERROR; } /* * CIOleClientSite::GetMoniker * * Purpose: * Retrieves the moniker for the site in which this object lives, * either the moniker relative to the container or the full * moniker. * * Parameters: * dwAssign DWORD specifying that the object wants moniker * assignment. Yeah. Right. Got any bridges to * sell? * dwWhich DWORD identifying which moniker the object * wants, either the container's moniker, the * moniker relative to this client site, or the * full moniker. * * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::GetMoniker(DWORD dwAssign, DWORD dwWhich, LPMONIKER *ppmk) { *ppmk=NULL; switch (dwWhich) { case OLEWHICHMK_CONTAINER: //This is just the file we're living in. break; case OLEWHICHMK_OBJREL: //This is everything but the filename. break; case OLEWHICHMK_OBJFULL: //Concatenate file and relative monikers for this one. break; } if (NULL==*ppmk) return ResultFromScode(E_FAIL); (*ppmk)->AddRef(); return NOERROR; } /* * CIOleClientSite::GetContainer * * Purpose: * Returns a pointer to the document's IOleContainer interface. * * Parameters: * ppContainer LPOLECONTAINER * in which to return the * interface. * * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::GetContainer(LPOLECONTAINER* ppContainer) { if (m_pContainer) return m_pContainer->QueryInterface(IID_IOleItemContainer, (LPVOID *)ppContainer); return ResultFromScode(E_FAIL); } /* * CIOleClientSite::ShowObject * * Purpose: * Tells the container to bring the object fully into view as much * as possible, that is, scroll the document. * * Parameters: * None * * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::ShowObject(void) { // deligate back to CContainer // m_pContainer->ShowObject(); return NOERROR; } /* * CIOleClientSite::OnShowWindow * * Purpose: * Informs the container if the object is showing itself or * hiding itself. This is done only in the opening mode and allows * the container to know when to shade or unshade the object. * * Parameters: * fShow BOOL indiciating that the object is being shown * (TRUE) or hidden (FALSE). * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::OnShowWindow(BOOL fShow) { // deligate back to CContainer // m_pContainer->OnShowWindow(fShow); return NOERROR; } /* * CIOleClientSite::RequestNewObjectLayout * * Purpose: * Called when the object would like to have its layout * reinitialized. This is used by OLE Controls. * * Parameters: * None * * Return Value: * HRESULT Standard. */ STDMETHODIMP CIOleClientSite::RequestNewObjectLayout(void) { // deligate back to CContainer // m_pContainer->RequestNewObjectLayout(); return NOERROR; } /************************************************************************************** * * InPlaceSite code * * * CIOleInPlaceSite implementation begins here! * **************************************************************************************/ /* * CIOleInPlaceSite::CIOleInPlaceSite * CIOleInPlaceSite::~CIOleInPlaceSite * * Parameters (Constructor): * pCContainer Pointer to the container we're in. * pUnkOuter LPUNKNOWN to which we delegate. */ CIOleInPlaceSite::CIOleInPlaceSite(PCONTAINER pCContainer) { m_cRef=0; m_pUnkOuter = m_pContainer = pCContainer; return; } CIOleInPlaceSite::~CIOleInPlaceSite(void) { ASSERT(m_cRef == 0); return; } /* * CIOleInPlaceSite::QueryInterface * CIOleInPlaceSite::AddRef * CIOleInPlaceSite::Release * * Purpose: * IUnknown members for CIOleInPlaceSite object. */ STDMETHODIMP CIOleInPlaceSite::QueryInterface(REFIID riid, LPVOID * ppv) { return m_pUnkOuter->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CIOleInPlaceSite::AddRef(void) { m_pUnkOuter->AddRef(); return ++m_cRef; } STDMETHODIMP_(ULONG) CIOleInPlaceSite::Release(void) { ULONG ul = --m_cRef; m_pUnkOuter->Release(); if (ul <= 0) delete this; return ul; } /* * CIOleInPlaceActiveObject::GetWindow * * Purpose: * Retrieves the handle of the window associated with the object * on which this interface is implemented. * * Parameters: * phWnd HWND * in which to store the window handle. * * Return Value: * HRESULT NOERROR if successful, E_FAIL if there is no * window. */ STDMETHODIMP CIOleInPlaceSite::GetWindow(HWND *phWnd) { *phWnd = m_pContainer->m_hWnd; return NOERROR; } /* * CIOleInPlaceActiveObject::ContextSensitiveHelp * * Purpose: * Instructs the object on which this interface is implemented to * enter or leave a context-sensitive help mode. * * Parameters: * fEnterMode BOOL TRUE to enter the mode, FALSE otherwise. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceSite::ContextSensitiveHelp(BOOL fEnterMode) { return NOERROR; } /* * CIOleInPlaceSite::CanInPlaceActivate * * Purpose: * Answers the server whether or not we can currently in-place * activate its object. By implementing this interface we say * that we support in-place activation, but through this function * we indicate whether the object can currently be activated * in-place. Iconic aspects, for example, cannot, meaning we * return S_FALSE. * * Parameters: * None * * Return Value: * HRESULT NOERROR if we can in-place activate the object * in this site, S_FALSE if not. */ STDMETHODIMP CIOleInPlaceSite::CanInPlaceActivate(void) { return NOERROR; } /* * CIOleInPlaceSite::OnInPlaceActivate * * Purpose: * Informs the container that an object is being activated in-place * such that the container can prepare appropriately. The * container does not, however, make any user interface changes at * this point. See OnUIActivate. * * Parameters: * None * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::OnInPlaceActivate(void) { // BUGBUG: Mikecole - Does this belong here ? //if (FAILED(m_pOleObject->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&m_pInPlaceActive))) // m_pInPlaceActive = 0; return NOERROR; } /* * CIOleInPlaceSite::OnInPlaceDeactivate * * Purpose: * Notifies the container that the object has deactivated itself * from an in-place state. Opposite of OnInPlaceActivate. The * container does not change any UI at this point. * * Parameters: * None * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::OnInPlaceDeactivate(void) { // BUGBUG: Mikecole - Does this belong here ? //if (FAILED(m_pOleObject->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&m_pInPlaceActive))) // m_pInPlaceActive = 0; return NOERROR; } /* * CIOleInPlaceSite::OnUIActivate * * Purpose: * Informs the container that the object is going to start munging * around with user interface, like replacing the menu. The * container should remove any relevant UI in preparation. * * Parameters: * None * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::OnUIActivate(void) { return NOERROR; } /* * CIOleInPlaceSite::OnUIDeactivate * * Purpose: * Informs the container that the object is deactivating its * in-place user interface at which time the container may * reinstate its own. Opposite of OnUIActivate. * * Parameters: * fUndoable BOOL indicating if the object will actually * perform an Undo if the container calls * ReactivateAndUndo. * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::OnUIDeactivate(BOOL fUndoable) { return NOERROR; } /* * CIOleInPlaceSite::DeactivateAndUndo * * Purpose: * If immediately after activation the object does an Undo, the * action being undone is the activation itself, and this call * informs the container that this is, in fact, what happened. * The container should call IOleInPlaceObject::UIDeactivate. * * Parameters: * None * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::DeactivateAndUndo(void) { //CONTROLMOD /* * Note that we don't pay attention to the locking * from IOleControlSite::LockInPlaceActive since only * the object calls this function and should know * that it's going to be deactivated. */ //End CONTROLMOD return NOERROR; } /* * CIOleInPlaceSite::DiscardUndoState * * Purpose: * Informs the container that something happened in the object * that means the container should discard any undo information * it currently maintains for the object. * * Parameters: * None * * Return Value: * HRESULT NOERROR or an appropriate error code. */ STDMETHODIMP CIOleInPlaceSite::DiscardUndoState(void) { return ResultFromScode(E_NOTIMPL); } /* * CIOleInPlaceSite::GetWindowContext * * Purpose: * Provides an in-place object with pointers to the frame and * document level in-place interfaces (IOleInPlaceFrame and * IOleInPlaceUIWindow) such that the object can do border * negotiation and so forth. Also requests the position and * clipping rectangles of the object in the container and a * pointer to an OLEINPLACEFRAME info structure which contains * accelerator information. * * Note that the two interfaces this call returns are not * available through QueryInterface on IOleInPlaceSite since they * live with the frame and document, but not the site. * * Parameters: * ppIIPFrame LPOLEINPLACEFRAME * in which to return the * AddRef'd pointer to the container's * IOleInPlaceFrame. * ppIIPUIWindow LPOLEINPLACEUIWINDOW * in which to return * the AddRef'd pointer to the container document's * IOleInPlaceUIWindow. * prcPos LPRECT in which to store the object's position. * prcClip LPRECT in which to store the object's visible * region. * pFI LPOLEINPLACEFRAMEINFO to fill with accelerator * stuff. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceSite::GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) { RECT rect; // the frame is associated with the application object. // need to AddRef() it... m_pContainer->m_pIOleInPlaceFrame->AddRef(); *lplpFrame = m_pContainer->m_pIOleInPlaceFrame; *lplpDoc = NULL; // must be NULL, cause we're SDI. // get the size of the object in pixels ::GetClientRect(m_pContainer->m_hWnd, &rect); // This may be bogus! // Copy this to the passed buffer CopyRect(lprcPosRect, &rect); // fill the clipping region CopyRect(lprcClipRect, &rect); // fill the FRAMEINFO lpFrameInfo->fMDIApp = FALSE; lpFrameInfo->hwndFrame = m_pContainer->m_hWnd; lpFrameInfo->haccel = NULL; lpFrameInfo->cAccelEntries = 0; return ResultFromScode(S_OK); } /* * CIOleInPlaceSite::Scroll * * Purpose: * Asks the container to scroll the document, and thus the object, * by the given amounts in the sz parameter. * * Parameters: * sz SIZE containing signed horizontal and vertical * extents by which the container should scroll. * These are in device units. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceSite::Scroll(SIZE sz) { return NOERROR; } /* * CIOleInPlaceSite::OnPosRectChange * * Purpose: * Informs the container that the in-place object was resized. * The container must call IOleInPlaceObject::SetObjectRects. * This does not change the site's rectangle in any case. * * Parameters: * prcPos LPCRECT containing the new size of the object. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceSite::OnPosRectChange(LPCRECT prcPos) { // m_pContainer->UpdateInPlaceObjectRects(prcPos, FALSE); return NOERROR; } /************************************************************************************** * * InPlaceFrame code * * * CIOleInPlaceFrame implementation begins here! * **************************************************************************************/ /* * CIOleInPlaceFrame::CIOleInPlaceFrame * CIOleInPlaceFrame::~CIOleInPlaceFrame * * Parameters (Constructor): * pTen PCTenant of the tenant we're in. * pUnkOuter LPUNKNOWN to which we delegate. */ CIOleInPlaceFrame::CIOleInPlaceFrame(PCONTAINER pCContainer) { m_cRef=0; m_pUnkOuter = m_pContainer = pCContainer; return; } CIOleInPlaceFrame::~CIOleInPlaceFrame(void) { ASSERT(m_cRef == 0); return; } /* * CIOleInPlaceFrame::QueryInterface * CIOleInPlaceFrame::AddRef * CIOleInPlaceFrame::Release * * Purpose: * IUnknown members for CIOleInPlaceFrame object. */ STDMETHODIMP CIOleInPlaceFrame::QueryInterface(REFIID riid, LPVOID * ppv) { //We only know IUnknown and IOleInPlaceFrame *ppv=NULL; //Remember to do ALL base interfaces if ( IID_IUnknown == riid || IID_IOleInPlaceUIWindow == riid || IID_IOleWindow == riid || IID_IOleInPlaceFrame == riid ) *ppv=(LPOLEINPLACEFRAME)this; if (NULL!=*ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CIOleInPlaceFrame::AddRef(void) { m_pUnkOuter->AddRef(); return ++m_cRef; } STDMETHODIMP_(ULONG) CIOleInPlaceFrame::Release(void) { ULONG ul = --m_cRef; m_pUnkOuter->Release(); if (ul <= 0) delete this; return ul; } /* * CIOleInPlaceFrame::GetWindow * * Purpose: * Retrieves the handle of the window associated with the object * on which this interface is implemented. * * Parameters: * phWnd HWND * in which to store the window handle. * * Return Value: * HRESULT NOERROR if successful, E_FAIL if there is no * window. */ STDMETHODIMP CIOleInPlaceFrame::GetWindow(HWND *phWnd) { *phWnd = m_pContainer->m_hWnd; return NOERROR; } /* * CIOleInPlaceFrame::ContextSensitiveHelp * * Purpose: * Instructs the object on which this interface is implemented to * enter or leave a context-sensitive help mode. * * Parameters: * fEnterMode BOOL TRUE to enter the mode, FALSE otherwise. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::ContextSensitiveHelp(BOOL fEnterMode) { // If we had an embedded control with menus, this would get called on an // f1 keypress with a menu pulled down. // return NOERROR; } /* * CIOleInPlaceFrame::GetBorder * * Purpose: * Returns the rectangle in which the container is willing to * negotiate about an object's adornments. * * Parameters: * prcBorder LPRECT in which to store the rectangle. * * Return Value: * HRESULT NOERROR if all is well, INPLACE_E_NOTOOLSPACE * if there is no negotiable space. */ STDMETHODIMP CIOleInPlaceFrame::GetBorder(LPRECT prcBorder) { if (NULL==prcBorder) return ResultFromScode(E_INVALIDARG); /* * We return all the client area space sans the StatStrip, * which we control */ GetClientRect(m_pContainer->m_hWnd, prcBorder); return NOERROR; } /* * CIOleInPlaceFrame::RequestBorderSpace * * Purpose: * Asks the container if it can surrender the amount of space * in pBW that the object would like for it's adornments. The * container does nothing but validate the spaces on this call. * * Parameters: * pBW LPCBORDERWIDTHS containing the requested space. * The values are the amount of space requested * from each side of the relevant window. * * Return Value: * HRESULT NOERROR if we can give up space, * INPLACE_E_NOTOOLSPACE otherwise. */ STDMETHODIMP CIOleInPlaceFrame::RequestBorderSpace(LPCBORDERWIDTHS pBW) { //Everything is fine with us, so always return an OK. // mikecole/douglash Should either return inplace_e_notoolspace or we should honor the // request for border space below in setborderspace(). return INPLACE_E_NOTOOLSPACE; } /* * CIOleInPlaceFrame::SetBorderSpace * * Purpose: * Called when the object now officially requests that the * container surrender border space it previously allowed * in RequestBorderSpace. The container should resize windows * appropriately to surrender this space. * * Parameters: * pBW LPCBORDERWIDTHS containing the amount of space * from each side of the relevant window that the * object is now reserving. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::SetBorderSpace(LPCBORDERWIDTHS pBW) { return NOERROR; } /* * CIOleInPlaceFrame::InsertMenus * * Purpose: * Instructs the container to place its in-place menu items where * necessary in the given menu and to fill in elements 0, 2, and 4 * of the OLEMENUGROUPWIDTHS array to indicate how many top-level * items are in each group. * * Parameters: * hMenu HMENU in which to add popups. * pMGW LPOLEMENUGROUPWIDTHS in which to store the * width of each container menu group. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::InsertMenus(HMENU hMenu, LPOLEMENUGROUPWIDTHS pMGW) { return NOERROR; } /* * CIOleInPlaceFrame::SetMenu * * Purpose: * Instructs the container to replace whatever menu it's currently * using with the given menu and to call OleSetMenuDescritor so OLE * knows to whom to dispatch messages. * * Parameters: * hMenu HMENU to show. * hOLEMenu HOLEMENU to the menu descriptor. * hWndObj HWND of the active object to which messages are * dispatched. * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::SetMenu(HMENU hMenu, HOLEMENU hOLEMenu, HWND hWndObj) { /* * Our responsibilities here are to put the menu on the frame * window and call OleSetMenuDescriptor. * CPatronClient::SetMenu which we call here takes care of * MDI/SDI differences. * * We also want to save the object's hWnd for use in WM_SETFOCUS * processing. */ return NOERROR; } /* * CIOleInPlaceFrame::RemoveMenus * * Purpose: * Asks the container to remove any menus it put into hMenu in * InsertMenus. * * Parameters: * hMenu HMENU from which to remove the container's * items. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::RemoveMenus(HMENU hMenu) { /* * To be defensive, loop through this menu removing anything * we recognize (that is, anything in m_phMenu) just in case * the server didn't clean it up right. At least we can * give ourselves the prophylactic benefit. */ /* * Walk backwards down the menu. For each popup, see if it * matches any other popup we know about, and if so, remove * it from the shared menu. */ return NOERROR; } /* * CIOleInPlaceFrame::SetStatusText * * Purpose: * Asks the container to place some text in a status line, if one * exists. If the container does not have a status line it * should return E_FAIL here in which case the object could * display its own. * * Parameters: * pszText LPCTSTR to display. * * Return Value: * HRESULT NOERROR if successful, S_TRUNCATED if not all * of the text could be displayed, or E_FAIL if * the container has no status line. */ STDMETHODIMP CIOleInPlaceFrame::SetStatusText(LPCOLESTR pszText) { /* * Just send this to the StatStrip. Unfortunately it won't tell * us about truncation. Oh well, we'll just act like it worked. */ if (pszText) { #if 0 char buf[256]; 25-Sep-1997 [ralphw] Can't find SetPrompt in IV source code if (ConvertWz(pszText, buf, sizeof(buf))) { if (*pszText) SetPrompt(buf, TRUE); else SetPrompt(); } #endif } return NOERROR; } /* * CIOleInPlaceFrame::EnableModeless * * Purpose: * Instructs the container to show or hide any modeless popup * windows that it may be using. * * Parameters: * fEnable BOOL indicating to enable/show the windows * (TRUE) or to hide them (FALSE). * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleInPlaceFrame::EnableModeless(BOOL fEnable) { return NOERROR; } /* * CIOleInPlaceFrame::TranslateAccelerator * * Purpose: * When dealing with an in-place object from an EXE server, this * is called to give the container a chance to process accelerators * after the server has looked at the message. * * Parameters: * pMSG LPMSG for the container to examine. * wID WORD the identifier in the container's * accelerator table (from IOleInPlaceSite * ::GetWindowContext) for this message (OLE does * some translation before calling). * * Return Value: * HRESULT NOERROR if the keystroke was used, * S_FALSE otherwise. */ STDMETHODIMP CIOleInPlaceFrame::TranslateAccelerator(LPMSG pMSG, WORD wID) { /* * wID already has anything translated from m_hAccelIP for us, * so we can just check for the commands we want and process * them instead of calling TranslateAccelerator which would be * redundant and which also has a possibility of dispatching to * the wrong window. */ // if (pMSG->message == WM_KEYDOWN && pMSG->wParam == VK_ESCAPE) // PostMessage(CUR_HWND, WM_CLOSE, 0, 0); return S_FALSE; } /*********************************************************************** * * COleInPlaceFrame::SetActiveObject * * Purpose: * * * Parameters: * * LPOLEINPLACEACTIVEOBJECT lpActiveObject - Pointer to the * objects * IOleInPlaceActiveObject * interface * * @@WTK WIN32, UNICODE * //LPCSTR lpszObjName - Name of the object * LPCOLESTR lpszObjName - Name of the object * * Return Value: * * S_OK * * Function Calls: * Function Location * * OutputDebugString Windows API * IOleInPlaceActiveObject::AddRef Object * IOleInPlaceActiveObject::Release Object * ResultFromScode OLE API * * Comments: * ********************************************************************/ STDMETHODIMP CIOleInPlaceFrame::SetActiveObject(LPOLEINPLACEACTIVEOBJECT lpActiveObject, LPCOLESTR lpszObjName) { // in an MDI app, this method really shouldn't be called, // this method associated with the doc is called instead. // should set window title here if ( m_pContainer->m_pInPlaceActive ) m_pContainer->m_pInPlaceActive->Release(); if (lpActiveObject) lpActiveObject->AddRef(); m_pContainer->m_pInPlaceActive = lpActiveObject; return NOERROR; } /********************************************************************* * * CIOleControlSite Implementation starts here. * * /* * CIOleControlSite::CIOleControlSite * CIOleControlSite::~CIOleControlSite * * Parameters (Constructor): * pTen PCTenant of the object we're in. * pUnkOuter LPUNKNOWN to which we delegate. */ CIOleControlSite::CIOleControlSite(PCONTAINER pCContainer) { m_cRef=0; m_pUnkOuter = m_pContainer = pCContainer; return; } CIOleControlSite::~CIOleControlSite(void) { return; } /* * CIOleControlSite::QueryInterface * CIOleControlSite::AddRef * CIOleControlSite::Release * * Purpose: * Delegating IUnknown members for CIOleControlSite. */ STDMETHODIMP CIOleControlSite::QueryInterface(REFIID riid, LPVOID *ppv) { return m_pUnkOuter->QueryInterface(riid, ppv); } STDMETHODIMP_(ULONG) CIOleControlSite::AddRef(void) { ++m_cRef; return m_pUnkOuter->AddRef(); } STDMETHODIMP_(ULONG) CIOleControlSite::Release(void) { --m_cRef; return m_pUnkOuter->Release(); } /* * CIOleControlSite::OnControlInfoChanged * * Purpose: * Informs the site that the CONTROLINFO for the control has * changed and we thus need to reload the data. * * Parameters: * None * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleControlSite::OnControlInfoChanged(void) { return NOERROR; } /* * CIOleControlSite::LockInPlaceActive * * Purpose: * Forces the container to keep this control in-place active * (but not UI active) regardless of other considerations, or * removes this lock. * * Parameters: * fLock BOOL indicating to lock (TRUE) or unlock (FALSE) * in-place activation. * * Return Value: * HRESULT NOERROR */ STDMETHODIMP CIOleControlSite::LockInPlaceActive(BOOL fLock) { return NOERROR; } /* * CIOleControlSite::GetExtendedControl * * Purpose: * Returns a pointer to the container's extended control that wraps * the actual control in this site, if one exists. * * Parameters: * ppDispatch LPDISPATCH * in which to return the pointer * to the extended control's IDispatch interface. * * Return Value: * HRESULT NOERROR or a general error value. */ STDMETHODIMP CIOleControlSite::GetExtendedControl(LPDISPATCH* ppDispatch) { *ppDispatch=NULL; return ResultFromScode(E_NOTIMPL); } /* * CIOleControlSite::TransformCoords * * Purpose: * Converts coordinates in HIMETRIC units into those used by the * container. * * Parameters: * pptlHiMet POINTL * containing either the coordinates to * transform to container or where to store the * transformed container coordinates. * pptlCont POINTF * containing the container coordinates. * dwFlags DWORD containing instructional flags. * * Return Value: * HRESULT NOERROR or a general error value. */ STDMETHODIMP CIOleControlSite::TransformCoords(POINTL *pptlHiMet, POINTF *pptlCont, DWORD dwFlags) { if (NULL==pptlHiMet || NULL==pptlCont) return ResultFromScode(E_POINTER); /* * Convert coordinates. We use MM_LOMETRIC which means that * to convert from HIMETRIC we divide by 10 and negate the y * coordinate. Conversion to HIMETRIC means negate the y * and multiply by 10. Note that size and position are * considered the same thing, that is, we don't differentiate * the two. */ if (XFORMCOORDS_HIMETRICTOCONTAINER & dwFlags) { pptlCont->x=(float)(pptlHiMet->x/10); pptlCont->y=(float)-(pptlHiMet->y/10); } else { pptlHiMet->x=(long)(pptlCont->x*10); pptlHiMet->y=(long)-(pptlCont->y*10); } return NOERROR; } /* * CIOleControlSite::TranslateAccelerator * * Purpose: * Instructs the container to translate a keyboard accelerator * message that the control has picked up instead. * * Parameters: * pMsg LPMSG to the message to translate. * grfModifiers DWORD flags with additional instructions. * * Return Value: * HRESULT NOERROR or a general error value. */ STDMETHODIMP CIOleControlSite::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers) { #ifdef _DEBUG char sz[1000]; HWND hWnd; hWnd = GetFocus(); wsprintf(sz,"CIOleControlSite::TranslateAccelerator()\nGetFocus == %X\npMsg->hwnd = %X\npMsg->message = %X\npMsg->wParam = %X\npMsg->lParam = %X\npMsg->time = %X\npMsg->pt.x = %X\npMsg->pt.y = %X\n", hWnd,pMsg->hwnd,pMsg->message,pMsg->wParam,pMsg->lParam,pMsg->time,pMsg->pt.x,pMsg->pt.y); OutputDebugString(sz); #endif return ResultFromScode(E_NOTIMPL); } /* * CIOleControlSite::OnFocus * * Purpose: * Informs the container that focus has either been lost or * gained in the control. * * Parameters: * fGotFocus BOOL indicating that the control gained (TRUE) * or lost (FALSE) focus. * * Return Value: * HRESULT NOERROR or a general error value. */ STDMETHODIMP CIOleControlSite::OnFocus(BOOL fGotFocus) { //We don't handle default buttons, so this is not interesting return NOERROR; } /* * CIOleControlSite::ShowPropertyFrame * * Purpose: * Instructs the container to show the property frame if * this is, in fact, an extended object. * * Parameters: * None * * Return Value: * HRESULT NOERROR or a general error value. */ STDMETHODIMP CIOleControlSite::ShowPropertyFrame(void) { //We don't do extended objects, so nothing to do here. return ResultFromScode(E_NOTIMPL); } //#endif // CIOleControlSite /******************************************************************** * * Implementation of IOleItemContainer * * We don't actually use this interface, but need to return one so * the IE control can QI it for IDispatch. Why they don't just QI the * site I don't know. */ CIOleItemContainer::CIOleItemContainer(IUnknown * pOuter) { m_cRef = 0; m_pOuter = pOuter; } // aggregating IUnknown methods STDMETHODIMP CIOleItemContainer::QueryInterface(REFIID riid, LPVOID * ppv) { *ppv = 0; if (m_pOuter) return m_pOuter->QueryInterface(riid,ppv); else return E_NOINTERFACE; #if 0 if (riid == IID_IUnknown || riid == IID_IOleItemContainer || riid == IID_IOleContainer || riid == IID_IParseDisplayName) { *ppv = (LPVOID)(IDispatch*)this; AddRef(); return S_OK; } return E_NOINTERFACE; #endif } STDMETHODIMP_(ULONG) CIOleItemContainer::AddRef(void) { m_cRef++; if (m_pOuter) m_pOuter->AddRef(); return m_cRef; } STDMETHODIMP_(ULONG) CIOleItemContainer::Release(void) { ULONG c = --m_cRef; if (m_pOuter) m_pOuter->Release(); if (c <= 0) delete this; return c; } STDMETHODIMP CIOleItemContainer::ParseDisplayName(IBindCtx *, LPOLESTR,ULONG*,IMoniker**) { return E_NOTIMPL; } STDMETHODIMP CIOleItemContainer::EnumObjects(DWORD,LPENUMUNKNOWN*) { return E_NOTIMPL; } STDMETHODIMP CIOleItemContainer::LockContainer(BOOL) { return E_NOTIMPL; } STDMETHODIMP CIOleItemContainer::GetObject(LPOLESTR,DWORD,IBindCtx*,REFIID,void**) { return E_NOTIMPL; } STDMETHODIMP CIOleItemContainer::GetObjectStorage(LPOLESTR,IBindCtx*,REFIID,void**) { return E_NOTIMPL; } STDMETHODIMP CIOleItemContainer::IsRunning(LPOLESTR) { return S_FALSE; } int ConvertWz(const WCHAR * pwz, char * psz, int len) { BOOL fDefault = FALSE; return WideCharToMultiByte(CP_ACP, 0, pwz, wcslen(pwz) + 1, psz, len, "*", &fDefault); } /********************************************************************************************* * * CDocHostUIHandler * * IE4 only QI()'s our control site for one of these. Most of these functions are called from * IE's IOleInPlaceActiveObject coorisponding members. This gives us a great deal of control * over UI compared to what we had with IE3. Using IDocHostUIHandler members me can: * * Control the right click context menu. * Control the window border. * Keep seperate registry settings from IE. * Handle keyboard accelarators more intelegently. */ CDocHostUIHandler::CDocHostUIHandler(IUnknown * pOuter) { m_cRef = 0; m_pOuter = pOuter; } STDMETHODIMP CDocHostUIHandler::QueryInterface(REFIID riid, LPVOID * ppv) { *ppv = 0; if (m_pOuter) return m_pOuter->QueryInterface(riid,ppv); else return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CDocHostUIHandler::AddRef(void) { m_cRef++; if (m_pOuter) m_pOuter->AddRef(); return m_cRef; } STDMETHODIMP_(ULONG) CDocHostUIHandler::Release(void) { ULONG c = --m_cRef; if (m_pOuter) m_pOuter->Release(); if (c <= 0) delete this; return c; } STDMETHODIMP CDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved) { // We cannot define these below since they are already incorrectly defined in include\mshtmlhst.h // so we will just use the hard-coded values instead //#define CONTEXT_MENU_DEFAULT 0 // typically blank areas in the topic //#define CONTEXT_MENU_IMAGE 1 // bitmaps, etc. //#define CONTEXT_MENU_CONTROL 2 //#define CONTEXT_MENU_TABLE 3 //#define CONTEXT_MENU_DEBUG 4 // seleted text uses this id //#define CONTEXT_MENU_1DSELECT 5 // these are links //#define CONTEXT_MENU_ANCHOR 6 //#define CONTEXT_MENU_IMGDYNSRC 7 if( dwID == 0 || dwID == 1 || dwID == 5 ) { if( HMENU hMenu = CreatePopupMenu() ) { #define IDTB_REBASE 1000 #define HTMLID_REBASE 2000 if( dwID == 0 ) { HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, IDTB_REBASE+IDTB_BACK, GetStringResource(IDS_OPTION_BACK) ); HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, IDTB_REBASE+IDTB_FORWARD, GetStringResource(IDS_OPTION_FORWARD) ); AppendMenu( hMenu, MF_SEPARATOR, -1, NULL ); HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, OLECMDID_SELECTALL, GetStringResource(IDS_OPTION_SELECTALL) ); AppendMenu( hMenu, MF_SEPARATOR, -1, NULL ); HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, HTMLID_REBASE+HTMLID_VIEWSOURCE, GetStringResource(IDS_OPTION_VIEWSOURCE) ); AppendMenu( hMenu, MF_SEPARATOR, -1, NULL ); HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, OLECMDID_PRINT, GetStringResource(IDS_OPTION_PRINT) ); HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, OLECMDID_REFRESH, GetStringResource(IDS_OPTION_REFRESH) ); AppendMenu( hMenu, MF_SEPARATOR, -1, NULL ); } if( dwID == 1 ) { HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, OLECMDID_COPY, GetStringResource(IDS_OPTION_COPY) ); AppendMenu( hMenu, MF_SEPARATOR, -1, NULL ); } HxAppendMenu( hMenu, MF_STRING | MF_ENABLED, OLECMDID_PROPERTIES, GetStringResource(IDS_OPTION_PROPERTIES) ); VARIANT vaIn; VARIANT vaOut; ::VariantInit(&vaIn); ::VariantInit(&vaOut); HWND hWndParent = NULL; hWndParent = ((CContainer*) m_pOuter)->m_hwndChild; if( !IsValidWindow(hWndParent) ) hWndParent = GetActiveWindow(); if( !hWndParent ) hWndParent = GetDesktopWindow(); int iCmd = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, (*ppt).x, (*ppt).y, 0, hWndParent, NULL); DestroyMenu( hMenu ); if( iCmd < IDTB_REBASE ) { if( iCmd == OLECMDID_PROPERTIES ) { // Trident folks say the In value must be set to the mouse pos V_VT(&vaIn) = VT_I4; V_I4(&vaIn) = MAKELONG((*ppt).x,(*ppt).y); } ((IOleCommandTarget*)pcmdtReserved)->Exec( NULL, iCmd, OLECMDEXECOPT_DODEFAULT, &vaIn, &vaOut ); } else if( iCmd < HTMLID_REBASE ) { iCmd -=IDTB_REBASE; if( iCmd == IDTB_BACK ) ((CContainer*) m_pOuter)->m_pWebBrowserApp->GoBack(); else if( iCmd == IDTB_FORWARD ) ((CContainer*) m_pOuter)->m_pWebBrowserApp->GoForward(); } else { iCmd -=HTMLID_REBASE; ((IOleCommandTarget*)pcmdtReserved)->Exec( &CGID_IWebBrowserPriv, iCmd, OLECMDEXECOPT_DODEFAULT, &vaIn, &vaOut ); } } return S_OK; } else return S_FALSE; } STDMETHODIMP CDocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo) { pInfo->dwFlags = 0; pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; return S_OK; } STDMETHODIMP CDocHostUIHandler::ShowUI(DWORD dwID, IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc) { return S_OK; } STDMETHODIMP CDocHostUIHandler::HideUI(void) { return S_OK; } STDMETHODIMP CDocHostUIHandler::UpdateUI(void) { return S_OK; } STDMETHODIMP CDocHostUIHandler::EnableModeless(BOOL fEnable) { return S_OK; } STDMETHODIMP CDocHostUIHandler::OnDocWindowActivate(BOOL fActivate) { return S_OK; } STDMETHODIMP CDocHostUIHandler::OnFrameWindowActivate(BOOL fActivate) { return S_OK; } STDMETHODIMP CDocHostUIHandler::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow) { return S_OK; } STDMETHODIMP CDocHostUIHandler::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID) { return S_FALSE; } STDMETHODIMP CDocHostUIHandler::GetOptionKeyPath(LPOLESTR *pchKey, DWORD dw) { #if 0 // The key given will be stored under HKEY_CURRETN_USER. // if ( (*pchKey = (LPOLESTR)CoTaskMemAlloc((lstrlenW(gszHHRegKey)*sizeof(WCHAR))+sizeof(WCHAR))) ) { wcscpy(*pchKey, gszHHRegKey); return S_OK; } #endif return S_FALSE; } STDMETHODIMP CDocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget) { return E_NOTIMPL; } STDMETHODIMP CDocHostUIHandler::GetExternal(IDispatch **ppDispatch) { *ppDispatch = NULL; return E_NOTIMPL; } STDMETHODIMP CDocHostUIHandler::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut) { return S_FALSE; } STDMETHODIMP CDocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet) { return S_FALSE; } /********************************************************************************************* * * CDocHostShowUI * */ CDocHostShowUI::CDocHostShowUI(IUnknown * pOuter) { m_cRef = 0; m_pOuter = pOuter; } STDMETHODIMP CDocHostShowUI::QueryInterface(REFIID riid, LPVOID * ppv) { *ppv = 0; if (m_pOuter) return m_pOuter->QueryInterface(riid,ppv); else return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CDocHostShowUI::AddRef(void) { m_cRef++; if (m_pOuter) m_pOuter->AddRef(); return m_cRef; } STDMETHODIMP_(ULONG) CDocHostShowUI::Release(void) { ULONG c = --m_cRef; if (m_pOuter) m_pOuter->Release(); if (c <= 0) delete this; return c; } STDMETHODIMP CDocHostShowUI::ShowHelp( HWND hwnd, LPOLESTR pszHelpFile, UINT uCommand, DWORD dwData, POINT ptMouse, IDispatch* pDispatchObjectHit ) { return S_FALSE; } STDMETHODIMP CDocHostShowUI::ShowMessage( HWND hwnd, LPOLESTR lpstrText, LPOLESTR lpstrCaption, DWORD dwType, LPOLESTR lpstrHelpFile, DWORD dwHelpContext, LRESULT* plResult ) { return S_FALSE; }