LINE.CPP (LINES OLE Sample)

/*************************************************************************

  • OLE Automation Lines Object.

  • line.cpp

  • CLine implementation

  • Written by Microsoft Product Support Services, Windows Developer Support

  • (c) Copyright Microsoft Corp. 1994 All Rights Reserved

  • ***********************************************************************/

#include <windows.h>

#include <windowsx.h>

#ifdef WIN16

#include <ole2.h>

#include <compobj.h>

#include <dispatch.h>

#include <variant.h>

#include <olenls.h>

#endif

#include "lines.h"

/*

* CLine::Create

*

* Purpose:

* Creates an instance of the Line automation object and initializes it.

*

* Parameters:

* ppLine Returns Line automation object.

*

* Return Value:

* HRESULT

*

*/

HRESULT

CLine::Create(CLine FAR* FAR* ppLine )

{

HRESULT hr;

CLine FAR* pLine = NULL;

*ppLine = NULL;

pLine = new CLine();

if (pLine == NULL)

goto error;

// Load type information for the line from type library.

hr = LoadTypeInfo(&pLine->m_ptinfo, IID_ILine);

if (FAILED(hr))

goto error;

*ppLine = pLine;

return NOERROR;

error:

if (pLine == NULL)

return ResultFromScode(E_OUTOFMEMORY);

if (pLine->m_ptinfo)

pLine->m_ptinfo->Release();

// Set to NULL to prevent destructor from attempting to free again

pLine->m_ptinfo = NULL;

delete pLine;

return hr;

}

/*

* CLine::CLine

*

* Purpose:

* Constructor for CLine object. Initializes members to NULL.

*

*/

#pragma warning (disable : 4355)

CLine::CLine() : m_SupportErrorInfo(this, IID_ILine)

#pragma warning (default : 4355)

{

m_ptinfo = NULL;

m_pPointStart = NULL;

m_pPointEnd = NULL;

m_nThickness = 0;

m_colorref = 0;

m_cRef = 0;

}

/*

* CLine::~CLine

*

* Purpose:

* Destructor for CLine object.

*

*/

CLine::~CLine()

{

if (m_ptinfo) m_ptinfo->Release();

if (m_pPointStart) m_pPointStart->Release();

if (m_pPointEnd) m_pPointEnd->Release();

}

/*

* CLine::QueryInterface, AddRef, Release

*

* Purpose:

* Implements IUnknown::QueryInterface, AddRef, Release

*

*/

STDMETHODIMP

CLine::QueryInterface(REFIID iid, void FAR* FAR* ppv)

{

*ppv = NULL;

if (iid == IID_IUnknown || iid == IID_IDispatch || iid == IID_ILine)

*ppv = this;

else if (iid == IID_ISupportErrorInfo)

*ppv = &m_SupportErrorInfo;

else return ResultFromScode(E_NOINTERFACE);

AddRef();

return NOERROR;

}

STDMETHODIMP_(ULONG)

CLine::AddRef(void)

{

#ifdef _DEBUG

TCHAR ach[50];

wsprintf(ach, TEXT("Ref = %ld, Line\r\n"), m_cRef+1);

OutputDebugString(ach);

#endif

return ++m_cRef;

}

STDMETHODIMP_(ULONG)

CLine::Release(void)

{

#ifdef _DEBUG

TCHAR ach[50];

wsprintf(ach, TEXT("Ref = %ld, Line\r\n"), m_cRef-1);

OutputDebugString(ach);

#endif

if(--m_cRef == 0)

{

delete this;

return 0;

}

return m_cRef;

}

/*

* CLine::GetTypeInfoCount

*

* Purpose:

* Implements IDispatch::GetTypeInfoCount.

*

*/

STDMETHODIMP

CLine::GetTypeInfoCount(UINT FAR* pctinfo)

{

*pctinfo = 1;

return NOERROR;

}

/*

* CLine::GetTypeInfo

*

* Purpose:

* Implements IDispatch::GetTypeInfo.

*

*/

STDMETHODIMP

CLine::GetTypeInfo(

UINT itinfo,

LCID lcid,

ITypeInfo FAR* FAR* pptinfo)

{

*pptinfo = NULL;

if(itinfo != 0)

return ResultFromScode(DISP_E_BADINDEX);

m_ptinfo->AddRef();

*pptinfo = m_ptinfo;

return NOERROR;

}

