//----------------------------------------------------------------------------
// ObjectComponents
// (c) Copyright 1996 by Borland International, All Rights Reserved
//
/// \file
/// Implementation of the TOcControl Class and helpers
/// These class encapsulate the hosting of OCX controls...
//----------------------------------------------------------------------------
#include <ocf/pch.h>
#include <ocf/ocstorag.h>
#include <ocf/ocdoc.h>
#include <ocf/ocapp.h>
#include <ocf/ocview.h>
#include <ocf/occtrl.h>
#include <ocf/autodefs.h>
#include <ocf/automacr.h>
namespace ocf {
using namespace owl;
// Routine to convert TOcControl* to TOcxView* [treated as opaque pointers]
// for exposing delegated properties..
//
static ObjectPtr
GetControlView(ObjectPtr ctl);
//
//
//
TEventEntry::TEventEntry() : IDOfEvent(0), ParamCount(0), NameAndParams(0)
{}
//
//
//
TEventEntry::~TEventEntry()
{
Cleanup();
}
//
/// \note Does not invoke 'Cleanup' before initializing data member with
/// newly retrieved information. Invoke 'Cleanup' explicitly if
/// object has already retrieved event information.
//
void
TEventEntry::Init(int index, ITypeInfo* typeInfo)
{
PRECONDITION(typeInfo);
LPFUNCDESC funcDesc= 0;
if (SUCCEEDED(typeInfo->GetFuncDesc(index, &funcDesc))) {
CHECK(funcDesc);
IDOfEvent = funcDesc->memid;
ParamCount= funcDesc->cParams;
NameAndParams= new BSTR[funcDesc->cParams+1];
uint i;
typeInfo->GetNames(funcDesc->memid, NameAndParams,
funcDesc->cParams+1, &i);
CHECK(i == uint(funcDesc->cParams+1));
typeInfo->ReleaseFuncDesc(funcDesc);
}
}
//
//
//
void
TEventEntry::Cleanup()
{
if (NameAndParams) {
for (int i=0; i <= (int)ParamCount; i++)
::SysFreeString(NameAndParams[i]);
delete [] NameAndParams;
NameAndParams = 0;
}
}
//
//
//
TEventList::TEventList(ITypeInfo* eventTypeInfo)
:EventList(0), Count(0), EventIID(CLSID_NULL)
{
PRECONDITION(eventTypeInfo);
LPTYPEATTR tAttr = 0;
if (SUCCEEDED(eventTypeInfo->GetTypeAttr(&tAttr))) {
EventIID = tAttr->guid;
Count = tAttr->cFuncs;
if (Count) {
EventList = new TEventEntry[Count];
for (int i=0; i < (int)Count; i++)
EventList[i].Init(i, eventTypeInfo);
}
eventTypeInfo->ReleaseTypeAttr(tAttr);
}
}
//
//
//
TEventList::~TEventList()
{
delete [] EventList;
}
//
//
//
TEventEntry&
TEventList::operator[](int index) {
PRECONDITION(index < (int)Count);
PRECONDITION(EventList);
return EventList[index];
}
///RAYK - help contexts?
//
// Control container ambient property support
//
DEFINE_AUTOCLASS(TOcxView)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_BACKCOLOR, BackColor, TAutoLong, _T("!BackColor"), _T("@BackColor_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_FORECOLOR, ForeColor, TAutoLong, _T("!ForeColor"), _T("@ForeColor_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_LOCALEID, LocaleID, TAutoLong, _T("!LocaleID"), _T("@LocaleID_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_TEXTALIGN, TextAlign, TAutoShort, _T("!TextAlign"), _T("@TextAlign_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_MESSAGEREFLECT, MessageReflect, TAutoBool, _T("!MessageReflect"), _T("@MsgReflect_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_USERMODE, UserMode, TAutoBool, _T("!UserMode"), _T("@UserMode_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_UIDEAD, UIDead, TAutoBool, _T("!UIDead"), _T("@UIDead_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_SHOWGRABHANDLES, ShowGrabHandles, TAutoBool, _T("!ShowGrabHandles"), _T("@GrabHdl_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_SHOWHATCHING, ShowHatching, TAutoBool, _T("!ShowHatching"), _T("@ShowHat_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_DISPLAYASDEFAULT, DisplayAsDefault, TAutoBool, _T("!DisplayAsDefault"), _T("@DispDef_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_SUPPORTSMNEMONICS,SupportsMnemonics,TAutoBool, _T("!SupportsMnemonics"),_T("@Mnemonics_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_DISPLAYNAME, DisplayName, TAutoString, _T("!DisplayName"), _T("@DispName_"), 0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_SCALEUNITS, ScaleUnits, TAutoString, _T("!ScaleUnits"), _T("@ScaleUnits_"),0)
EXPOSE_PROPRW_ID(DISPID_AMBIENT_FONT, Font, TAutoDispatch,_T("!Font"), _T("@Font_"), 0)
END_AUTOCLASS(TOcxView, tfNormal, _T("TOcxView"), _T("@TOcxView_"), 0)
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4838) // warning C4838: conversion from 'unsigned long' to 'long' requires a narrowing conversion.
#endif
//
// Control standard extended properties and standard events
//
DEFINE_AUTOCLASS(TOcControl)
//
// Standard extended properties
//
EXPOSE_PROPRO_ID(0x80010008L, Parent, TAutoDispatch,_T("!Parent"), _T("!Parent"), 0)
EXPOSE_PROPRW_ID(0x80010007L, Visible, TAutoBool, _T("!Visible"), _T("!Visible"), 0)
EXPOSE_PROPRW_ID(0x80010037L, Cancel, TAutoBool, _T("!Cancel"), _T("@Cancel_"), 0)
EXPOSE_PROPRW_ID(0x80010038L, Default, TAutoBool, _T("!Default"), _T("@Default_"), 0)
EXPOSE_PROPRW_ID(0x80010000L, Name, TAutoString, _T("!Name"), _T("@ObjName_"), 0)
EXPOSE_PROPRW_ID(0x80010100L, Left, TAutoLong, _T("!Left"), _T("!Left"), 0)
EXPOSE_PROPRW_ID(0x80010101L, Top, TAutoLong, _T("!Top"), _T("!Top"), 0)
EXPOSE_PROPRW_ID(0x80010102L, Width, TAutoLong, _T("!Width"), _T("!Width"), 0)
EXPOSE_PROPRW_ID(0x80010103L, Height, TAutoLong, _T("!Height"), _T("!Height"), 0)
// Expose ambient properties
//
EXPOSE_DELEGATE(TOcxView, _T("TOcxView"), GetControlView)
END_AUTOCLASS(TOcControl, tfNormal, _T("TOcControl"), _T("@TOcControl_"), 0)
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
//
// Control standard extended properties and standard events
//
DEFINE_AUTOCLASS(TOcControlEvent)
//
// Standard events
//
EXPOSE_METHOD_ID(DISPID_CLICK, Click, TAutoLong, _T("!Click"), _T("@Click_"), 0)
EXPOSE_METHOD_ID(DISPID_DBLCLICK, DblClick, TAutoLong, _T("!DblClick"), _T("@DblClick_"), 0)
EXPOSE_METHOD_ID(DISPID_MOUSEDOWN, MouseDown,TAutoLong, _T("!MouseDown"), _T("@MouseDown_"), 0)
REQUIRED_ARG(TAutoShort, _T("!Button"))
REQUIRED_ARG(TAutoShort, _T("!Shift"))
REQUIRED_ARG(TAutoLong, _T("!X"))
REQUIRED_ARG(TAutoLong, _T("!Y"))
EXPOSE_METHOD_ID(DISPID_MOUSEUP, MouseUp, TAutoLong, _T("!MouseUp"), _T("@MouseUp_"), 0)
REQUIRED_ARG(TAutoShort, _T("!Button"))
REQUIRED_ARG(TAutoShort, _T("!Shift"))
REQUIRED_ARG(TAutoLong, _T("!X"))
REQUIRED_ARG(TAutoLong, _T("!Y"))
EXPOSE_METHOD_ID(DISPID_MOUSEMOVE, MouseMove,TAutoLong, _T("!MouseMove"), _T("@MouseMove_"), 0)
REQUIRED_ARG(TAutoShort, _T("!Button"))
REQUIRED_ARG(TAutoShort, _T("!Shift"))
REQUIRED_ARG(TAutoLong, _T("!X"))
REQUIRED_ARG(TAutoLong, _T("!Y"))
EXPOSE_METHOD_ID(DISPID_KEYDOWN, KeyDown, TAutoLong, _T("!KeyDown"), _T("@KeyDown_"), 0)
REQUIRED_ARG(TAutoShortRef, _T("!KeyCode"))
REQUIRED_ARG(TAutoShort, _T("!Shift"))
EXPOSE_METHOD_ID(DISPID_KEYUP, KeyUp, TAutoLong, _T("!KeyUp"), _T("@KeyUp_"), 0)
REQUIRED_ARG(TAutoShortRef, _T("!KeyCode"))
REQUIRED_ARG(TAutoShort, _T("!Shift"))
EXPOSE_METHOD_ID(DISPID_ERROREVENT, ErrorEvent, TAutoLong, _T("!ErrorEvent"),_T("&ErrorEvent_"),0)
REQUIRED_ARG(TAutoShort, _T("!Number"))
REQUIRED_ARG(TAutoString,_T("!Description"))
REQUIRED_ARG(TAutoLong, _T("!SCode"))
REQUIRED_ARG(TAutoString,_T("!Source"))
REQUIRED_ARG(TAutoString,_T("!HelpFile"))
REQUIRED_ARG(TAutoLong, _T("!HelpContext"))
REQUIRED_ARG(TAutoBoolRef,_T("!CancelDisplay"))
EXPOSE_METHOD_ID(DISPID_CATCH_ALL, CustomEvent, TAutoLong, _T("!CustomEvent"), _T("@CustomEvent_"),0)
REQUIRED_ARG(TAutoLongRef, _T("!Number"))
END_AUTOCLASS(TOcControlEvent, tfNormal, _T("TOcControlEvent"), _T("@TOcCtrlEvent_"), 0)
//
//
//
ObjectPtr GetControlView(ObjectPtr ctl)
{
return (ObjectPtr)((TOcControl*)ctl)->GetActiveControlView();
}
//
/// Construct a new part with a given temp id
//
TOcControl::TOcControl(TOcDocument& document, int id, TOcControlEvent* pEv)
:TOcPart(document, id), pUserName(new TString), BCtrlI(0),
pIExtended(0), pEvents(pEv), EventList(0)
{
*pUserName = GetName();
if (pEvents)
pEventsOwnership=false;
else
pEventsOwnership=true;
}
//
/// Construct a part from a named stream in an oc doc's storage
//
TOcControl::TOcControl(TOcDocument& document, LPCTSTR name)
:TOcPart(document, name), pUserName(0), BCtrlI(0), pIExtended(0),
pEvents(0), EventList(0)
{
// !rayk
pEventsOwnership=true;
}
//
//
//
TOcControl::~TOcControl()
{
if (pIExtended)
pIExtended->Release();
if (pEvents && pEventsOwnership)
delete pEvents;
delete pUserName;
delete EventList;
}
//
//
//
bool
TOcControl::Init(TOcInitInfo * initInfo, TRect objPos)
{
return TOcPart::Init(initInfo, objPos);
}
//
/// Perform common ctor initialization
//
bool
TOcControl::InitObj(TOcInitInfo * initInfo)
{
if (TOcPart::InitObj((TOcInitInfo *)NULL) == false)
return false;
if (initInfo) {
if (!pIExtended)
pIExtended = (TServedObject*)CreateAutoObject(this, ClassInfo);
if (!pEvents)
pEvents = new TOcControlEvent();
// There must be an IStorage associated with each part, make sure the
// ctor got it OK
//
initInfo->Storage = Storage->GetIStorage();
// Create part helper
//
TXObjComp::Check(
OcDocument.OcApp.BOleComponentCreate(&BPart, GetOuter(), cidBOleControl),
TXObjComp::xInternalPartError);
// Get the interfaces we need & then release the object itself
//
if (HRSucceeded(BPart->QueryInterface(IID_IBPart, (LPVOID *)&BPartI)))
BPartI->Release();
if (HRSucceeded(BPart->QueryInterface(IID_IBLinkable, (LPVOID *)&BLPartI)))
BLPartI->Release();
if (HRSucceeded(BPart->QueryInterface(IID_IBControl, (LPVOID *)&BCtrlI)))
BCtrlI->Release();
// Initialize the Extended/Ambient IDispatch
//
HRESULT hr;
IBSite* BSiteI;
hr = QueryInterface(IID_IBSite, (LPVOID *)&BSiteI);
if (HRSucceeded(hr)) {
IDispatch* pID = 0;
TOcView* activeView = OcDocument.GetActiveView();
CHECK(activeView);
if ((pIExtended) &&(SUCCEEDED(pIExtended->QueryObject(IID_IDispatch,
(LPVOID *)&pID)))) {
BCtrlI->SetAmbientDispatch(pID);
pID->Release();
}
// Init the part
//
if (!BPartI || !HRSucceeded(hr = BPartI->Init(BSiteI, initInfo))) {
BSiteI->Release();
BPart->Release();
BPart = 0;
TXObjComp::Throw(TXObjComp::xPartInitError, hr);
}
BSiteI->Release();
Rename();
if (initInfo->How == ihLink) // Remember that we are a link
Flags |= Link;
// Initialize the Events IDispatch
//
SetEventDispatch();
// New parts become active when they are init'd above. Make sure that
// our view knows that we are active too.
//
if (initInfo->Where == iwNew) {
Flags |= Active;
activeView->ActivatePart(this);
}
}
else
TXObjComp::Throw(TXObjComp::xPartInitError, hr);
}
return true;
}
//
/// Retrieves the ITypeInfo the 'default source' event object of this
/// control.
/// \note Receiver must 'Release' the returned object, if successful.
//
ITypeInfo*
TOcControl::GetEventTypeInfo()
{
ITypeInfo* pRet = NULL;
if (GetBControlI())
GetBControlI()->GetEventTypeInfo(&pRet);
return pRet;
}
//
/// Retrieves a list of events generated by this control.
/// Returns true if the event list was successfully retrieved.
//
bool
TOcControl::FillEventList()
{
// Skip if we've already retrieved the event list
//
if (EventList && EventList->GetCount())
return true;
// Retrieve Event ITypeInfo
//
ITypeInfo* eventTypeInfo = GetEventTypeInfo();
if (!eventTypeInfo)
return false;
// Allocate new EventList object
//
EventList = new TEventList(eventTypeInfo);
eventTypeInfo->Release();
return true;
}
//
//
//
TEventList*
TOcControl::GetEventList() const
{
return EventList;
}
//
/// Retrieves the primary IDispatch of the control.
/// \note Receiver must 'Release' the returned object, if successful.
//
IDispatch*
TOcControl::GetCtlDispatch()
{
IDispatch* pDisp = 0;
if (GetBControlI())
GetBControlI()->GetCtrlDispatch(&pDisp);
return pDisp;
}
//
//
//
void
TOcControl::SetEventDispatch()
{
if (!pEvents)
return;
pEvents->pCtrl = this;
pEvents->InitEventDispatch();
IDispatch* pID = 0;
TServedObject* pS = pEvents->pIEvents;
if (SUCCEEDED(pS->QueryObject(IID_IDispatch, (void**)&pID))) {
IID iidEv;
BCtrlI->GetEventIID(&iidEv);
pS->iidEvent = iidEv;
ITypeInfo* pITypeInfo;
LPTYPEATTR pTA;
UINT i;
UINT cEvents;
BCtrlI->GetEventTypeInfo(&pITypeInfo);
if (pITypeInfo) {
pITypeInfo->GetTypeAttr(&pTA);
if (pTA) {
cEvents = pTA->cFuncs;
pITypeInfo->ReleaseTypeAttr(pTA);
for (i = 0; i < cEvents; i++) {
LPFUNCDESC pFD;
if (SUCCEEDED(pITypeInfo->GetFuncDesc(i, &pFD))) {
ObjectPtr object = this; // copy in case of ptr adjustment
// see if we have a method associated with this DISPID
// if not, find one with the same name and see if the
// number of parameters matches
//
TAutoSymbol* sym = pS->Class->FindId(pFD->memid, object);
if (!sym) {
UINT cNames;
BSTR bstrName; // Event name(function only)
DISPID dispid; // Event name(function only)
if (SUCCEEDED(pITypeInfo->GetNames(pFD->memid, &bstrName,
1, &cNames))) {
sym = pS->Class->Lookup(OleStr(bstrName),
LANGIDFROMLCID(LOCALE_USER_DEFAULT),
asAnyCommand, dispid);
if (sym &&
(sym->DispId == -1 || sym->DispId == 0) &&
sym->TestFlag(DISPATCH_METHOD) && // check type
pS->Class->GetArgCount(*sym) == pFD->cParams) {
sym->DispId = pFD->memid;
}
SysFreeString(bstrName);
}
}
pITypeInfo->ReleaseFuncDesc(pFD);
}
}
}
pITypeInfo->Release();
}
BCtrlI->SetEventDispatch(pID);
pID->Release();
}
}
//
//
//
TOcView*
TOcControl::GetActiveControlView()
{
return (TOcView*)OcDocument.GetActiveView();
}
//
//
//
TUnknown*
TOcControl::CreateAutoObject(const void* obj, TAutoClass& clsInfo)
{
TAppDescriptor* appDesc;
TUnknown* result = 0;
appDesc = &(OcDocument.OcApp.GetRegistrar().GetAppDescriptor());
if (appDesc) {
result = appDesc->CreateAutoObject(obj, clsInfo.GetTypeInfo(),
obj, clsInfo.GetTypeInfo(), 0);
if (result)
((TServedObject*)result)->AddRef();
}
return result;
}
//
/// Callback from TUnknown's implementation of QueryInterface
//
HRESULT
TOcControl::QueryObject(const IID & iid, void * * iface)
{
PRECONDITION(iface);
HRESULT hr;
// interfaces
//
HRSucceeded(hr = IBControlSite_QueryInterface(this, iid, iface))
// helpers
//
|| HRSucceeded(hr = TOcPart::QueryObject(iid, iface))
|| (pIExtended &&(HRSucceeded(hr = pIExtended->QueryObject(iid, iface))))
;
return hr;
}
/// Extended property support
//
void
TOcControl::SetUserName(TString& name)
{
*pUserName = name;
}
//
//
//
TString&
TOcControl::GetUserName()
{
return *pUserName;
}
//
/// Retrieves the extended IDispatch (exposing extended properties)
//
IDispatch*
TOcControl::GetParent()
{
IDispatch* pID = 0;
TOcView* view = OcDocument.GetActiveView();
if (view) {
if (HRSucceeded(view->QueryInterface(IID_IDispatch, (LPVOID *)&pID)))
pID->Release();
}
return pID;
}
//
//
//
void
TOcControl::SetLeft(long value)
{
TPoint nuPos(int(value), Pos.y);
SetPos(nuPos);
UpdateRect();
}
//
//
//
void
TOcControl::SetWidth(long value)
{
TSize nuSize(int(value), Size.cy);
SetSize(nuSize);
UpdateRect();
}
//
//
//
void
TOcControl::SetTop(long value)
{
TPoint nuPos(Pos.x, int(value));
SetPos(nuPos);
UpdateRect();
}
//
//
//
void
TOcControl::SetHeight(long Value)
{
TSize nuSize(Size.cx, int(Value));
SetSize(nuSize);
UpdateRect();
}
//
/// Event support
//
HRESULT _IFUNC
TOcControl::OnControlFocus(BOOL fGotFocus)
{
TOcView* view = OcDocument.GetActiveView();
if (!view)
return HR_FAIL;
if (fGotFocus && (view->GetActivePart()) &&
(view->GetActivePart() != this))
view->GetActivePart()->Activate (FALSE);
TCtrlFocusEvent ev(this, fGotFocus);
view->ForwardEvent(OC_CTRLEVENT_FOCUS, &ev);
return HR_NOERROR;
}
//
//
//
HRESULT _IFUNC
TOcControl::OnPropertyChanged(DISPID dispid)
{
TOcView* view = OcDocument.GetActiveView();
if (!view)
return HR_FAIL;
TCtrlPropertyEvent ev(this, dispid);
view->ForwardEvent(OC_CTRLEVENT_PROPERTYCHANGE, &ev);
return HR_NOERROR;
}
//
//
//
HRESULT _IFUNC
TOcControl::OnPropertyRequestEdit(DISPID dispid)
{
TOcView* view = OcDocument.GetActiveView();
if (!view)
return HR_FAIL;
TCtrlPropertyEvent ev(this, dispid);
view->ForwardEvent(OC_CTRLEVENT_PROPERTYREQUESTEDIT, &ev);
return ev.accept ? HR_OK : HR_FALSE;
}
//
//
//
HRESULT _IFUNC
TOcControl::TransformCoords(TPointL * lpptlHimetric,
TPointF * lpptfContainer, DWORD flags)
{
TOcView* view = OcDocument.GetActiveView();
if (!view)
return HR_FAIL;
TCtrlTransformCoords ev(this, lpptlHimetric, lpptfContainer, flags);
if (!view->ForwardEvent(OC_VIEWTRANSFORMCOORDS, &ev)) {
// default if not handled is to go from himetric to pixels and back again
// if you want otherwise, you should override this, or answer the
// message differently.
HDC dc = ::GetDC(0);
int xPixPerInch = ::GetDeviceCaps(dc, LOGPIXELSX);
int yPixPerInch = ::GetDeviceCaps(dc, LOGPIXELSY);
ReleaseDC(0, dc);
if (flags & XFORMCOORDS_HIMETRICTOCONTAINER) {
lpptfContainer->x = (float)MAP_LOGHIM_TO_PIX(lpptlHimetric->x, xPixPerInch);
lpptfContainer->y = (float)MAP_LOGHIM_TO_PIX(lpptlHimetric->y, yPixPerInch);
}
else if (flags & XFORMCOORDS_CONTAINERTOHIMETRIC) {
lpptlHimetric->x = MAP_PIX_TO_LOGHIM((ULONG)lpptfContainer->x, xPixPerInch);
lpptlHimetric->y = MAP_PIX_TO_LOGHIM((ULONG)lpptfContainer->y, yPixPerInch);
}
}
return S_OK;
}
//
//
//
HRESULT _IFUNC TOcControl::Init(UINT, IBControl*, UINT)
{
return ResultFromScode(E_NOTIMPL);
}
//
/// TOcxView Class Implementation
//
TOcxView::TOcxView(TOcDocument& doc, TRegList* regList, IUnknown* outer)
:
TOcView(doc, regList, outer),
pBlankString(new TString(" "))
//pDisplayName(new TString("Control")),
//pScaleUnits(new TString("Control"))
{
TAppDescriptor* appDesc;
appDesc = &(OcApp.GetRegistrar().GetAppDescriptor());
if (appDesc) {
pIAmbients = (TServedObject*)appDesc->CreateAutoObject(
(VOID*)this, ClassInfo.GetTypeInfo(),
(VOID*)this, ClassInfo.GetTypeInfo(),
0);
if (pIAmbients)
pIAmbients->AddRef();
}
}
//
//
//
TOcxView::~TOcxView()
{
if (pIAmbients)
pIAmbients->Release();
delete pBlankString;
}
//
//
//
HRESULT
TOcxView::QueryObject(const IID & iid, void * * iface)
{
PRECONDITION(iface);
HRESULT hr;
// interfaces
//
if (pIAmbients && (HRSucceeded(hr = pIAmbients->QueryObject(iid, iface))))
{
}
// helpers
//
else if (HRSucceeded(hr = TOcView::QueryObject(iid, iface)))
{
}
return hr;
}
//
//
//
void
TOcxView::SetBackColor(long)
{
AmbientChanged(DISPID_AMBIENT_BACKCOLOR);
}
void
TOcxView::SetForeColor(long)
{
AmbientChanged(DISPID_AMBIENT_FORECOLOR);
}
void
TOcxView::SetLocaleID(long)
{
AmbientChanged(DISPID_AMBIENT_LOCALEID);
}
void
TOcxView::SetMessageReflect(bool)
{
AmbientChanged(DISPID_AMBIENT_MESSAGEREFLECT);
}
void
TOcxView::SetTextAlign(short)
{
AmbientChanged(DISPID_AMBIENT_TEXTALIGN);
}
void
TOcxView::SetUserMode(bool)
{
AmbientChanged(DISPID_AMBIENT_USERMODE);
}
void
TOcxView::SetUIDead(bool)
{
AmbientChanged(DISPID_AMBIENT_UIDEAD);
}
void
TOcxView::SetShowGrabHandles(bool)
{
AmbientChanged(DISPID_AMBIENT_SHOWGRABHANDLES);
}
void
TOcxView::SetSupportsMnemonics(bool)
{
AmbientChanged(DISPID_AMBIENT_SUPPORTSMNEMONICS);
}
void
TOcxView::SetShowHatching(bool)
{
AmbientChanged(DISPID_AMBIENT_SHOWHATCHING);
}
void
TOcxView::SetDisplayAsDefault(bool)
{
AmbientChanged(DISPID_AMBIENT_DISPLAYASDEFAULT);
}
void
TOcxView::SetDisplayName(TString& /*name*/)
{
//pDisplayName = &name;
AmbientChanged(DISPID_AMBIENT_DISPLAYNAME);
}
void
TOcxView::SetScaleUnits(TString& /*unit*/)
{
//pScaleUnits = &unit;
AmbientChanged(DISPID_AMBIENT_SCALEUNITS);
}
void
TOcxView::SetFont(IDispatch*)
{
AmbientChanged(DISPID_AMBIENT_FONT);
}
void
TOcxView::SetAmbBackColor(long color)
{
ForwardEvent(OC_AMBIENT_SETBACKCOLOR, color);
}
void
TOcxView::SetAmbForeColor(long color)
{
ForwardEvent(OC_AMBIENT_SETFORECOLOR, color);
}
void
TOcxView::SetAmbLocaleID(long localeId)
{
ForwardEvent(OC_AMBIENT_SETLOCALEID, localeId);
}
void
TOcxView::SetAmbMessageReflect(bool msgRef)
{
ForwardEvent(OC_AMBIENT_SETMESSAGEREFLECT, msgRef);
}
void
TOcxView::SetAmbTextAlign(short align)
{
ForwardEvent(OC_AMBIENT_SETTEXTALIGN, align);
}
void
TOcxView::SetAmbUserMode(bool mode)
{
ForwardEvent(OC_AMBIENT_SETUSERMODE, mode);
}
void
TOcxView::SetAmbUIDead(bool dead)
{
ForwardEvent(OC_AMBIENT_SETUIDEAD, dead);
}
void
TOcxView::SetAmbShowGrabHandles(bool handles)
{
ForwardEvent(OC_AMBIENT_SETSHOWGRABHANDLES, handles);
}
void
TOcxView::SetAmbSupportsMnemonics(bool mnem)
{
ForwardEvent(OC_AMBIENT_SETSUPPORTSMNEMONICS, mnem);
}
void
TOcxView::SetAmbShowHatching(bool hatch)
{
ForwardEvent(OC_AMBIENT_SETSHOWHATCHING, hatch);
}
void
TOcxView::SetAmbDisplayAsDefault(bool Disp)
{
ForwardEvent(OC_AMBIENT_SETDISPLAYASDEFAULT, Disp);
}
void
TOcxView::SetAmbDisplayName(TString& name)
{
ForwardEvent(OC_AMBIENT_SETDISPLAYNAME, &name);
}
void
TOcxView::SetAmbScaleUnits(TString& scaleUnits)
{
ForwardEvent(OC_AMBIENT_SETSCALEUNITS, &scaleUnits);
}
void
TOcxView::SetAmbFont(IDispatch* fontDisp)
{
ForwardEvent(OC_AMBIENT_SETFONT, fontDisp);
}
long
TOcxView::GetBackColor()
{
return GetAmbientValue(OC_AMBIENT_GETBACKCOLOR, RGB(0x80, 0x80, 0x80));
}
long
TOcxView::GetForeColor()
{
return GetAmbientValue(OC_AMBIENT_GETFORECOLOR, RGB(0x00, 0x00, 0x00));
}
long
TOcxView::GetLocaleID()
{
return GetAmbientValue(OC_AMBIENT_GETLOCALEID, LOCALE_USER_DEFAULT);
}
bool
TOcxView::GetMessageReflect()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETMESSAGEREFLECT, false) & 0xf);
}
short
TOcxView::GetTextAlign()
{
return (short)(GetAmbientValue(OC_AMBIENT_GETTEXTALIGN, 0) & 0xffff);
}
bool
TOcxView::GetUserMode()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETUSERMODE, true) & 0xf);
}
bool
TOcxView::GetUIDead()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETUIDEAD, false) & 0xf);
}
bool
TOcxView::GetShowGrabHandles()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETSHOWGRABHANDLES, false) & 0xf);
}
bool
TOcxView::GetShowHatching()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETSHOWHATCHING, false) & 0xf);
}
bool
TOcxView::GetDisplayAsDefault()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETDISPLAYASDEFAULT, false) & 0xf);
}
bool
TOcxView::GetSupportsMnemonics()
{
return (bool)(GetAmbientValue(OC_AMBIENT_GETSUPPORTSMNEMONICS, false) & 0xf);
}
TString&
TOcxView::GetDisplayName()
{
TString* value;
return ForwardEvent(OC_AMBIENT_GETDISPLAYNAME, &value) ? *value : *pBlankString;
}
TString&
TOcxView::GetScaleUnits()
{
TString* value;
return ForwardEvent(OC_AMBIENT_GETSCALEUNITS, &value) ? *value : *pBlankString;
}
IDispatch*
TOcxView::GetFont()
{
IDispatch* value;
// NOTE: If view handles the message, it should AddRef the font
//
return ForwardEvent(OC_AMBIENT_GETFONT, &value) ? value: 0;
}
void
TOcxView::AmbientChanged(DISPID dispid)
{
// Will loop through all known controls and let them
// know when an ambient property changes
//
for (TOcPartCollectionIter i(OcDocument.GetParts()); i; i++) {
TOcPart* ocPart = (TOcPart*)i.Current();
IBControl* CtrlI;
if (SUCCEEDED(ocPart->QueryInterface(IID_IBControl, (LPVOID *)&CtrlI))) {
#if 0
// !BB The following order of call looks very suspicious to me
// !BB Shouldn't one release only and only when the interface pointer
// !BB will no longer be used?? Or, I am missing some subtle issue
// !BB about OLE controls and Ambient property changed.
CtrlI->Release();
CtrlI->AmbientChanged(dispid);
#else
CtrlI->AmbientChanged(dispid);
CtrlI->Release();
#endif
}
}
}
long
TOcxView::GetAmbientValue(long ambientMsg, long def)
{
uint32 value;
return ForwardEvent(int(ambientMsg), &value) ? value : def;
}
//
// TOcControlEvent Class Implementation
// Support for standard events and generic custom event
//
TOcControlEvent::TOcControlEvent()
:pCtrl(0), pIEvents(0)
{
}
TOcControlEvent::~TOcControlEvent()
{
if (pIEvents)
pIEvents->Release();
}
void
TOcControlEvent::InitEventDispatch()
{
if (!pIEvents)
pIEvents = (TServedObject *)CreateAutoObject(this, ClassInfo);
}
TUnknown*
TOcControlEvent::CreateAutoObject(const void* obj, TAutoClass& clsInfo)
{
if (pCtrl) {
clsInfo.AutoIds = false;
pIEvents = (TServedObject*)pCtrl->CreateAutoObject(obj, clsInfo);
return pIEvents;
}
else
return 0;
}
//
//
//
HRESULT
TOcControlEvent::ForwardClickEvent(uint msg, DISPID dispid)
{
TOcView* view = pCtrl->GetActiveControlView();
if (!view)
return E_FAIL;
TCtrlEvent ev(pCtrl, dispid);
view->ForwardEvent(msg, &ev);
return S_OK;
}
//
//
//
HRESULT
TOcControlEvent::ForwardMouseEvent(uint msg, DISPID id,
short button, short shift,
long x, long y)
{
TOcView* view = pCtrl->GetActiveControlView();
if (!view)
return E_FAIL;
TCtrlMouseEvent ev(pCtrl, id, button, shift, x, y);
view->ForwardEvent(msg, &ev);
return S_OK;
}
//
//
//
HRESULT
TOcControlEvent::ForwardKeyEvent(uint msg, DISPID id,
short* keyCode, short shift)
{
TOcView* view = pCtrl->GetActiveControlView();
if (!view)
return E_FAIL;
TCtrlKeyEvent ev(pCtrl, id, *keyCode, shift);
view->ForwardEvent(msg, &ev);
return S_OK;
}
//
//
//
HRESULT
TOcControlEvent::ErrorEvent(short Number, TAutoString Description,
SCODE SCode, TAutoString Source,
TAutoString HelpFile, long HelpContext,
bool* CancelDisplay)
{
TOcView* view = pCtrl->GetActiveControlView();
if (!view)
return E_FAIL;
TCtrlErrorEvent ev(pCtrl, Number, Description, SCode, Source, HelpFile,
HelpContext, *CancelDisplay);
view->ForwardEvent(OC_CTRLEVENT_ERROREVENT, &ev);
return S_OK;
}
//
//
//
HRESULT
TOcControlEvent::CustomEvent(long* args)
{
TOcView* view = pCtrl->GetActiveControlView();
if (!view)
return HR_FAIL;
TAutoStack* autoStack = (TAutoStack*)args;
TCtrlCustomEvent ev(pCtrl, autoStack->DispId, autoStack);
view->ForwardEvent(OC_CTRLEVENT_CUSTOMEVENT, &ev);
return HR_NOERROR;
}
//
//
//
HRESULT
TOcControlEvent::Click()
{
return ForwardClickEvent(OC_CTRLEVENT_CLICK, DISPID_CLICK);
}
//
//
//
HRESULT
TOcControlEvent::DblClick()
{
return ForwardClickEvent(OC_CTRLEVENT_DBLCLICK, DISPID_DBLCLICK);
}
//
//
//
HRESULT
TOcControlEvent::MouseDown(short button, short shift, long x, long y)
{
return ForwardMouseEvent(OC_CTRLEVENT_MOUSEDOWN, DISPID_MOUSEDOWN,
button, shift, x, y);
}
//
//
//
HRESULT
TOcControlEvent::MouseMove(short button, short shift, long x, long y)
{
return ForwardMouseEvent(OC_CTRLEVENT_MOUSEMOVE, DISPID_MOUSEMOVE,
button, shift, x, y);
}
//
//
//
HRESULT
TOcControlEvent::MouseUp(short button, short shift, long x, long y)
{
return ForwardMouseEvent(OC_CTRLEVENT_MOUSEUP,
DISPID_MOUSEUP, button, shift, x, y);
}
//
//
//
HRESULT
TOcControlEvent::KeyDown(short * keyCode, short shift)
{
return ForwardKeyEvent(OC_CTRLEVENT_KEYDOWN, DISPID_KEYDOWN,
keyCode, shift);
}
//
//
//
HRESULT
TOcControlEvent::KeyUp(short * keyCode, short shift)
{
return ForwardKeyEvent(OC_CTRLEVENT_KEYUP, DISPID_KEYUP,
keyCode, shift);
}
//
//
//
typedef HRESULT (PASCAL *REGPROC)();
//
//
//
static HRESULT
OcInvokeProc(LPCTSTR libraryName, LPCSTR procName)
{
HRESULT hr = ResultFromScode (E_FAIL);
HINSTANCE libHandle = LoadLibrary(libraryName);
if (libHandle <= HINSTANCE(HINSTANCE_ERROR))
return hr;
REGPROC dllRegProc;
dllRegProc = (REGPROC)::GetProcAddress (libHandle, procName);
if (dllRegProc) {
hr = dllRegProc();
}
FreeLibrary(libHandle);
return hr;
}
//
//
//
_OCFFUNC(HRESULT)
OcRegisterControl(LPTSTR libraryName)
{
// NOTE: The new recommendation is to refrain from loading the control
// until the 'SelfRegister' string has been found in the VERSIONINFO
// resource...
//
return OcInvokeProc(libraryName, "DllRegisterServer");
}
//
//
//
_OCFFUNC(HRESULT)
OcUnregisterControl (CLSID classId)
{
HRESULT hr;
LPOLESTR str;
hr = StringFromCLSID (classId, &str);
if (SUCCEEDED(hr)) {
TCHAR temp[64];
_tcscpy (temp, OleStr(str));
TCHAR key[255];
wsprintf (key, _T("CLSID\\%s\\InprocServer32"), temp);
CoTaskMemFree(str);
TCHAR ocxPath[_MAX_PATH];
long len = sizeof(ocxPath);
hr = (HRESULT)RegQueryValue (TRegKey::GetClassesRoot(),
key, ocxPath,
(LONG *)&len);
if (SUCCEEDED(hr)) {
// NOTE: The new recommendation is to refrain from loading the control
// until the 'SelfRegister' string has been found in the VERSIONINFO
// resource...
//
hr = OcInvokeProc(ocxPath, "DllUnregisterServer");
}
}
return hr;
}
} // OCF namespace
//==============================================================================
↑ V595 The 'BPartI' pointer was utilized before it was verified against nullptr. Check lines: 300, 323.
↑ V614 Uninitialized pointer 'value' used. Consider checking the second actual argument of the 'ForwardEvent' function.
↑ V614 Uninitialized pointer 'value' used. Consider checking the second actual argument of the 'ForwardEvent' function.
↑ V614 Uninitialized pointer 'value' used. Consider checking the second actual argument of the 'ForwardEvent' function.
↑ V614 Uninitialized variable 'value' used. Consider checking the second actual argument of the 'ForwardEvent' function.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: CtlId.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: CtlId.
↑ V1004 The 'typeInfo' pointer was used unsafely after it was verified against nullptr. Check lines: 50, 52.
↑ V1004 The 'funcDesc' pointer was used unsafely after it was verified against nullptr. Check lines: 53, 54.
↑ V1004 The 'eventTypeInfo' pointer was used unsafely after it was verified against nullptr. Check lines: 86, 89.
↑ V1032 The pointer 'args' is cast to a more strictly aligned pointer type.
↑ V547 Expression 'appDesc' is always true.
↑ V547 Expression 'appDesc' is always true.
↑ V1004 The 'activeView' pointer was used unsafely after it was verified against nullptr. Check lines: 314, 344.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'true' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V601 The 'false' value is implicitly cast to the integer type. Inspect the second argument.
↑ V803 Decreased performance. In case 'i' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.
↑ V813 Decreased performance. The 'objPos' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'classId' argument should probably be rendered as a constant reference.