#include #ifdef PLATFORM_WIN32 NAMESPACE_UPP LPOLESTR AllocString(String s) { LPOLESTR p = reinterpret_cast(CoTaskMemAlloc(sizeof(OLECHAR) * (s.GetLength() + 1))), d = p; const char *f = s; while(*d++ = *f++) ; return p; } OcxControl::OcxControl() { ActiveX(); view_sink_aspect = DVASPECT_CONTENT; view_sink_advf = 0; status = CLOSED; stream_inited = false; timer_shutdown = false; extent_size = GetStdSize(); } OcxControl::~OcxControl() { LOGMETHOD("OcxControl::~OcxControl"); } bool OcxControl::IsOcxChild() { return true; } LRESULT OcxControl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { LOGMETHOD("OcxControl::WindowProc"); // RLOG("message = " << FormatIntHex(message) << ", wParam = " << FormatIntHex(wParam) << ", lParam = " << FormatIntHex(lParam)); if(message == WM_GETDLGCODE) return DLGC_WANTALLKEYS | DLGC_WANTARROWS | DLGC_WANTMESSAGE; LRESULT res = Ctrl::WindowProc(message, wParam, lParam); return res; } bool OcxControl::Open(HWND parent) // parent = 0 - create forged control { LOGMETHOD("OcxControl::Open"); // if(!IsForged()) ctrl_rect = GetRect(); if(IsOpen()) Ctrl::Close(); if(parent && IsChild()) Remove(); status = CLOSED; // noproc = true; // visible |= !parent; Rect rc = ctrl_rect; if(IsNull(rc)) rc = Rect(0, 0, 0, 0); if(!parent) { // move window away from screen in forged mode rc.Offset(-30000 - rc.left, -30000 - rc.top); SetRect(rc); } // view.SetRectEmpty(); Create(parent, (IsEnabled() ? 0 : WS_DISABLED) | (parent ? WS_CHILD : WS_POPUP) | WS_VISIBLE, (parent ? 0 : WS_EX_TOOLWINDOW), false, SW_HIDE, false); Show(); /* wnd = &stdwnd; fullrefresh = false; dword style = parent ? WS_CHILD : WS_POPUP, exstyle = WS_EX_TOOLWINDOW; if(!enabled) style |= WS_DISABLED; noproc = true; visible |= !parent; Rect rc = GetRect(); if(!parent) { // move window away from screen in forged mode rc.OffsetRect(-30000 - rc.left, -30000 - rc.top); SetRect(rc); } view.SetRectEmpty(); wnd->CreateEx(exstyle, CtrlWindowClass(), #ifdef _DEBUG Name(), #else NULL, #endif style, rc.left, rc.top, rc.Width(), rc.Height(), parent ? parent : 0, 0, 0); if(!wnd->m_hWnd) return false; type = POPUP; noproc = false; for(Ctrl *q = GetFirstChild(); q; q = q->GetNext()) reinterpret_cast(q)->_CreateChild(); if(visible) ShowWindow(GetHWND(), SW_SHOWNA); // SetMnemonic((byte) hotchar); RefreshLayout(); RefreshPos(); Refresh(); CancelMode(); CreateInit(); move = true; */ status = ACTIVE; //(parent ? ACTIVE : FORGED); return true; } void OcxControl::Serialize(Stream& stream) { int version = 1; SerializePos(stream); } void OcxControl::SerializePos(Stream& stream) { int version = 1; stream / version; Rect rc; if(stream.IsStoring()) rc = GetRect(); stream % rc; if(stream.IsLoading()) SetRect(rc); } const WCHAR OcxControl::data_stream_name[] = L"data"; HRESULT OcxControl::SetClientSite(IOleClientSite *site) { LOGMETHOD("IOleObject::SetClientSite()"); in_place_site = site; client_site = site; if(GetRect().IsEmpty()) { LOG("Setting up default control rect..."); SetRect(GetStdSize()); } return LOGRESULT(S_OK); } HRESULT OcxControl::GetClientSite(IOleClientSite **res) { LOGMETHOD("IOleObject::GetClientSite"); if(*res = ~client_site) client_site->AddRef(); return LOGRESULT(S_OK); } HRESULT OcxControl::SetHostNames(LPCOLESTR app_name, LPCOLESTR doc_name) { LOGMETHOD("IOleObject::SetHostNames"); return LOGRESULT(S_OK); } HRESULT OcxControl::Close(dword save_option) { LOGMETHOD("IOleObject::Close"); InPlaceDeactivate(); return LOGRESULT(S_OK); } HRESULT OcxControl::SetMoniker(dword which, IMoniker *moniker) { LOGMETHOD("IOleObject::SetMoniker"); return LOGRESULT(S_OK); } HRESULT OcxControl::GetMoniker(dword assign, dword which, IMoniker **moniker) { LOGMETHOD("IOleObject::GetMoniker"); *moniker = 0; return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::InitFromData(IDataObject *data, BOOL creation, dword) { LOGMETHOD("IOleObject::InitFromData"); return LOGRESULT(S_FALSE); } HRESULT OcxControl::GetClipboardData(dword, IDataObject **data) { LOGMETHOD("IOleObject::GetClipboardData"); *data = 0; return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::DoVerb(long verb, MSG *msg, IOleClientSite *active_site, long index, HWND parent, const RECT *rc) { LOGMETHOD("IOleObject::DoVerb"); switch(verb) { case OLEIVERB_PRIMARY: return DoVerbPrimary(); case OLEIVERB_SHOW: return DoVerbShow(); case OLEIVERB_INPLACEACTIVATE: return DoVerbInPlaceActivate(); case OLEIVERB_UIACTIVATE: return DoVerbUIActivate(); case OLEIVERB_HIDE: return DoVerbHide(); case OLEIVERB_OPEN: return DoVerbOpen(); case OLEIVERB_DISCARDUNDOSTATE: return DoVerbDiscardUndo(); case OLEIVERB_PROPERTIES: return DoVerbProperties(); default: return OLEOBJ_S_INVALIDVERB; } } HRESULT OcxControl::EnumVerbs(IEnumOLEVERB **verbs) { LOGMETHOD("IOleObject::EnumVerbs"); *verbs = 0; return LOGRESULT(OLEOBJ_E_NOVERBS); } HRESULT OcxControl::Update() { LOGMETHOD("IOleObject::Update"); return LOGRESULT(S_OK); } HRESULT OcxControl::IsUpToDate() { LOGMETHOD("IOleObject::IsUpToDate"); return LOGRESULT(MK_E_UNAVAILABLE); } HRESULT OcxControl::GetUserClassID(GUID *guid) { LOGMETHOD("IOleObject::GetUserClassID"); ASSERT(ocx_info); *guid = ocx_info->GetCoClassGUID(); return LOGRESULT(S_OK); } HRESULT OcxControl::GetUserType(dword form, LPOLESTR *type) { // __asm int 3 LOGMETHOD("IOleObject::GetUserType"); ASSERT(ocx_info); *type = AllocString(ocx_info->GetName()); return LOGRESULT(S_OK); } HRESULT OcxControl::SetExtent(dword aspect, SIZEL *hi_size) { LOGMETHOD("IOleObject::SetExtent(" << hi_size->cx << ", " << hi_size->cy << ")"); if(aspect == DVASPECT_CONTENT) { extent_size = min(FromHiMetric(*hi_size), GetMaxSize()); OCXLOG("Ctrl size = " << extent_size); SetRect(Rect(GetRect().TopLeft(), extent_size)); } return LOGRESULT(S_OK); } HRESULT OcxControl::GetExtent(dword aspect, SIZEL *size) { LOGMETHOD("IOleObject::GetExtent"); if(aspect == DVASPECT_CONTENT) { *size = ToHiMetric(extent_size); return LOGRESULT(S_OK); } return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::Advise(IAdviseSink *sink, dword *connection) { LOGMETHOD("IOleObject::Advise"); if(!sink || !connection) return E_INVALIDARG; *connection = advise_sinks.Add(sink); return LOGRESULT(S_OK); } HRESULT OcxControl::Unadvise(dword connection) { LOGMETHOD("IOleObject::Unadvise"); return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_INVALIDARG); } HRESULT OcxControl::EnumAdvise(IEnumSTATDATA **sink_enum) { LOGMETHOD("IOleObject::EnumAdvise"); *sink_enum = 0; return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::GetMiscStatus(dword aspect, dword *st) { LOGMETHOD("IOleObject::GetMiscStatus"); *st = OLEMISC_RECOMPOSEONRESIZE | OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE; return LOGRESULT(S_OK); } HRESULT OcxControl::SetColorScheme(LOGPALETTE *logpal) { LOGMETHOD("IOleObject::SetColorScheme"); return LOGRESULT(S_OK); } HRESULT OcxControl::GetClassID(GUID *guid) { LOGMETHOD("IPersist::GetClassID"); ASSERT(ocx_info); *guid = ocx_info->GetCoClassGUID(); return LOGRESULT(S_OK); } HRESULT OcxControl::IsDirty() { LOGMETHOD("IPersistStorage::IsDirty"); return LOGRESULT(IsModified() ? S_OK : S_FALSE); } HRESULT OcxControl::InitNew(IStorage *stg) { LOGMETHOD("IPersistStorage::InitNew"); if(!stg) return LOGRESULT(E_INVALIDARG); HRESULT hr; IStreamPtr stream; if(FAILED(hr = stg->CreateStream(data_stream_name, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) return LOGRESULT(hr); return InitNew(); // call IPersistStream::InitNew } HRESULT OcxControl::Load(IStorage *stg) { LOGMETHOD("IPersistStorage::Load"); if(!stg) return LOGRESULT(E_INVALIDARG); HRESULT hr; IStreamPtr stream; if(FAILED(hr = stg->OpenStream(data_stream_name, 0, STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stream))) return LOGRESULT(hr); return Load(stream); // delegate load to IPersistStream::Load } HRESULT OcxControl::Save(IStorage *stg, BOOL same_as_load) { LOGMETHOD("IPersistStorage::Save(" << (same_as_load ? "same as load" : "full save") << ')'); if(!stg) return LOGRESULT(E_INVALIDARG); HRESULT hr; #if LOG_PERSIST >= 1 STATSTG stat; Zero(stat); if(FAILED(hr = stg->Stat(&stat, STATFLAG_NONAME))) return LOGRESULT(hr); OCXLOG(NFormat("Storage flags = %08x\r\n", (int)stat.grfMode)); OCXLOG("CLSID = " << GetCoClassName(stat.clsid) << " - " << Format(stat.clsid)); #endif IStreamPtr stream; if(FAILED(hr = stg->CreateStream(data_stream_name, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream))) return LOGRESULT(hr); if(FAILED(hr = Save(stream, true))) return hr; #if LOG_PERSIST >= 1 ULARGE_INTEGER ul; if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &ul))) return hr; OCXLOG("- stream size = " << ul.LowPart); #endif return S_OK; } HRESULT OcxControl::SaveCompleted(IStorage *stg) { LOGMETHOD("IPersistStorage::SaveCompleted"); return LOGRESULT(S_OK); } HRESULT OcxControl::HandsOffStorage() { LOGMETHOD("IPersistStorage::HandsOffStorage"); return LOGRESULT(S_OK); } HRESULT OcxControl::Load(IStream *stream) { LOGMETHOD("IPersistStreamInit::Load"); if(stream_inited) return LOGRESULT(E_UNEXPECTED); #if LOG_PERSIST >= 1 ULARGE_INTEGER old_pos, len; HRESULT hr; if(FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_CUR, &old_pos)) || FAILED(hr = stream->Seek(AsLarge(0), STREAM_SEEK_END, &len)) || FAILED(hr = stream->Seek(reinterpret_cast(old_pos), STREAM_SEEK_SET, 0))) return hr; OCXLOG("- stream size = " << len.LowPart); #endif OleStream os(stream); if(!os.IsOpen() || os.IsError()) { LOGPERSIST("- internal error creating OleStream"); return LOGRESULT(E_FAIL); } os.SetLoading(); Serialize(os); ClearModify(); os.Close(); stream_inited = true; if(os.IsError()) return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); return LOGRESULT(S_OK); } HRESULT OcxControl::Save(IStream *stream, BOOL clear_dirty) { LOGMETHOD("IPersistStreamInit::Save"); OleStream os(stream); if(!os.IsOpen() || os.IsError()) { LOGPERSIST("- internal error creating OleStream"); return LOGRESULT(E_FAIL); } os.SetStoring(); Serialize(os); os.Close(); if(os.IsError()) return LOGRESULT(os.GetError() >= 0 ? os.GetError() : E_FAIL); if(clear_dirty) ClearModify(); return LOGRESULT(S_OK); } HRESULT OcxControl::GetSizeMax(ULARGE_INTEGER *size) { LOGMETHOD("IPersistStreamInit::GetSizeMax"); if(!size) return LOGRESULT(E_INVALIDARG); SizeStream ss; Serialize(ss); *size = AsULarge(ss.GetSize()); return LOGRESULT(S_OK); } HRESULT OcxControl::InitNew() { LOGMETHOD("IPersistStreamInit::InitNew"); if(stream_inited) return LOGRESULT(E_UNEXPECTED); SetRect(Rect(Point(0, 0), GetStdSize())); SetData(Value()); // default clear algorithm ClearModify(); stream_inited = true; return LOGRESULT(S_OK); } HRESULT OcxControl::GetData(FORMATETC *format, STGMEDIUM *medium) { LOGMETHOD("IDataObject::GetData"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::GetDataHere(FORMATETC *format, STGMEDIUM *medium) { LOGMETHOD("IDataObject::GetDataHere"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::QueryGetData(FORMATETC *format) { LOGMETHOD("IDataObject::QueryGetData"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::GetCanonicalFormatEtc(FORMATETC *in, FORMATETC *out) { LOGMETHOD("IDataObject::GetCanonicalFormatEtc"); *out = *in; out->ptd = 0; return LOGRESULT(DATA_S_SAMEFORMATETC); } HRESULT OcxControl::SetData(FORMATETC *format, STGMEDIUM *medium, BOOL free) { LOGMETHOD("IDataObject::SetData"); if(free) ReleaseStgMedium(medium); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::EnumFormatEtc(dword dir, IEnumFORMATETC **enumerator) { LOGMETHOD("IDataObject::EnumFormatEtc"); *enumerator = 0; return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::DAdvise(FORMATETC *format, dword advf, IAdviseSink *sink, dword *connection) { LOGMETHOD("IDataObject::DAdvise"); *connection = advise_sinks.Add(sink); return LOGRESULT(S_OK); } HRESULT OcxControl::DUnadvise(dword connection) { LOGMETHOD("IDataObject::DUnadvise"); return LOGRESULT(advise_sinks.Remove(connection) ? S_OK : E_FAIL); } HRESULT OcxControl::EnumDAdvise(IEnumSTATDATA **enumerator) { LOGMETHOD("IDataObject::EnumDAdvise"); *enumerator = 0; return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::Draw(dword aspect, long index, void *aspectinfo, DVTARGETDEVICE *device, HDC target_dc, HDC draw_dc, const RECTL *bounds, const RECTL *wbounds, BOOL (STDMETHODCALLTYPE *progress)(dword arg), dword arg) { LOGMETHOD("IViewObject::Draw"); if(aspect != DVASPECT_CONTENT) return DV_E_DVASPECT; // if(IsClosed() && !CreateControl(0)) // create forged control to make paint routines work // return E_FAIL; Rect rc(GetSize()); if(bounds) { rc.left = bounds->left; rc.top = bounds->top; rc.right = bounds->right; rc.bottom = bounds->bottom; LPtoDP(draw_dc, reinterpret_cast(&rc), 2); } // if(IsForged()) // SetCtrlRect(rc); Point worg, vorg; Size wext, vext; SetWindowOrgEx(draw_dc, 0, 0, worg); SetWindowExtEx(draw_dc, 1, 1, wext); SetViewportOrgEx(draw_dc, 0, 0, vorg); SetViewportExtEx(draw_dc, 1, 1, vext); int old_mode = SetMapMode(draw_dc, MM_TEXT); UPP::Draw draw(draw_dc); draw.Offset(rc.TopLeft()); DrawCtrl(draw); draw.End(); SetMapMode(draw_dc, old_mode); SetWindowOrgEx(draw_dc, worg.x, worg.y, 0); SetWindowExtEx(draw_dc, wext.cx, wext.cy, 0); SetViewportOrgEx(draw_dc, vorg.x, vorg.y, 0); SetViewportExtEx(draw_dc, vext.cx, vext.cy, 0); // DUMP(GetMapMode(draw_dc)); // DUMP(::GetWindow(draw_dc)); // DUMP(GetViewport(draw_dc)); // ::Draw draw(draw_dc); // draw.DrawRect(rc, Yellow); // draw.Clipoff(rc); // CtrlPaint(draw); // draw.End(); return LOGRESULT(S_OK); } HRESULT OcxControl::GetColorSet(dword aspect, long index, void *aspectinfo, DVTARGETDEVICE *device, HDC target, LOGPALETTE **palette) { LOGMETHOD("IViewObject::GetColorSet"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::Freeze(dword aspect, long index, void *aspectinfo, dword *freeze_key) { LOGMETHOD("IViewObject::Freeze"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::Unfreeze(dword freeze_key) { LOGMETHOD("IViewObject::Unfreeze"); return LOGRESULT(E_NOTIMPL); } HRESULT OcxControl::SetAdvise(dword aspect, dword advf, IAdviseSink *sink) { LOGMETHOD("IViewObject::SetAdvise(aspect = " << aspect << ", advf = " << advf << ")"); view_sink_aspect = aspect; view_sink_advf = advf; view_sink = sink; return LOGRESULT(S_OK); } HRESULT OcxControl::GetAdvise(dword *aspect, dword *advf, IAdviseSink **sink) { LOGMETHOD("IViewObject::GetAdvise"); if(aspect) *aspect = view_sink_aspect; if(advf) *advf = view_sink_advf; if(sink && (*sink = ~view_sink)) (**sink).AddRef(); return LOGRESULT(S_OK); } HRESULT OcxControl::GetExtent(dword aspect, long index, DVTARGETDEVICE *device, SIZEL *size) { LOGMETHOD("IViewObject2::GetExtent"); *size = GetRect().Size(); return LOGRESULT(S_OK); } HRESULT OcxControl::GetRect(dword aspect, RECTL *rc) { LOGMETHOD("IViewObjectEx::GetRect(aspect = " << aspect << ")"); if(aspect != DVASPECT_CONTENT) return E_NOTIMPL; if(!rc) return E_INVALIDARG; *rc = ToRectL(GetRect()); return S_OK; } HRESULT OcxControl::GetViewStatus(dword *status) { LOGMETHOD("IViewObjectEx::GetViewStatus"); *status = (IsTransparent() ? 0 : DVASPECT_OPAQUE); return S_OK; } HRESULT OcxControl::QueryHitPoint(dword aspect, const RECT *bounds, POINT pos, long close_hint, dword *result) { LOGMETHOD("IViewObjectEx::QueryHitPoint"); if(!result) return E_INVALIDARG; if(aspect != DVASPECT_CONTENT) return E_FAIL; *result = PtInRect(bounds, pos) ? HITRESULT_HIT : HITRESULT_OUTSIDE; return S_OK; } HRESULT OcxControl::QueryHitRect(dword aspect, const RECT *bounds, const RECT *rc, long close_hint, dword *result) { LOGMETHOD("IViewObjectEx::QueryHitRect"); if(!result) return E_INVALIDARG; if(aspect != DVASPECT_CONTENT) return E_FAIL; *result = Rect(*bounds).Contains(Rect(*rc)) ? HITRESULT_HIT : HITRESULT_OUTSIDE; return S_OK; } HRESULT OcxControl::GetNaturalExtent(dword aspect, long index, DVTARGETDEVICE *ptd, HDC tdc, DVEXTENTINFO *extinfo, SIZEL *psize) { LOGMETHOD("IViewObjectEx::GetNaturalExtent"); if(aspect != DVASPECT_CONTENT) return E_FAIL; if(psize) *psize = GetRect().Size(); return S_OK; } HRESULT OcxControl::GetWindow(HWND *hwnd) { LOGMETHOD("IOleWindow::GetWindow"); if(!hwnd) return LOGRESULT(E_INVALIDARG); return LOGRESULT((*hwnd = GetHWND()) ? S_OK : E_FAIL); } HRESULT OcxControl::ContextSensitiveHelp(BOOL enter_mode) { LOGMETHOD("IOleWindow::ContextSensitiveHelp"); return LOGRESULT(S_OK); } HRESULT OcxControl::InPlaceDeactivate() { LOGMETHOD("IOleInPlaceObject::InPlaceDeactivate"); if(!IsActive()) return LOGRESULT(S_OK); UIDeactivate(); if(!!in_place_site) in_place_site->OnInPlaceDeactivate(); if(IsOpen() && !IsChild()) Ctrl::Close(); in_place_site.Clear(); client_site.Clear(); status = CLOSED; return LOGRESULT(S_OK); } HRESULT OcxControl::UIDeactivate() { LOGMETHOD("IOleInPlaceObject::UIDeactivate"); if(!IsUIActive()) return LOGRESULT(S_OK); // no work needed when not UI active if(!in_place_site) return LOGRESULT(E_FAIL); SetActiveObject(false); return LOGRESULT(in_place_site->OnUIDeactivate(false)); } HRESULT OcxControl::SetObjectRects(const RECT *pos, const RECT *clip) { LOGMETHOD("IOleInPlaceObject::SetObjectRects(pos = " << Rect(*pos) << ", clip = " << Rect(*clip) << ")"); if(!pos || !clip) return LOGRESULT(E_INVALIDARG); Rect rc(Point(pos->left, pos->top), extent_size); OCXLOG("-> Ctrl rc = " << rc << " (extent size = " << extent_size << ")"); SetRect(rc); return LOGRESULT(S_OK); } HRESULT OcxControl::ReactivateAndUndo() { LOGMETHOD("IOleInPlaceObject::ReactivateAndUndo"); if(!IsActive()) return OLE_E_NOT_INPLACEACTIVE; return DoVerbUIActivate(); } HRESULT OcxControl::TranslateAccelerator(MSG *msg) { LOGMETHOD("IOleInPlaceObject::TranslateAccelerator"); dword keycode = 0; if(msg->message == WM_KEYDOWN) keycode = KEYtoK(msg->wParam); else if(msg->message == WM_KEYUP) keycode = KEYtoK(msg->wParam) | K_KEYUP; else if(msg->message == WM_SYSKEYDOWN && (msg->lParam & 0x20000000)) keycode = KEYtoK(msg->wParam); else if(msg->message == WM_SYSKEYUP && (msg->lParam & 0x20000000)) keycode = KEYtoK(msg->wParam) | K_KEYUP; else if(msg->message == WM_CHAR) keycode = msg->wParam; if(keycode == 0 || !IsActive() || !IsEnabled() || !IsVisible()) return LOGRESULT(S_FALSE); return LOGRESULT(HotKey(keycode) ? S_OK : S_FALSE); } HRESULT OcxControl::OnFrameWindowActivate(BOOL activate) { LOGMETHOD("IOleInPlaceObject::OnFrameWindowActivate"); Refresh(); return LOGRESULT(S_OK); } HRESULT OcxControl::OnDocWindowActivate(BOOL activate) { LOGMETHOD("IOleInPlaceObject::OnDocWindowActivate"); Refresh(); return LOGRESULT(S_OK); } HRESULT OcxControl::ResizeBorder(const RECT *border, IOleInPlaceUIWindow *ui, BOOL frame) { LOGMETHOD("IOleInPlaceObject::ResizeBorder"); Refresh(); return LOGRESULT(S_OK); } HRESULT OcxControl::EnableModeless(BOOL enable) { LOGMETHOD("IOleInPlaceObject::EnableModeless"); return LOGRESULT(S_OK); } HRESULT OcxControl::GetControlInfo(CONTROLINFO *cinfo) { LOGMETHOD("IOleControl::GetControlInfo"); if(!cinfo) return LOGRESULT(E_INVALIDARG); cinfo->hAccel = 0; cinfo->cAccel = 0; cinfo->dwFlags = 0; // by default eat neither Return nor Escape return LOGRESULT(S_OK); } HRESULT OcxControl::OnMnemonic(MSG *msg) { LOGMETHOD("IOleControl::OnMnemonic"); return LOGRESULT(S_OK); } HRESULT OcxControl::OnAmbientPropertyChange(DISPID dispid) { LOGMETHOD("IOleControl::OnAmbientPropertyChange"); return LOGRESULT(S_OK); } HRESULT OcxControl::FreezeEvents(BOOL freeze) { LOGMETHOD("IOleControl::FreezeEvents(" << (freeze ? "on" : "off") << ")"); return LOGRESULT(S_OK); } HRESULT OcxControl::DoVerbPrimary() { LOGMETHOD("DoVerbPrimary"); return LOGRESULT(ShowControl(true)); } HRESULT OcxControl::DoVerbShow() { LOGMETHOD("DoVerbShow"); return LOGRESULT(ShowControl(false)); } HRESULT OcxControl::ShowControl(bool ui_activate) { LOGMETHOD("OcxControl::ShowControl(" << (ui_activate ? "UI activate" : "") << ")"); if(!in_place_site) return LOGRESULT(E_FAIL); HRESULT hr; if(!IsActive()) { HWND parent = 0; if((hr = in_place_site->CanInPlaceActivate()) != S_OK || FAILED(hr = in_place_site->OnInPlaceActivate()) || FAILED(hr = in_place_site->GetWindow(&parent))) return LOGRESULT(hr); if(!parent || !::IsWindow(parent)) return E_FAIL; UpdateControlRect(); if(!Open(parent)) return LOGRESULT(E_FAIL); Show(); Enable(); // todo: fire view change // if(view_sink) // { // view_sink->OnViewChange(DVASPECT_CONTENT, -1); // if(view_sink_advf & ADVF_ONLYONCE) // view_sink = 0; // } // } if(ui_activate && !IsUIActive() && SUCCEEDED(in_place_site->OnUIActivate())) status = UIACTIVE; Show(); Enable(); if(!HasFocusDeep() && !SetWantFocus() && GetFirstChild()) IterateFocusForward(GetFirstChild(), this); SetActiveObject(true); return LOGRESULT(client_site->ShowObject()); } HRESULT OcxControl::DoVerbInPlaceActivate() { LOGMETHOD("DoVerbInPlaceActivate"); return LOGRESULT(ShowControl(false)); } HRESULT OcxControl::DoVerbUIActivate() { LOGMETHOD("DoVerbUIActivate"); return LOGRESULT(ShowControl(true)); } HRESULT OcxControl::DoVerbHide() { LOGMETHOD("DoVerbHide"); Hide(); // Close(false); return LOGRESULT(S_OK); } HRESULT OcxControl::DoVerbOpen() { LOGMETHOD("DoVerbOpen"); return LOGRESULT(ShowControl(false)); } HRESULT OcxControl::DoVerbDiscardUndo() { LOGMETHOD("DoVerbDiscardUndo"); return LOGRESULT(S_OK); } HRESULT OcxControl::DoVerbProperties() { LOGMETHOD("DoVerbProperties"); return LOGRESULT(S_OK); } void OcxControl::UpdateControlRect() { LOGMETHOD("OcxControl::UpdateControlRect"); if(!in_place_site) return; IOleInPlaceFramePtr frame; IOleInPlaceUIWindowPtr ui_window; OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; Rect rc, clip; if(FAILED(in_place_site->GetWindowContext(&frame, &ui_window, rc, clip, &frame_info))) return; OCXLOG("Control rect: " << rc << ", clip = " << clip); SetRect(rc); } void OcxControl::SetActiveObject(bool set) { LOGMETHOD("OcxControl::SetActiveObject"); if(!in_place_site) return; IRef frame; IRef ui_window; OLEINPLACEFRAMEINFO frame_info = { sizeof(frame_info) }; Rect rc, clip; if(FAILED(in_place_site->GetWindowContext(frame.Set(), ui_window.Set(), rc, clip, &frame_info))) return; if(!!frame) { frame->SetActiveObject(set ? this : 0, 0); if(set) frame->SetBorderSpace(0); } if(!!ui_window) { ui_window->SetActiveObject(set ? this : 0, 0); if(set) ui_window->SetBorderSpace(0); } } void OcxControl::RefreshSink() { LOGMETHOD("OcxControl::RefreshSink"); if(!!view_sink) view_sink->OnViewChange(DVASPECT_CONTENT, -1); } HRESULT OcxControl::GetActivationPolicy(DWORD *pdwPolicy) { LOGMETHOD("IPointerInactive::GetActivationPolicy"); *pdwPolicy = POINTERINACTIVE_ACTIVATEONENTRY; return LOGRESULT(S_OK); } HRESULT OcxControl::OnInactiveMouseMove(LPCRECT pRectBounds, LONG x, LONG y, DWORD grfKeyState) { LOGMETHOD("IPointerInactive::OnInactiveMouseMove"); return S_OK; } HRESULT OcxControl::OnInactiveSetCursor(LPCRECT pRectBounds, LONG x, LONG y, DWORD dwMouseMsg, BOOL fSetAlways) { LOGMETHOD("IPointerInactive::InactiveSetCursor"); return S_OK; } HRESULT OcxRunnableControl::GetRunningClass(GUID *clsid) { LOGMETHOD("IRunnableObject::GetRunningClass"); *clsid = __uuidof(0); return LOGRESULT(E_UNEXPECTED); } HRESULT OcxRunnableControl::Run(LPBC ctx) { LOGMETHOD("IRunnableObject::Run"); return LOGRESULT(S_OK); } BOOL OcxRunnableControl::IsRunning() { LOGMETHOD("IRunnableObject::IsRunning"); return true; } HRESULT OcxRunnableControl::LockRunning(BOOL lock, BOOL last_unlock_closes) { LOGMETHOD("IRunnableObject::LockRunning"); return LOGRESULT(S_OK); } HRESULT OcxRunnableControl::SetContainedObject(BOOL contained) { LOGMETHOD("IRunnableObject::SetContainedObject"); return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Next(unsigned long count, CONNECTDATA *data, unsigned long *fetched) { LOGMETHOD("IConnectionPoint::IEnumConnections::Next(" << (int)count << ")"); if(!point) return LOGRESULT(E_FAIL); if(count == 0 || !data || !fetched) return LOGRESULT(E_INVALIDARG); int avail = min(count, point->conn_map.GetCount() - index); if(avail <= 0) { *fetched = 0; return LOGRESULT(S_OK); } *fetched = avail; while(--avail >= 0) { data->pUnk = point->conn_map[index].AddRef(); data->dwCookie = point->conn_map.GetKey(index); index++; data++; } return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Skip(unsigned long connections) { LOGMETHOD("IConnectionPoint::IEnumConnections::Skip(" << (int)connections << ")"); index += connections; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Reset() { LOGMETHOD("IConnectionPoint::IEnumConnections::Reset()"); index = 0; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Enumerator::Clone(IEnumConnections **enum_conn) { LOGMETHOD("IConnectionPoint::IEnumConnections::Clone()"); Enumerator *enumerator = new OcxObjectWrapper; enumerator->Attach(~point); *enum_conn = enumerator; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionInterface(IID *iid) { LOGMETHOD("IConnectionPoint::GetConnectionInterface()"); *iid = guid; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::GetConnectionPointContainer(IConnectionPointContainer **cpc) { LOGMETHOD("IConnectionPoint::GetConnectionPointContainer()"); *cpc = container; if(container) { container->AddRef(); return LOGRESULT(S_OK); } return LOGRESULT(E_FAIL); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Advise(IUnknown *ptr, DWORD *cookie) { LOGMETHOD("IConnectionPoint::Advise()"); IRef pif; if(!cookie || !ptr || FAILED(ptr->QueryInterface(guid, pif.SetVoid()))) return LOGRESULT(E_INVALIDARG); // required interface not found *cookie = (free_id.IsEmpty() ? conn_map.GetCount() : free_id.Pop()); conn_map.Add(*cookie) = pif; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::Unadvise(DWORD cookie) { LOGMETHOD("IConnectionPoint::Unadvise(" << (int)cookie << ")"); int p = conn_map.Find(cookie); if(p < 0) return LOGRESULT(E_INVALIDARG); conn_map.Remove(p); free_id.Add(cookie); return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPoint::EnumConnections(IEnumConnections **enum_conn) { LOGMETHOD("IConnectionPoint::EnumConnections()"); Enumerator *enumerator = new OcxObjectWrapper; enumerator->Attach(this); *enum_conn = enumerator; return LOGRESULT(S_OK); } void OcxConnectionPoint::FireEvent(int method_id, const Vector& values) { LOGMETHOD("OcxConnectionPoint::FireEvent"); int i, nargs = values.GetCount(); Buffer args(nargs); for(i = 0; i < nargs; i++) { VARIANTARG& out = args[i]; out.vt = VT_EMPTY; VariantCopy(&out, &ValueToVariant(values[nargs - i - 1])); } DISPPARAMS disp = { args, 0, nargs, 0 }; for(i = 0; i < conn_map.GetCount(); i++) conn_map[i]->Invoke(method_id, IID_NULL, 0, DISPATCH_METHOD, &disp, NULL, NULL, NULL); for(i = 0; i < nargs; i++) VariantClear(&args[i]); } HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Next(unsigned long count, IConnectionPoint **data, unsigned long *fetched) { LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Next(" << (int)count << ")"); if(!point) return LOGRESULT(E_FAIL); if(count == 0 || !data || !fetched) return LOGRESULT(E_INVALIDARG); int avail = min(count, point->point_map.GetCount() - index); if(avail <= 0) { *fetched = 0; return LOGRESULT(S_OK); } *fetched = avail; while(--avail >= 0) { *data = point->point_map[index]; (*data)->AddRef(); index++; data++; } return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Skip(unsigned long connections) { LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Skip(" << (int)connections << ")"); index += connections; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Reset() { LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Reset()"); index = 0; return LOGRESULT(S_OK); } HRESULT STDMETHODCALLTYPE OcxConnectionPointContainer::Enumerator::Clone(IEnumConnectionPoints **enum_conn) { LOGMETHOD("IConnectionPointContainer::IEnumConnectionPoints::Clone()"); Enumerator *enumerator = new OcxObjectWrapper; enumerator->Attach(~point); *enum_conn = enumerator; return LOGRESULT(S_OK); } OcxConnectionPointContainer::OcxConnectionPointContainer() { } HRESULT OcxConnectionPointContainer::EnumConnectionPoints(IEnumConnectionPoints **ppEnum) { LOGMETHOD("IConnectionPointContainer::EnumConnectionPoints()"); Enumerator *enumerator = new OcxObjectWrapper; enumerator->Attach(this); *ppEnum = enumerator; return LOGRESULT(S_OK); } HRESULT OcxConnectionPointContainer::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) { Guid guid(riid); LOGMETHOD("IConnectionPointContainer::FindConnectionPoint(" << guid << ", ppCP = " << FormatIntHex(ppCP) << ")"); int i = point_map.Find(guid); RLOG("point_map.Find(guid) = " << i); if(i < 0) { *ppCP = 0; return LOGRESULT(CONNECT_E_NOCONNECTION); } (*ppCP = point_map[i])->AddRef(); return LOGRESULT(S_OK); } END_UPP_NAMESPACE #endif