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
- Databases for Amazon shops developers
-
Amazon Categories Database
Browse Nodes Database