You will now implement the Position property you added at the end of Step 2. This property exposes the document’s m_pt
member variable by using the second dispatch interface implemented by CAutoClickPoint
. You will expose this new property by adding code to the Get and Set member functions (GetPosition
and SetPosition
) which you declared in Step 2. The return type of GetPosition
and the type of the parameter passed to SetPosition
is LPDISPATCH, a pointer to a dispatch object.
The following two Autodriv message handlers, OnGetPosition
and OnSetPosition
, found in the CAutoDrivDlg
class, access the Position
property of AutoClik’s document dispatch interface using the GetPosition
property:
void CAutoDrivDlg::OnGetPosition()
{
CClikPoint point;
point.AttachDispatch(m_autoClikObject.GetPosition());
m_x = point.GetX();
m_y = point.GetY();
UpdateData(FALSE);
}
void CAutoDrivDlg::OnSetPosition()
{
CClikPoint point;
point.AttachDispatch(m_autoClikObject.GetPosition());
UpdateData(TRUE);
point.SetX((short)m_x);
point.SetY((short)m_y);
m_autoClikObject.SetPosition(point.m_lpDispatch);
}
The code:
CClikPoint point;
point.AttachDispatch(m_autoClikObject.GetPosition());
accesses AutoClik’s Position
property, which is declared as LPDISPATCH in the MFC Automation server’s dispatch map. The Automation client gets initial access to AutoClik’s document dispatch interface object by creating it (in the OnCreate
method):
if (!m_autoClikObject.CreateDispatch(_T("AutoClick.Document")))
{
AfxMessageBox(IDP_CANNOT_CREATE_AUTOCLICK);
return -1; // fail
}
m_autoClikObject.ShowWindow();
To declare one dispatch interface object as a property of another dispatch interface
This is the property you added in Step 2.
This takes you to their stub implementations in AutoClickDoc.cpp.
LPDISPATCH CAutoClickDoc::GetPosition()
{
CAutoClickPoint* pPos = new CAutoClickPoint;
pPos->m_x = (short) m_pt.x;
pPos->m_y = (short) m_pt.y;
LPDISPATCH lpResult = pPos->GetIDispatch(FALSE);
return lpResult;
}
void CAutoClickDoc::SetPosition(LPDISPATCH newValue)
{
CAutoClickPoint* pPos =
(CAutoClickPoint*)CCmdTarget::FromIDispatch(newValue);
if (pPos != NULL && pPos->IsKindOf
(RUNTIME_CLASS(CAutoClickPoint)))
{
m_pt.x = pPos->m_x;
m_pt.y = pPos->m_y;
Refresh();
}
}
#include "AutoClickPoint.h"
This is required because the implementation of SetPosition
refers to the CAutoClickPoint
class.
CAutoClickPoint
to display AutoClickPoint.h in the text editor. CAutoClickPoint
’s OLE dispatch map from protected to public, by adding the public keyword just before the comment line:public:
// Generated OLE dispatch map functions
//{{AFX_DISPATCH(CAutoClickPoint)
short m_x;
short m_y;
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
This is required because CAutoClickDoc
directly accesses CAutoClickPoint
’s member variables m_x
and m_y
in its implementation of GetPosition
and SetPosition
.
The implementation of GetPosition
creates a new CAutoClickPoint
object. The CAutoClickPoint
object, which is an Automation-enabled CCmdTarget object, in turn creates a dispatch interface object, through the help of the framework.
Finally, GetPosition
gets the OLE IDispatch pointer by calling the CCmdTarget::GetIDispatch member function of the CAutoClickPoint
object and returns this IDispatch pointer to the Automation client. The AddRef parameter of GetIDispatch is FALSE, because the OLE reference count of this dispatch interface object was already set to 1 when the CAutoClickPoint
object was constructed.
The implementation of SetPosition
does a C++ down-casting of the IDispatch pointer to a CAutoClickPoint
pointer. It tests the down-casting with IsKindOf to make sure the Automation client passed back an IDispatch pointer to a CAutoClickPoint
object rather than an IDispatch pointer to some other kind of object.
Finally, SetPosition
updates the view to reflect the new position of the text by calling the document’s Refresh
function. Because Refresh
is called by SetPosition
, it is not necessary to implement the OnXChanged
and OnYChanged
member functions to update the views for the CAutoClickPoint
class.