Win32HtmlViewRep( Win32HtmlView *view, HWND hw,int style ):hwnd(hw){ owner=view; site.rep=this; eventsink.rep=this; frame.rep=this; viewstyle=style; emitNavEvent=!!(viewstyle & BBHtmlView::NONAVIGATE); currenturl=new BBString(""); eventurl=new BBString(""); OleCreate( CLSID_WebBrowser,IID_IOleObject,OLERENDER_DRAW,0,&site,&storage,(void**)&oleObject ); OleSetContainedObject( oleObject,TRUE); oleObject->SetHostNames(L"Web Host",L"Web View"); oleObject->QueryInterface(IID_IWebBrowser2,(void**)&iBrowser); oleObject->QueryInterface(IID_IOleInPlaceObject,(void**)&inPlaceObject ); oleObject->QueryInterface(IID_IConnectionPointContainer,(void**)&iConnection); iConnection->FindConnectionPoint(DIID_DWebBrowserEvents, &iConnectionPoint); iConnectionPoint->Advise((LPUNKNOWN)&eventsink, &dwCookie); RECT rect; ::GetClientRect( hwnd,&rect ); oleObject->DoVerb(OLEIVERB_SHOW,NULL,&site,-1,hwnd,&rect); go( "about:blank" ); }
//获取信息 bool CImageDataObject::IntercalateReObject(REOBJECT & ReObject, IOleClientSite * pIOleClientSite) { //状态判断 ASSERT(m_StgMedium.hBitmap!=NULL); if (m_StgMedium.hBitmap==NULL) return false; //创建对象 if ((m_pIOleObject==NULL)||(m_pIStorage==NULL)) { try { //创建存储 LPLOCKBYTES lpLockBytes=NULL; CreateILockBytesOnHGlobal(NULL,TRUE,&lpLockBytes); StgCreateDocfileOnILockBytes(lpLockBytes,STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,0,&m_pIStorage); //创建对象 OleCreateStaticFromData(this,IID_IOleObject,OLERENDER_FORMAT,&m_FormatEtc,NULL,m_pIStorage,(VOID * *)&m_pIOleObject); OleSetContainedObject(m_pIOleObject,TRUE); //对象效验 ASSERT((m_pIOleObject!=NULL)&&(m_pIStorage!=NULL)); if ((m_pIOleObject==NULL)||(m_pIStorage==NULL)) throw 0; } catch (...) { //释放对象 if (m_pIOleObject!=NULL) { m_pIOleObject->Release(); m_pIOleObject=NULL; } //释放对象 if (m_pIStorage!=NULL) { m_pIStorage->Release(); m_pIStorage=NULL; } return false; } } //设置变量 ZeroMemory(&ReObject,sizeof(ReObject)); //属性信息 ReObject.cbStruct=sizeof(ReObject); ReObject.cp=REO_CP_SELECTION; ReObject.dvaspect=DVASPECT_CONTENT; m_pIOleObject->GetUserClassID(&ReObject.clsid); //接口信息 ReObject.pstg=m_pIStorage; ReObject.poleobj=m_pIOleObject; ReObject.polesite=pIOleClientSite; return true; }
BOOL EmbedBrowserObject(PWBOBJ pwbo) { HWND hwnd; IOleObject *browserObject; IWebBrowser2 *webBrowser2; RECT rect; char *ptr; _IOleClientSiteEx *_iOleClientSiteEx; if(!pwbo) return FALSE; hwnd = pwbo->hwnd; if(!(ptr = (char *)GlobalAlloc(GMEM_FIXED, sizeof(_IOleClientSiteEx) + sizeof(IOleObject *)))) return FALSE; _iOleClientSiteEx = (_IOleClientSiteEx *)(ptr + sizeof(IOleObject *)); _iOleClientSiteEx->client.lpVtbl = &MyIOleClientSiteTable; _iOleClientSiteEx->inplace.inplace.lpVtbl = &MyIOleInPlaceSiteTable; _iOleClientSiteEx->inplace.frame.frame.lpVtbl = &MyIOleInPlaceFrameTable; _iOleClientSiteEx->inplace.frame.window = hwnd; _iOleClientSiteEx->ui.ui.lpVtbl = &MyIDocHostUIHandlerTable; if(!OleCreate((REFCLSID)&CLSID_WebBrowser, (IID *)&IID_IOleObject, OLERENDER_DRAW, 0, (IOleClientSite *)_iOleClientSiteEx, &MyIStorage, (void**)&browserObject)) { *((IOleObject **)ptr) = browserObject; // The original code uses SetWindowLong/GetWindowLong with GWL_USERDATA to store the // browser object pointer. we use pwbo->lparams[0] because the former is already used // to store the WinBinder object. pwbo->lparams[0] = (LONG)ptr; // SetWindowLong(hwnd, GWL_USERDATA, (LONG)ptr); browserObject->lpVtbl->SetHostNames(browserObject, L"My Host Name", 0); GetClientRect(hwnd, &rect); if(!OleSetContainedObject((struct IUnknown *)browserObject, TRUE) && !browserObject->lpVtbl->DoVerb(browserObject, OLEIVERB_SHOW, NULL, (IOleClientSite *)_iOleClientSiteEx, -1, hwnd, &rect) && !browserObject->lpVtbl->QueryInterface(browserObject, (IID *)&IID_IWebBrowser2, (void**)&webBrowser2)) { webBrowser2->lpVtbl->put_Left(webBrowser2, 0); webBrowser2->lpVtbl->put_Top(webBrowser2, 0); webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right); webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom); webBrowser2->lpVtbl->Release(webBrowser2); return TRUE; } UnEmbedBrowserObject(hwnd); return FALSE; } GlobalFree(ptr); return FALSE; }
bool ActiveXControlComponent::createControl (const void* controlIID) { deleteControl(); if (ComponentPeer* const peer = getPeer()) { const Rectangle<int> bounds (peer->getAreaCoveredBy (*this)); HWND hwnd = (HWND) peer->getNativeHandle(); ScopedPointer<Pimpl> newControl (new Pimpl (hwnd, *this)); HRESULT hr; if ((hr = OleCreate (*(const IID*) controlIID, IID_IOleObject, 1 /*OLERENDER_DRAW*/, 0, newControl->clientSite, newControl->storage, (void**) &(newControl->control))) == S_OK) { newControl->control->SetHostNames (L"JUCE", 0); if (OleSetContainedObject (newControl->control, TRUE) == S_OK) { RECT rect; rect.left = bounds.getX(); rect.top = bounds.getY(); rect.right = bounds.getRight(); rect.bottom = bounds.getBottom(); if (newControl->control->DoVerb (OLEIVERB_SHOW, 0, newControl->clientSite, 0, hwnd, &rect) == S_OK) { control = newControl; control->controlHWND = ActiveXHelpers::getHWND (this); if (control->controlHWND != 0) { control->setControlBounds (bounds); 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; }
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) != nullptr); if (dynamic_cast <Win32ComponentPeer*> (peer) != nullptr) { const Point<int> pos (getTopLevelComponent()->getLocalPoint (this, Point<int>())); HWND hwnd = (HWND) peer->getNativeHandle(); ScopedPointer<Pimpl> newControl (new Pimpl (hwnd, *this)); HRESULT hr; if ((hr = OleCreate (*(const IID*) controlIID, IID_IOleObject, 1 /*OLERENDER_DRAW*/, 0, newControl->clientSite, newControl->storage, (void**) &(newControl->control))) == S_OK) { newControl->control->SetHostNames (L"Juce", 0); if (OleSetContainedObject (newControl->control, TRUE) == S_OK) { RECT rect; rect.left = pos.getX(); rect.top = pos.getY(); rect.right = pos.getX() + getWidth(); rect.bottom = pos.getY() + getHeight(); if (newControl->control->DoVerb (OLEIVERB_SHOW, 0, newControl->clientSite, 0, hwnd, &rect) == S_OK) { control = newControl; setControlBounds (Rectangle<int> (pos.getX(), pos.getY(), getWidth(), getHeight())); control->controlHWND = ActiveXHelpers::getHWND (this); if (control->controlHWND != 0) { originalWndProc = (void*) (pointer_sized_int) GetWindowLongPtr ((HWND) control->controlHWND, GWLP_WNDPROC); SetWindowLongPtr ((HWND) control->controlHWND, GWLP_WNDPROC, (LONG_PTR) Pimpl::activeXHookWndProc); } return true; } } } } return false; }
BOOL InitWebBrowser(HHInfo *info, HWND hwndParent) { WebBrowserContainer *container; IOleInPlaceObject *inplace; HRESULT hr; RECT rc; container = heap_alloc_zero(sizeof(*container)); if (!container) return FALSE; container->IOleClientSite_iface.lpVtbl = &OleClientSiteVtbl; container->IOleInPlaceSite_iface.lpVtbl = &OleInPlaceSiteVtbl; container->IOleInPlaceFrame_iface.lpVtbl = &OleInPlaceFrameVtbl; container->IDocHostUIHandler_iface.lpVtbl = &DocHostUIHandlerVtbl; container->ref = 1; container->hwndWindow = hwndParent; info->web_browser = container; hr = OleCreate(&CLSID_WebBrowser, &IID_IOleObject, OLERENDER_DRAW, 0, &container->IOleClientSite_iface, &MyIStorage, (void **)&container->ole_obj); if (FAILED(hr)) goto error; GetClientRect(hwndParent, &rc); hr = OleSetContainedObject((struct IUnknown *)container->ole_obj, TRUE); if (FAILED(hr)) goto error; hr = IOleObject_DoVerb(container->ole_obj, OLEIVERB_SHOW, NULL, &container->IOleClientSite_iface, -1, hwndParent, &rc); if (FAILED(hr)) goto error; hr = IOleObject_QueryInterface(container->ole_obj, &IID_IOleInPlaceObject, (void**)&inplace); if (FAILED(hr)) goto error; IOleInPlaceObject_SetObjectRects(inplace, &rc, &rc); IOleInPlaceObject_Release(inplace); hr = IOleObject_QueryInterface(container->ole_obj, &IID_IWebBrowser2, (void **)&container->web_browser); if (SUCCEEDED(hr)) return TRUE; error: ReleaseWebBrowser(info); return FALSE; }
// returns true on success, false on failure bool ImageDataObject::InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap) { BITMAP bminfo; // Get the image data object // ImageDataObject *pods = new ImageDataObject; GetObject(hBitmap, sizeof(bminfo), &bminfo); pods->SetBitmap(hBitmap); // Get the RichEdit container site // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object // LPLOCKBYTES lpLockBytes = nullptr; SCODE sc = ::CreateILockBytesOnHGlobal(nullptr, TRUE, &lpLockBytes); if (sc != S_OK) { pOleClientSite->Release(); return false; } IStorage *pStorage; sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); if (sc != S_OK) { lpLockBytes = nullptr; pOleClientSite->Release(); return false; } // The final ole object which will be inserted in the richedit control // IOleObject *pOleObject; pOleObject = pods->GetOleObject(pOleClientSite, pStorage); if (pOleObject == nullptr) { pStorage->Release(); pOleClientSite->Release(); return false; } // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit // REOBJECT reobject; memset(&reobject, 0, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = pOleObject->GetUserClassID(&clsid); if (sc != S_OK) { pOleObject->Release(); pStorage->Release(); pOleClientSite->Release(); return false; } reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; reobject.dwFlags = bminfo.bmHeight <= 12 ? 0 : REO_BELOWBASELINE; // Insert the bitmap at the current location in the richedit control // sc = pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces // pOleObject->Release(); pOleClientSite->Release(); lpLockBytes->Release(); pStorage->Release(); return sc == S_OK; }
void CImageDataObject::InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap) { SCODE sc; // Get the image data object // CImageDataObject *pods = new CImageDataObject; LPDATAOBJECT lpDataObject; pods->QueryInterface(IID_IDataObject, (void **)&lpDataObject); pods->SetBitmap(hBitmap); // Get the RichEdit container site // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object // IStorage *pStorage; LPLOCKBYTES lpLockBytes = NULL; sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if (sc != S_OK) AfxThrowOleException(sc); ASSERT(lpLockBytes != NULL); sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage); if (sc != S_OK) { VERIFY(lpLockBytes->Release() == 0); lpLockBytes = NULL; AfxThrowOleException(sc); } ASSERT(pStorage != NULL); // The final ole object which will be inserted in the richedit control // IOleObject *pOleObject; pOleObject = pods->GetOleObject(pOleClientSite, pStorage); if(!pOleObject) AfxThrowOleException(sc); // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit // REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = pOleObject->GetUserClassID(&clsid); if (sc != S_OK) AfxThrowOleException(sc); reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; // Insert the bitmap at the current location in the richedit control // pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces // pOleObject->Release(); pOleClientSite->Release(); pStorage->Release(); lpDataObject->Release(); }
// returns true on success, false on failure //bool InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap, HGLOBAL hGlobal) bool InsertBitmap(IRichEditOle* pRichEditOle, HENHMETAFILE hEmf) { SCODE sc; // Get the image data object // static const FORMATETC lc_format[] = { { CF_ENHMETAFILE, 0, DVASPECT_CONTENT, -1, TYMED_ENHMF }//, // { CF_BITMAP, 0, DVASPECT_CONTENT, -1, TYMED_GDI }, // { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL } }; STGMEDIUM lc_stgmed[] = { { TYMED_ENHMF, { (HBITMAP)hEmf }, 0 }//, // { TYMED_GDI, { hBitmap }, 0 }, // { TYMED_HGLOBAL, { (HBITMAP)hGlobal }, 0 } }; IDataObject *pods; CreateDataObject(lc_format, lc_stgmed, 1, &pods); // Get the RichEdit container site // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object // LPLOCKBYTES lpLockBytes = NULL; sc = CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if (sc != S_OK) { pOleClientSite->Release(); return false; } IStorage *pStorage; sc = StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage); if (sc != S_OK) { lpLockBytes->Release(); pOleClientSite->Release(); return false; } // The final ole object which will be inserted in the richedit control // IOleObject *pOleObject; sc = OleCreateStaticFromData(pods, IID_IOleObject, OLERENDER_FORMAT, (LPFORMATETC)lc_format, pOleClientSite, pStorage, (void **)&pOleObject); if (sc != S_OK) { pStorage->Release(); lpLockBytes->Release(); pOleClientSite->Release(); return false; } // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit // REOBJECT reobject = { 0 }; reobject.cbStruct = sizeof(REOBJECT); reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; reobject.dwFlags = REO_BELOWBASELINE; sc = pOleObject->GetUserClassID(&reobject.clsid); if (sc != S_OK) { pOleObject->Release(); pStorage->Release(); lpLockBytes->Release(); pOleClientSite->Release(); return false; } // Insert the bitmap at the current location in the richedit control // sc = pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces // pOleObject->Release(); pStorage->Release(); lpLockBytes->Release(); pOleClientSite->Release(); pods->Release(); return sc == S_OK; }
//--------------------------------------------------------------------------- // wxActiveXContainer::CreateActiveX // // Actually creates the ActiveX container through the FrameSite // and sets up ActiveX events // // TODO: Document this more //--------------------------------------------------------------------------- void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk) { HRESULT hret; hret = m_ActiveX.QueryInterface(iid, pUnk); CHECK_HR(hret); // FrameSite m_frameSite = new FrameSite(m_realparent, this); // oleClientSite hret = m_clientSite.QueryInterface( IID_IOleClientSite, (IDispatch *) m_frameSite); CHECK_HR(hret); // adviseSink wxAutoIAdviseSink adviseSink(IID_IAdviseSink, (IDispatch *) m_frameSite); wxASSERT(adviseSink.Ok()); // Get Dispatch interface hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX); CHECK_HR(hret); // // SETUP TYPEINFO AND ACTIVEX EVENTS // // get type info via class info wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX); wxASSERT(classInfo.Ok()); // type info wxAutoITypeInfo typeInfo; hret = classInfo->GetClassInfo(typeInfo.GetRef()); CHECK_HR(hret); wxASSERT(typeInfo.Ok()); // TYPEATTR TYPEATTR *ta = NULL; hret = typeInfo->GetTypeAttr(&ta); CHECK_HR(hret); // this should be a TKIND_COCLASS wxASSERT(ta->typekind == TKIND_COCLASS); // iterate contained interfaces for (int i = 0; i < ta->cImplTypes; i++) { HREFTYPE rt = 0; // get dispatch type info handle hret = typeInfo->GetRefTypeOfImplType(i, &rt); if (! SUCCEEDED(hret)) continue; // get dispatch type info interface wxAutoITypeInfo ti; hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef()); if (! ti.Ok()) continue; CHECK_HR(hret); // check if default event sink bool defEventSink = false; int impTypeFlags = 0; typeInfo->GetImplTypeFlags(i, &impTypeFlags); if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT) { if (impTypeFlags & IMPLTYPEFLAG_FSOURCE) { // WXOLE_TRACEOUT("Default Event Sink"); defEventSink = true; if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE) { // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable"); defEventSink = false; wxFAIL_MSG(wxT("Default event sink is in vtable!")); } } } // wxAutoOleInterface<> assumes a ref has already been added // TYPEATTR TYPEATTR *ta = NULL; hret = ti->GetTypeAttr(&ta); CHECK_HR(hret); if (ta->typekind == TKIND_DISPATCH) { // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str()); if (defEventSink) { wxAutoIConnectionPoint cp; DWORD adviseCookie = 0; wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX); wxASSERT( cpContainer.Ok()); HRESULT hret = cpContainer->FindConnectionPoint(ta->guid, cp.GetRef()); CHECK_HR(hret); IDispatch* disp; m_frameSite->QueryInterface(IID_IDispatch, (void**)&disp); hret = cp->Advise(new wxActiveXEvents(this, ta->guid), &adviseCookie); CHECK_HR(hret); } } ti->ReleaseTypeAttr(ta); } // free typeInfo->ReleaseTypeAttr(ta); // // END // // Get IOleObject interface hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX); CHECK_HR(hret); // get IViewObject Interface hret = m_viewObject.QueryInterface(IID_IViewObject, m_ActiveX); CHECK_HR(hret); // document advise m_docAdviseCookie = 0; hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie); CHECK_HR(hret); // TODO:Needed? // hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink); m_oleObject->SetHostNames(L"wxActiveXContainer", NULL); OleSetContainedObject(m_oleObject, TRUE); OleRun(m_oleObject); // Get IOleInPlaceObject interface hret = m_oleInPlaceObject.QueryInterface( IID_IOleInPlaceObject, m_ActiveX); CHECK_HR(hret); // status DWORD dwMiscStatus; m_oleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus); CHECK_HR(hret); // set client site first ? if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) m_oleObject->SetClientSite(m_clientSite); // stream init wxAutoIPersistStreamInit pPersistStreamInit(IID_IPersistStreamInit, m_oleObject); if (pPersistStreamInit.Ok()) { hret = pPersistStreamInit->InitNew(); CHECK_HR(hret); } if (! (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) m_oleObject->SetClientSite(m_clientSite); m_oleObjectHWND = 0; if (m_oleInPlaceObject.Ok()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); if (SUCCEEDED(hret)) ::SetActiveWindow(m_oleObjectHWND); } if (! (dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) { RECT posRect; wxCopyRectToRECT(m_realparent->GetClientSize(), posRect); if (posRect.right > 0 && posRect.bottom > 0 && m_oleInPlaceObject.Ok()) { m_oleInPlaceObject->SetObjectRects(&posRect, &posRect); } hret = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect); CHECK_HR(hret); hret = m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0, (HWND)m_realparent->GetHWND(), &posRect); CHECK_HR(hret); } if (! m_oleObjectHWND && m_oleInPlaceObject.Ok()) { hret = m_oleInPlaceObject->GetWindow(&m_oleObjectHWND); CHECK_HR(hret); } if (m_oleObjectHWND) { ::SetActiveWindow(m_oleObjectHWND); ::ShowWindow(m_oleObjectHWND, SW_SHOW); this->AssociateHandle(m_oleObjectHWND); this->Reparent(m_realparent); wxWindow* pWnd = m_realparent; int id = m_realparent->GetId(); pWnd->Connect(id, wxEVT_SIZE, wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this); // this->Connect(GetId(), wxEVT_PAINT, // wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this); pWnd->Connect(id, wxEVT_SET_FOCUS, wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this); pWnd->Connect(id, wxEVT_KILL_FOCUS, wxFocusEventHandler(wxActiveXContainer::OnKillFocus), 0, this); } }
long EmbedBrowserObject(HWND hwnd) { LPCLASSFACTORY pClassFactory; IOleObject *browserObject; IWebBrowser2 *webBrowser2; RECT rect; char *ptr; _IOleClientSiteEx *_iOleClientSiteEx; // Our IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame functions need to get our window handle. We // could store that in some global. But then, that would mean that our functions would work with only that // one window. If we want to create multiple windows, each hosting its own browser object (to display its // own web page), then we need to create unique IOleClientSite, IOleInPlaceSite, and IOleInPlaceFrame // structs for each window. And we'll put an extra field at the end of those structs to store our extra // data such as a window handle. So, our functions won't have to touch global data, and can therefore be // re-entrant and work with multiple objects/windows. // // Remember that a pointer to our IOleClientSite we create here will be passed as the first arg to every // one of our IOleClientSite functions. Ditto with the IOleInPlaceFrame object we create here, and the // IOleInPlaceFrame functions. So, our functions are able to retrieve the window handle we'll store here, // and then, they'll work with all such windows containing a browser control. // // Furthermore, since the browser will be calling our IOleClientSite's QueryInterface to get a pointer to // our IOleInPlaceSite and IDocHostUIHandler objects, that means that our IOleClientSite QueryInterface // must have an easy way to grab those pointers. Probably the easiest thing to do is just embed our // IOleInPlaceSite and IDocHostUIHandler objects inside of an extended IOleClientSite which we'll call // a _IOleClientSiteEx. As long as they come after the pointer to the IOleClientSite VTable, then we're // ok. // // Of course, we need to GlobalAlloc the above structs now. We'll just get all 4 with a single call to // GlobalAlloc, especially since 3 of them are all contained inside of our _IOleClientSiteEx anyway. // // So, we're not actually allocating separate IOleClientSite, IOleInPlaceSite, IOleInPlaceFrame and // IDocHostUIHandler structs. // // One final thing. We're going to allocate extra room to store the pointer to the browser object. if (!(ptr = (char *)GlobalAlloc(GMEM_FIXED, sizeof(_IOleClientSiteEx) + sizeof(IOleObject *)))) return(-1); // Initialize our IOleClientSite object with a pointer to our IOleClientSite VTable. _iOleClientSiteEx = (_IOleClientSiteEx *)(ptr + sizeof(IOleObject *)); _iOleClientSiteEx->client.lpVtbl = &gIOleClientSiteTable; // Initialize our IOleInPlaceSite object with a pointer to our IOleInPlaceSite VTable. _iOleClientSiteEx->inplace.inplace.lpVtbl = &gIOleInPlaceSiteTable; // Initialize our IOleInPlaceFrame object with a pointer to our IOleInPlaceFrame VTable. _iOleClientSiteEx->inplace.frame.frame.lpVtbl = &gIOleInPlaceFrameTable; // Save our HWND (in the IOleInPlaceFrame object) so our IOleInPlaceFrame functions can retrieve it. _iOleClientSiteEx->inplace.frame.window = hwnd; // Initialize our IDocHostUIHandler object with a pointer to our IDocHostUIHandler VTable. _iOleClientSiteEx->ui.ui.lpVtbl = &gIDocHostUIHandlerTable; // Get a pointer to the browser object and lock it down (so it doesn't "disappear" while we're using // it in this program). We do this by calling the OS function CoGetClassObject(). // // NOTE: We need this pointer to interact with and control the browser. With normal WIN32 controls such as a // Static, Edit, Combobox, etc, you obtain an HWND and send messages to it with SendMessage(). Not so with // the browser object. You need to get a pointer to its "base structure" (as returned by CoGetClassObject()). This // structure contains an array of pointers to functions you can call within the browser object. Actually, the // base structure contains a 'lpVtbl' field that is a pointer to that array. We'll call the array a 'VTable'. // // For example, the browser object happens to have a SetHostNames() function we want to call. So, after we // retrieve the pointer to the browser object (in a local we'll name 'browserObject'), then we can call that // function, and pass it args, as so: // // browserObject->lpVtbl->SetHostNames(browserObject, SomeString, SomeString); // // There's our pointer to the browser object in 'browserObject'. And there's the pointer to the browser object's // VTable in 'browserObject->lpVtbl'. And the pointer to the SetHostNames function happens to be stored in an // field named 'SetHostNames' within the VTable. So we are actually indirectly calling SetHostNames by using // a pointer to it. That's how you use a VTable. // // NOTE: We pass our _IOleClientSiteEx struct and lie -- saying that it's a IOleClientSite. It's ok. A // _IOleClientSiteEx struct starts with an embedded IOleClientSite. So the browser won't care, and we want // this extended struct passed to our IOleClientSite functions. // Get a pointer to the browser object's IClassFactory object via CoGetClassObject() pClassFactory = 0; if (!CoGetClassObject(&CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, NULL, &IID_IClassFactory, (void **)&pClassFactory) && pClassFactory) { // Call the IClassFactory's CreateInstance() to create a browser object if (!pClassFactory->lpVtbl->CreateInstance(pClassFactory, 0, &IID_IOleObject, &browserObject)) { // Free the IClassFactory. We need it only to create a browser object instance pClassFactory->lpVtbl->Release(pClassFactory); // Ok, we now have the pointer to the browser object in 'browserObject'. Let's save this in the // memory block we allocated above, and then save the pointer to that whole thing in our window's // USERDATA field. That way, if we need multiple windows each hosting its own browser object, we can // call EmbedBrowserObject() for each one, and easily associate the appropriate browser object with // its matching window and its own objects containing per-window data. *((IOleObject **)ptr) = browserObject; SetWindowLong(hwnd, GWL_USERDATA, (LONG)ptr); // Give the browser a pointer to my IOleClientSite object if (!browserObject->lpVtbl->SetClientSite(browserObject, (IOleClientSite *)_iOleClientSiteEx)) { // We can now call the browser object's SetHostNames function. SetHostNames lets the browser object know our // application's name and the name of the document in which we're embedding the browser. (Since we have no // document name, we'll pass a 0 for the latter). When the browser object is opened for editing, it displays // these names in its titlebar. // // We are passing 3 args to SetHostNames. You'll note that the first arg to SetHostNames is the base // address of our browser control. This is something that you always have to remember when working in C // (as opposed to C++). When calling a VTable function, the first arg to that function must always be the // structure which contains the VTable. (In this case, that's the browser control itself). Why? That's // because that function is always assumed to be written in C++. And the first argument to any C++ function // must be its 'this' pointer (ie, the base address of its class, which in this case is our browser object // pointer). In C++, you don't have to pass this first arg, because the C++ compiler is smart enough to // produce an executable that always adds this first arg. In fact, the C++ compiler is smart enough to // know to fetch the function pointer from the VTable, so you don't even need to reference that. In other // words, the C++ equivalent code would be: // // browserObject->SetHostNames(L"My Host Name", 0); // // So, when you're trying to convert C++ code to C, always remember to add this first arg whenever you're // dealing with a VTable (ie, the field is usually named 'lpVtbl') in the standard objects, and also add // the reference to the VTable itself. // // Oh yeah, the L is because we need UNICODE strings. And BTW, the host and document names can be anything // you want. browserObject->lpVtbl->SetHostNames(browserObject, L"My Host Name", 0); GetClientRect(hwnd, &rect); // Let browser object know that it is embedded in an OLE container. if (!OleSetContainedObject((struct IUnknown *)browserObject, TRUE) && // Set the display area of our browser control the same as our window's size // and actually put the browser object into our window. !browserObject->lpVtbl->DoVerb(browserObject, OLEIVERB_SHOW, NULL, (IOleClientSite *)_iOleClientSiteEx, -1, hwnd, &rect) && // Ok, now things may seem to get even trickier, One of those function pointers in the browser's VTable is // to the QueryInterface() function. What does this function do? It lets us grab the base address of any // other object that may be embedded within the browser object. And this other object has its own VTable // containing pointers to more functions we can call for that object. // // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser // object, so we can call some of the functions in the former's table. For example, one IWebBrowser2 function // we intend to call below will be Navigate2(). So we call the browser object's QueryInterface to get our // pointer to the IWebBrowser2 object. !browserObject->lpVtbl->QueryInterface(browserObject, &IID_IWebBrowser2, (void**)&webBrowser2)) { // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is // webBrowser2->lpVtbl. // Let's call several functions in the IWebBrowser2 object to position the browser display area // in our window. The functions we call are put_Left(), put_Top(), put_Width(), and put_Height(). // Note that we reference the IWebBrowser2 object's VTable to get pointers to those functions. And // also note that the first arg we pass to each is the pointer to the IWebBrowser2 object. webBrowser2->lpVtbl->put_Left(webBrowser2, 0); webBrowser2->lpVtbl->put_Top(webBrowser2, 0); webBrowser2->lpVtbl->put_Width(webBrowser2, rect.right); webBrowser2->lpVtbl->put_Height(webBrowser2, rect.bottom); // We no longer need the IWebBrowser2 object (ie, we don't plan to call any more functions in it // right now, so we can release our hold on it). Note that we'll still maintain our hold on the // browser object until we're done with that object. webBrowser2->lpVtbl->Release(webBrowser2); // Success return(0); } } // Something went wrong setting up the browser! UnEmbedBrowserObject(hwnd); return(-4); } pClassFactory->lpVtbl->Release(pClassFactory); GlobalFree(ptr); // Can't create an instance of the browser! return(-3); } GlobalFree(ptr); // Can't get the web browser's IClassFactory! return(-2); }
void CExtRichEdit::InsertFace(CString strPicPath) { LPLOCKBYTES lpLockBytes = NULL; SCODE sc; HRESULT hr; //print to RichEdit' s IClientSite LPOLECLIENTSITE m_lpClientSite; //A smart point to IAnimator IGifAnimatorPtr m_lpAnimator; //ptr 2 storage LPSTORAGE m_lpStorage; //the object 2 b insert 2 LPOLEOBJECT m_lpObject; //Create lockbytes sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if (sc != S_OK) AfxThrowOleException(sc); ASSERT(lpLockBytes != NULL); //use lockbytes to create storage sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &m_lpStorage); if (sc != S_OK) { VERIFY(lpLockBytes->Release() == 0); lpLockBytes = NULL; AfxThrowOleException(sc); } ASSERT(m_lpStorage != NULL); //get the ClientSite of the very RichEditCtrl GetIRichEditOle()->GetClientSite(&m_lpClientSite); ASSERT(m_lpClientSite != NULL); try { //Initlize COM interface hr = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if( FAILED(hr) ) _com_issue_error(hr); //Get GifAnimator object //here, I used a smart point, so I do not need to free it hr = m_lpAnimator.CreateInstance(CLSID_GifAnimator); if( FAILED(hr) ) _com_issue_error(hr); //COM operation need BSTR, so get a BSTR BSTR path = strPicPath.AllocSysString(); //Load the gif hr = m_lpAnimator->LoadFromFile(path); if( FAILED(hr) ) _com_issue_error(hr); // TRACE0( m_lpAnimator->GetFilePath() ); //get the IOleObject hr = m_lpAnimator.QueryInterface(IID_IOleObject, (void**)&m_lpObject); if( FAILED(hr) ) _com_issue_error(hr); //Set it 2 b inserted OleSetContainedObject(m_lpObject, TRUE); //2 insert in 2 richedit, you need a struct of REOBJECT REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = m_lpObject->GetUserClassID(&clsid); if (sc != S_OK) AfxThrowOleException(sc); //set clsid reobject.clsid = clsid; //can be selected reobject.cp = REO_CP_SELECTION; //content, but not static reobject.dvaspect = DVASPECT_CONTENT; //goes in the same line of text line reobject.dwFlags = REO_BELOWBASELINE; //REO_RESIZABLE | reobject.dwUser = 0; //the very object reobject.poleobj = m_lpObject; //client site contain the object reobject.polesite = m_lpClientSite; //the storage reobject.pstg = m_lpStorage; SIZEL sizel; sizel.cx = sizel.cy = 0; reobject.sizel = sizel; HWND hWndRT = this->m_hWnd; //Sel all text // ::SendMessage(hWndRT, EM_SETSEL, 0, -1); // DWORD dwStart, dwEnd; // ::SendMessage(hWndRT, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); // ::SendMessage(hWndRT, EM_SETSEL, dwEnd+1, dwEnd+1); //Insert after the line of text GetIRichEditOle()->InsertObject(&reobject); ::SendMessage(hWndRT, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); VARIANT_BOOL ret; //do frame changing ret = m_lpAnimator->TriggerFrameChange(); //show it m_lpObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_lpClientSite, 0, m_hWnd, NULL); m_lpObject->DoVerb(OLEIVERB_SHOW, NULL, m_lpClientSite, 0, m_hWnd, NULL); //redraw the window to show animation RedrawWindow(); if (m_lpClientSite) { m_lpClientSite->Release(); m_lpClientSite = NULL; } if (m_lpObject) { m_lpObject->Release(); m_lpObject = NULL; } if (m_lpStorage) { m_lpStorage->Release(); m_lpStorage = NULL; } SysFreeString(path); } catch( _com_error e ) { AfxMessageBox(e.ErrorMessage()); ::CoUninitialize(); } }
//创建函数 OLECONTAINER_FUNCTION(BOOL)::Create(GUID clsid, DWORD dwExStyle, DWORD dwStyle, HWND hWndParent, HINSTANCE hInstance) { m_bTransparent=dwExStyle&WS_EX_LAYERED; //变量定义 WNDCLASSEX WndClassEx; ZeroMemory(&WndClassEx,sizeof(WndClassEx)); //设置变量 WndClassEx.cbSize=sizeof(WNDCLASSEX); WndClassEx.hInstance=hInstance; WndClassEx.lpszClassName=WND_FLASH_CLASS; WndClassEx.lpfnWndProc=COleContainerWnd<TControl>::WndProcStatic; //注册窗口 RegisterClassEx(&WndClassEx); CRect rcRect; if (dwStyle&WS_CHILD) ::GetClientRect(hWndParent, &rcRect); else ::GetWindowRect(hWndParent, &rcRect); m_hWnd=CreateWindowEx(dwExStyle,WND_FLASH_CLASS,NULL,dwStyle,rcRect.left,rcRect.top,rcRect.Width(),rcRect.Height(),hWndParent,NULL,hInstance,(VOID *)this); ::SetWindowPos(m_hWnd,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); HRESULT hResult; hResult=OleCreate(clsid, IID_IOleObject, OLERENDER_DRAW,0,(IOleClientSite *)this,(IStorage *)this,(VOID **)&m_pIOleObject); if (FAILED(hResult)) { static bool bShow=true; if (hResult==REGDB_E_CLASSNOTREG && bShow) { bShow=false; //提示消息 CInformation Information; if (IDOK==Information.ShowMessageBox(TEXT("系统提示"),TEXT("您的FLASH播放器版本过低,为了正常使用功能,请您下载最新的Flash插件。点击确定最新的Flash插件 "),MB_OKCANCEL,30)) { //打开页面 ShellExecute(NULL,TEXT("OPEN"),TEXT("http://www.adobe.com/go/getflashplayer"),NULL,NULL,SW_NORMAL); } OnErrorClassNotReg(); } return FALSE; } if (FAILED(OleSetContainedObject(m_pIOleObject, TRUE))) return FALSE; if (FAILED(m_pIOleObject->QueryInterface(__uuidof(TControl), (VOID **)&m_pIControl))) return FALSE; if (FAILED(m_pIOleObject->QueryInterface(IID_IViewObjectEx, (VOID **)&m_pIViewObjectEx))) { m_pIViewObjectEx=NULL; if (FAILED(m_pIOleObject->QueryInterface(IID_IViewObject, (VOID **)&m_pIViewObject))) return FALSE; } if (m_bTransparent) { if (FAILED(m_pIOleObject->QueryInterface(IID_IOleInPlaceObjectWindowless, (VOID **)&m_pIOleInPlaceObjectWindowless))) { if (FAILED(m_pIOleObject->QueryInterface(IID_IOleInPlaceObject, (VOID **)&m_pIOleInPlaceObject))) return FALSE; m_bTransparent=FALSE; } } else { if (FAILED(m_pIOleObject->QueryInterface(IID_IOleInPlaceObject, (VOID **)&m_pIOleInPlaceObject))) return FALSE; } if (!OnBeforeShowingContent()) return FALSE; if (FAILED(m_pIOleObject->DoVerb(OLEIVERB_SHOW, NULL, (IOleClientSite *)this, 0, NULL, NULL))) return FALSE; if (!OnAfterShowingContent()) return FALSE; INT nScreenW=GetSystemMetrics(SM_CXSCREEN); INT nScreenH=GetSystemMetrics(SM_CYSCREEN); ::SetWindowPos(m_hWnd,HWND_TOPMOST,(nScreenW-rcRect.Width())/2, (nScreenH-rcRect.Height())/2, 0, 0, SWP_NOSIZE); return TRUE; }
//创建函数 BOOL CFlashActiveX::CreateControl(DWORD dwStyle, CWnd * pParentWnd, CRect rcCreate, HINSTANCE hInstance, IUnknownEx * pIUnknownEx) { //状态效验 ASSERT(m_hWnd==NULL); if (m_hWnd!=NULL) return FALSE; //变量定义 WNDCLASSEX WndClassEx; ZeroMemory(&WndClassEx,sizeof(WndClassEx)); //设置变量 WndClassEx.cbSize=sizeof(WNDCLASSEX); WndClassEx.hInstance=hInstance; WndClassEx.lpszClassName=WND_FLASH_CLASS; WndClassEx.lpfnWndProc=::DefWindowProc; //注册窗口 RegisterClassEx(&WndClassEx); //查询接口 m_pIFlashControlSink=QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx,IFlashControlSink); //创建窗口 m_hWnd=CreateWindowEx(WS_EX_LAYERED,WND_FLASH_CLASS,NULL,dwStyle,rcCreate.left,rcCreate.top,rcCreate.Width(),rcCreate.Height(), pParentWnd->m_hWnd,NULL,hInstance,(VOID *)this); //创建控件 GUID ClsID=ShockwaveFlashObjects::CLSID_ShockwaveFlash; HRESULT hResult=OleCreate(ClsID,IID_IOleObject,OLERENDER_DRAW,0,(IOleClientSite *)this,(IStorage *)this,(VOID **)&m_pIOleObject); //结果判断 if (FAILED(hResult)) { static bool bShow=true; if ((hResult==REGDB_E_CLASSNOTREG)&&(bShow==false)) { bShow=false; //提示消息 CInformation Information; if (IDOK==Information.ShowMessageBox(TEXT("系统提示"),TEXT("您的FLASH播放器版本过低,为了正常使用功能,请您下载最新的Flash插件。点击确定最新的Flash插件 "),MB_OKCANCEL,30)) { //打开页面 ShellExecute(NULL,TEXT("OPEN"),TEXT("http://www.adobe.com/go/getflashplayer"),NULL,NULL,SW_NORMAL); } } return FALSE; } //容器模式 OleSetContainedObject(m_pIOleObject,TRUE); //查询接口 if (FAILED(m_pIOleObject->QueryInterface(__uuidof(IFalshControl),(VOID * *)&m_pIFalshControl))) { ASSERT(FALSE); return FALSE; } //查询接口 if (FAILED(m_pIOleObject->QueryInterface(IID_IViewObjectEx,(VOID * *)&m_pIViewObjectEx))) { if (FAILED(m_pIOleObject->QueryInterface(IID_IViewObject,(VOID **)&m_pIViewObject))) { ASSERT(FALSE); return FALSE; } } //设置组件 m_pIFalshControl->PutWMode(TEXT("transparent")); //显示控件 if (FAILED(m_pIOleObject->DoVerb(OLEIVERB_UIACTIVATE,NULL,(IOleClientSite *)this,0L,NULL,NULL))) { ASSERT(FALSE); return FALSE; } return TRUE; }
OLECONTAINER(BOOL)::Create(GUID clsid, DWORD dwExStyle, DWORD dwStyle, HWND hWndParent, HINSTANCE hInst) { m_hWndParent = hWndParent; m_hInst = hInst; m_CLSID = clsid; m_bTransparent = (dwExStyle & WS_EX_LAYERED) ? TRUE : FALSE; m_bChild = (dwStyle & WS_CHILD) ? TRUE : FALSE; WNDCLASSEX wcs = {0}; wcs.cbSize = sizeof(WNDCLASSEX); wcs.lpfnWndProc = COleContainerWnd<TObj>::WndProcStatic; wcs.hInstance = hInst; wcs.lpszClassName = W2X_FLASH_WND_CLASS; RegisterClassEx(&wcs); RECT rt = {0}; if (NULL != hWndParent) { if (m_bChild) { ::GetClientRect(hWndParent, &rt); } else { ::GetWindowRect(hWndParent, &rt); } } else { rt.right = rt.left + 32; rt.bottom = rt.top + 32; } m_hWnd = CreateWindowEx(dwExStyle, W2X_FLASH_WND_CLASS, m_wnd_name_ptr, dwStyle, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, hWndParent, NULL, hInst, (void *)this); HRESULT hr; hr = OleCreate(m_CLSID, IID_IOleObject, OLERENDER_DRAW, 0, (IOleClientSite *)this, (IStorage *)this, (void **)&m_lpO); if (FAILED(hr)) { if (hr == REGDB_E_CLASSNOTREG) { OnErrorClassNotReg(); } return FALSE; } hr = OleSetContainedObject(m_lpO, TRUE); if (FAILED(hr)) return FALSE; hr = m_lpO->QueryInterface(__uuidof(TObj), (void **)&m_lpControl); if (FAILED(hr)) return FALSE; hr = m_lpO->QueryInterface(IID_IViewObjectEx, (void **)&m_lpViewObjectEx); if (FAILED(hr)) { m_lpViewObjectEx = NULL; hr = m_lpO->QueryInterface(IID_IViewObject, (void **)&m_lpViewObject); if (FAILED(hr)) return FALSE; } if (m_bTransparent) { hr = m_lpO->QueryInterface(IID_IOleInPlaceObjectWindowless, (void **)&m_lpInPlaceObjWindowless); if (FAILED(hr)) { hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void **)&m_lpInPlaceObj); if (FAILED(hr)) return FALSE; m_bTransparent = FALSE; } } else { hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void **)&m_lpInPlaceObj); if (FAILED(hr)) return FALSE; } if (!OnBeforeShowingContent()) return FALSE; hr = m_lpO->DoVerb(OLEIVERB_SHOW, NULL, (IOleClientSite *)this, 0, NULL, NULL); if (FAILED(hr)) return FALSE; if (!OnAfterShowingContent()) return FALSE; return TRUE; }
void UIIMEdit::InsertImage(BSTR bstrFileName,SIZE size,BOOL isGif) { LPSTORAGE lpStorage = NULL; LPOLEOBJECT lpObject = NULL; LPLOCKBYTES lpLockBytes = NULL; LPOLECLIENTSITE lpClientSite = NULL; GifSmiley::IGifSmileyCtrl* lpAnimator = nullptr; HRESULT hr = ::CoCreateInstance(GifSmiley::CLSID_CGifSmileyCtrl, NULL, CLSCTX_INPROC, GifSmiley::IID_IGifSmileyCtrl, (LPVOID*)&lpAnimator); if (NULL == lpAnimator || FAILED(hr)) { LOG__(ERR, _T("InsertImage CoCreateInstance failed")); goto End; } COLORREF backColor = (COLORREF)(::GetSysColor(COLOR_WINDOW)); HWND hwnd = (HWND)((long)m_pManager->GetPaintWindow()); IRichEditOle *pRichEditOle = m_pRichEditOle; if (NULL == pRichEditOle) goto End; BSTR path = NULL; //Create lockbytes hr = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if (FAILED(hr)) { LOG__(ERR, _T("InsertImage CreateILockBytesOnHGlobal failed")); goto End; } //use lockbytes to create storage SCODE sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &lpStorage); if (sc != S_OK) { LOG__(ERR, _T("InsertImage StgCreateDocfileOnILockBytes failed")); goto End; } // retrieve OLE interface for richedit and Get site pRichEditOle->GetClientSite(&lpClientSite); try { //COM operation need BSTR, so get a BSTR path = bstrFileName; //Load the image if (isGif) lpAnimator->LoadFromFile(path); else { UInt32 height = (size.cy < GetHeight()) ? size.cy : GetHeight(); UInt32 width = (size.cx < GetWidth() / 2) ? size.cx : GetWidth() / 2; lpAnimator->LoadFromFileSized(path, width, height); } //Set back color OLE_COLOR oleBackColor = (OLE_COLOR)backColor; lpAnimator->put_BackColor(oleBackColor); //get the IOleObject hr = lpAnimator->QueryInterface(IID_IOleObject, (void**)&lpObject); if (FAILED(hr)) { LOG__(ERR, _T("InsertImage lpAnimator QueryInterface failed")); goto End; } //Set it to be inserted OleSetContainedObject(lpObject, TRUE); //to insert into richedit, you need a struct of REOBJECT REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; hr = lpObject->GetUserClassID(&clsid); //set clsid reobject.clsid = clsid; //can be selected reobject.cp = REO_CP_SELECTION; //content, but not static reobject.dvaspect = DVASPECT_CONTENT; //goes in the same line of text line reobject.dwFlags = REO_BELOWBASELINE; //reobject.dwUser = (DWORD)myObject; //the very object reobject.poleobj = lpObject; //client site contain the object reobject.polesite = lpClientSite; //the storage reobject.pstg = lpStorage; SIZEL sizel = { 0 }; reobject.sizel = sizel; LPOLECLIENTSITE lpObjectClientSite = NULL; hr = lpObject->GetClientSite(&lpObjectClientSite); if (FAILED(hr) || lpObjectClientSite == NULL) lpObject->SetClientSite(lpClientSite); pRichEditOle->InsertObject(&reobject); //redraw the window to show animation ::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); } catch (...) { LOG__(ERR, _T("InsertImage unknown exeption")); } End: if (lpClientSite) { lpClientSite->Release(); lpClientSite = nullptr; } if (lpObject) { lpObject->Release(); lpObject = nullptr; } if (lpLockBytes) { lpLockBytes->Release(); lpLockBytes = nullptr; } if (lpStorage) { lpStorage->Release(); lpStorage = nullptr; } if (lpAnimator) { lpAnimator->Release(); lpAnimator = nullptr; } }
OLECONTAINER(BOOL)::Create(GUID clsid, DWORD dwExStyle, DWORD dwStyle, HWND hWndParent, HINSTANCE hInst) { m_hWndParent = hWndParent; m_hInst = hInst; m_CLSID = clsid; m_bTransparent = dwExStyle & WS_EX_LAYERED; m_bChild = dwStyle & WS_CHILD; WNDCLASSEX wcs = {0}; wcs.cbSize = sizeof(WNDCLASSEX); wcs.lpfnWndProc = COleContainerWnd<TObj>::WndProcStatic; wcs.hInstance = hInst; wcs.lpszClassName = "MyOleControl"; RegisterClassEx(&wcs); RECT r; if (m_bChild) ::GetClientRect(hWndParent, &r); else ::GetWindowRect(hWndParent, &r); m_hWnd = CreateWindowEx(dwExStyle, "MyOleControl", "MyOleControlWindow", dwStyle, r.left, r.top, r.right-r.left, r.bottom-r.top, hWndParent, NULL, hInst, (void *)this); ::SetWindowPos(GetHWND(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); HRESULT hr; hr = OleCreate(m_CLSID, IID_IOleObject, OLERENDER_DRAW, 0, (IOleClientSite *)this, (IStorage *)this, (void **)&m_lpO); if (FAILED(hr)) { if (hr == REGDB_E_CLASSNOTREG) { OnErrorClassNotReg(); } return FALSE; } hr = OleSetContainedObject(m_lpO, TRUE); if (FAILED(hr)) return FALSE; hr = m_lpO->QueryInterface(__uuidof(TObj), (void **)&m_lpControl); if (FAILED(hr)) return FALSE; hr = m_lpO->QueryInterface(IID_IViewObjectEx, (void **)&m_lpViewObjectEx); if (FAILED(hr)) { m_lpViewObjectEx = NULL; hr = m_lpO->QueryInterface(IID_IViewObject, (void **)&m_lpViewObject); if (FAILED(hr)) return FALSE; } if (m_bTransparent) { hr = m_lpO->QueryInterface(IID_IOleInPlaceObjectWindowless, (void **)&m_lpInPlaceObjWindowless); if (FAILED(hr)) { hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void **)&m_lpInPlaceObj); if (FAILED(hr)) return FALSE; m_bTransparent = FALSE; } } else { hr = m_lpO->QueryInterface(IID_IOleInPlaceObject, (void **)&m_lpInPlaceObj); if (FAILED(hr)) return FALSE; } if (!OnBeforeShowingContent()) return FALSE; hr = m_lpO->DoVerb(OLEIVERB_UIACTIVATE, NULL, (IOleClientSite *)this, 0, NULL, NULL); //hr = m_lpO->DoVerb(OLEIVERB_UIACTIVATE, NULL, (IOleClientSite *)this, 0, NULL, NULL); if (FAILED(hr)) return FALSE; if (!OnAfterShowingContent()) return FALSE; return TRUE; }
// Static member functions void CImageDataObject::InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap) { LPLOCKBYTES lpLockBytes = NULL; SCODE sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); if(sc != S_OK) { DeleteObject(hBitmap); pRichEditOle->Release(); dcdebug("Thrown OLE Exception: %d\n", sc); return; } dcassert(lpLockBytes != NULL); // Initialize a Storage Object IStorage *pStorage = NULL; sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage); if(sc != S_OK) { DeleteObject(hBitmap); pRichEditOle->Release(); lpLockBytes->Release(); lpLockBytes = NULL; dcdebug("Thrown OLE Exception: %d\n", sc); return; } dcassert(pStorage != NULL); CImageDataObject pods; pods.SetBitmap(hBitmap); // Get the RichEdit container site IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // The final ole object which will be inserted in the richedit control IOleObject* pOleObject = pods.GetOleObject(pOleClientSite, pStorage); if(pOleObject != NULL) { // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit REOBJECT reobject = { 0 }; reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = pOleObject->GetUserClassID(&clsid); if(sc != S_OK) { pRichEditOle->Release(); DeleteObject(hBitmap); dcdebug("Thrown OLE Exception: %d\n", sc); return; } reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.dwFlags = REO_BELOWBASELINE; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; // Insert the bitmap at the current location in the richedit control pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces pOleObject->Release(); } pOleClientSite->Release(); lpLockBytes->Release(); pStorage->Release(); pRichEditOle->Release(); DeleteObject(hBitmap); }
void CExRichEditWindowless::InsertGif(LONG gif) { CComQIPtr<IDynamicOleCom> spDyn; HRESULT hr = spDyn.CoCreateInstance(STR_PROGID); if(SUCCEEDED(hr)) { LPOLEOBJECT lpOleObject = NULL; HRESULT hr = spDyn->QueryInterface(IID_IOleObject, (void**)&lpOleObject); IUnknownPtr lpUnk = lpOleObject; hr = lpUnk->QueryInterface(IID_IOleObject, (LPVOID*)&lpOleObject); if (lpOleObject == NULL) throw(E_OUTOFMEMORY); //hr = lpOleObject->SetClientSite( static_cast<IOleClientSite *>( this ) ); IViewObject2Ptr lpViewObject;// IViewObject for IOleObject above hr = lpOleObject->QueryInterface(IID_IViewObject2, (LPVOID*)&lpViewObject); if (hr != S_OK) { AtlThrow(hr); } IRichEditOle* pRichEditOle = GetIRichEditOle(); ////获取RichEdit的OLEClientSite IOleClientSitePtr lpClientSite; hr = pRichEditOle->GetClientSite(&lpClientSite); if (hr != S_OK) { AtlThrow(hr); } REOBJECT reobject; ZeroMemory(&reobject,sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; hr = lpOleObject->GetUserClassID(&clsid); if (hr != S_OK) { AtlThrow(hr); } reobject.clsid = clsid; reobject.cp = -1; //reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT;//DVASPECT_OPAQUE; reobject.poleobj = lpOleObject; reobject.polesite = lpClientSite; //reobject.pstg = lpStorage; SIZEL sizel; sizel.cx = sizel.cy = 0; // let richedit determine initial size Image* img = (Image*)gif; SIZEL sizeInPix = {img->GetWidth(), img->GetHeight()}; SIZEL sizeInHiMetric; AtlPixelToHiMetric(&sizeInPix, &sizeInHiMetric); reobject.sizel = sizeInHiMetric; reobject.dwFlags = REO_BELOWBASELINE|REO_STATIC;//REO_RESIZABLE CExRichEditData* pdata = new CExRichEditData; pdata->m_dataType = GIF; pdata->m_data = (void*)gif; reobject.dwUser = (DWORD)pdata;//TODO 用户数据 lpOleObject->SetClientSite(lpClientSite); hr = pRichEditOle->InsertObject(&reobject); lpOleObject->SetExtent(DVASPECT_CONTENT, &sizeInHiMetric); OleSetContainedObject(lpOleObject, TRUE); lpOleObject->Release(); spDyn->SetHostWindow((LONG)hwndParent); spDyn->InsertGif(gif); } }