/*

* CLine::GetIDsOfNames

*

* Purpose:

* Implements IDispatch::GetIDsOfNames. The standard implementation, DispGetIDsOfNames,

* is used.

*

*/

STDMETHODIMP

CLine::GetIDsOfNames(

REFIID riid,

OLECHAR FAR* FAR* rgszNames,

UINT cNames,

LCID lcid,

DISPID FAR* rgdispid)

{

return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);

}

/*

* CLine::Invoke

*

* Purpose:

* Implements IDispatch::Invoke. The standard implementation, DispInvoke,

* is used. Properties and methods exposed by the application object will

* set m_bRaiseException to raise an exception.

*

*/

STDMETHODIMP

CLine::Invoke(

DISPID dispidMember,

REFIID riid,

LCID lcid,

WORD wFlags,

DISPPARAMS FAR* pdispparams,

VARIANT FAR* pvarResult,

EXCEPINFO FAR* pexcepinfo,

UINT FAR* puArgErr)

{

HRESULT hr;

// VB 3.0/Disptest have a bug in which they pass DISPATCH_PROPERTYPUT

// instead of DISPATCH_PROPERTYPUTREF for the EndPoint and StartPoint

// properties. Future versions of VB will correctly pass DISPATCH_PROPERTYPUTREF.

// EndPoint has DISPID == 1 and StartPoint has DISPID == 2 - see lines.odl.

// The following code works around the VB 3.0/Disptest bug.

if ((dispidMember == 1 || dispidMember == 2)

&& wFlags == DISPATCH_PROPERTYPUT)

wFlags = DISPATCH_PROPERTYPUTREF;

m_bRaiseException = FALSE;

hr = DispInvoke(

this, m_ptinfo,

dispidMember, wFlags, pdispparams,

pvarResult, pexcepinfo, puArgErr);

if (m_bRaiseException)

{

if (NULL != pexcepinfo)

_fmemcpy(pexcepinfo, &m_excepinfo, sizeof(EXCEPINFO));

return ResultFromScode(DISP_E_EXCEPTION);

}

else return hr;

}

/*

*

* Properties and methods exposed through automation.

*

*/

STDMETHODIMP

CLine::get_Color(long FAR* plColorref)

{

*plColorref = m_colorref;

return NOERROR;

}

STDMETHODIMP

CLine::put_Color(long lColorref)

{

m_colorref = (COLORREF)lColorref;

return NOERROR;

}

STDMETHODIMP

CLine::get_EndPoint(IPoint FAR* FAR* ppPoint)

{

HRESULT hr;

*ppPoint = NULL;

if (NULL == m_pPointEnd)

return RaiseException(IDS_NoStartPoint);

hr = m_pPointEnd->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoint);

if (FAILED(hr))

return RaiseException(IDS_Unexpected);

return NOERROR;

}

STDMETHODIMP

CLine::putref_EndPoint(IPoint FAR* pPointNew)

{

HRESULT hr;

CPoint FAR* pPoint;

// Save the IPoint interface so we can easily access private data

hr = pPointNew->QueryInterface(IID_IPoint, (void FAR* FAR*)&pPoint);

if (FAILED(hr))

return RaiseException(IDS_PointFromOtherInstance);

// Replace the old point with the new

if (m_pPointEnd)

m_pPointEnd->Release();

m_pPointEnd = pPoint;

return NOERROR;

}

STDMETHODIMP

CLine::get_StartPoint(IPoint FAR* FAR* ppPoint)

{

HRESULT hr;

*ppPoint = NULL;

if (NULL == m_pPointStart)

return RaiseException(IDS_NoStartPoint);

hr = m_pPointStart->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoint);

if (FAILED(hr))

return RaiseException(IDS_Unexpected);

return NOERROR;

}

STDMETHODIMP

CLine::putref_StartPoint(IPoint FAR* pPointNew)

{

HRESULT hr;

CPoint FAR* pPoint;

// Save the IPoint interface so we can easily access private data

hr = pPointNew->QueryInterface(IID_IPoint, (void FAR* FAR*)&pPoint);

if (FAILED(hr))

return RaiseException(IDS_PointFromOtherInstance);

// Replace the old point with the new

if (m_pPointStart)

m_pPointStart->Release();

m_pPointStart = pPoint;

return NOERROR;

}

STDMETHODIMP

CLine::get_Thickness(int FAR* pnThickness)

{

*pnThickness = m_nThickness;

return NOERROR;

}

STDMETHODIMP

CLine::put_Thickness(int nThickness)

{

m_nThickness = nThickness;

return NOERROR;

}

/*

*

* The following methods are not exposed through Automation

*

*/

STDMETHODIMP_(void)

CLine::Draw(HDC hdc)

{

HPEN hpen, hpenOld;

if (m_pPointStart == NULL)

return;

if (m_pPointEnd == NULL)

return;

hpen = CreatePen(PS_SOLID, m_nThickness, m_colorref);

hpenOld = (HGDIOBJ)SelectObject(hdc, (HGDIOBJ)hpen);

MoveToEx(hdc, m_pPointStart->get_x(), m_pPointStart->get_y(), NULL);

LineTo(hdc, m_pPointEnd->get_x(), m_pPointEnd->get_y());

SelectObject(hdc, (HGDIOBJ)hpenOld);

DeleteObject((HGDIOBJ)hpen);

return;

}

/*

* CLine::GetInvalidateRect

*

* Purpose:

* Get the rectangle that cicumscribes the line. This rectangle is used to invalidate the area

* of the window where the line is to be draw or erased.

*

*/

STDMETHODIMP_(void)

CLine::GetInvalidateRect(LPRECT prc)

{

int nX1, nY1, nX2, nY2;

nX1 = m_pPointStart->get_x();

nY1 = m_pPointStart->get_y();

nX2 = m_pPointEnd->get_x();

nY2 = m_pPointEnd->get_y();

if (nX1 < nX2)

{

prc->left = nX1;

prc->right = nX2;

}

else

{

prc->left = nX2;

prc->right = nX1;

}

if (nY1 < nY2)

{

prc->top = nY1;

prc->bottom = nY2;

}

else

{

prc->top = nY2;

prc->bottom = nY1;

}

InflateRect(prc, m_nThickness, m_nThickness);

}

STDMETHODIMP_(BOOL)

CLine::AddEndPointsToPane(CPane FAR* pPane)

{

// Does the line have end points?

if (NULL == m_pPointStart)

return FALSE;

if (NULL == m_pPointEnd)

return FALSE;

// Add points to Point collection in the Pane object.

if (pPane->AddPoint(m_pPointStart))

return pPane->AddPoint(m_pPointEnd);

return FALSE;

}

STDMETHODIMP_(void)

CLine::RemoveEndPointsFromPane(CPane FAR* pPane)

{

// Remove the end points of the line to be removed from the Points collection in the Pane.

if (NULL != m_pPointStart)

pPane->RemovePoint(m_pPointStart);

if (NULL != m_pPointEnd)

pPane->RemovePoint(m_pPointEnd);

}

/*

* CLine::RaiseException

*

* Purpose:

* Fills the EXCEPINFO structure and signal IDispatch::Invoke to return DISP_E_EXCEPTION.

* Sets ErrorInfo object for vtable-binding controllers.

*

*/

STDMETHODIMP

CLine::RaiseException(int nID)

{

extern SCODE g_scodes[];

TCHAR szError[STR_LEN];

ICreateErrorInfo *pcerrinfo;

IErrorInfo *perrinfo;

HRESULT hr;

_fmemset(&m_excepinfo, 0, sizeof(EXCEPINFO));

m_excepinfo.wCode = nID;

if (LoadString(g_pApplication->m_hinst, nID, szError, sizeof(szError)))

m_excepinfo.bstrDescription = SysAllocString(TO_OLE_STRING(szError));

m_excepinfo.bstrSource = SysAllocString(g_pApplication->m_bstrProgID);

m_bRaiseException = TRUE;

// Set ErrInfo object so that vtable binding containers can get

// rich error information.

hr = CreateErrorInfo(&pcerrinfo);

if (SUCCEEDED(hr))

{

pcerrinfo->SetGUID(IID_ILine);

if (m_excepinfo.bstrSource)

pcerrinfo->SetSource(m_excepinfo.bstrSource);

if (m_excepinfo.bstrDescription)

pcerrinfo->SetDescription(m_excepinfo.bstrDescription);

hr = pcerrinfo->QueryInterface(IID_IErrorInfo, (LPVOID FAR*) &perrinfo);

if (SUCCEEDED(hr))

{

SetErrorInfo(0, perrinfo);

perrinfo->Release();

}

pcerrinfo->Release();

}

return ResultFromScode(g_scodes[nID-1001]);

}

Software for developers
Delphi Components
.Net Components
Software for Android Developers
More information resources
MegaDetailed.Net
Unix Manual Pages
Delphi Examples