APP.CPP (LINES OLE Sample)

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

  • OLE Automation Lines Object.

  • app.cpp

  • CApplication 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"

/*

* CApplication::Create

*

* Purpose:

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

*

* Parameters:

* hinst HINSTANCE of application.

* ppApplication Returns Application automation object.

*

* Return Value:

* HRESULT

*

*/

HRESULT

CApplication::Create(HINSTANCE hinst, CApplication FAR* FAR* ppApplication )

{

TCHAR ach[STR_LEN];

TCHAR achFullName[260];

HRESULT hr;

CApplication FAR* pApplication = NULL;

HWND hwnd;

*ppApplication = NULL;

// Create application object.

pApplication = new CApplication();

if (pApplication == NULL)

{

hr = ResultFromScode(E_OUTOFMEMORY);

goto error;

}

LoadString(hinst, IDS_Name, ach, sizeof(ach));

hwnd = CreateWindow(TEXT("MainWndClass"), ach,

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

650, 650,

NULL, NULL, hinst, NULL);

if (!hwnd)

{

hr = ResultFromScode(E_OUTOFMEMORY);

goto error;

}

pApplication->m_hwnd = hwnd;

pApplication->m_hinst = hinst;

// Set name and fullname of application.

pApplication->m_bstrName = SysAllocString(TO_OLE_STRING(ach));

if (NULL == pApplication->m_bstrName)

{

hr = ResultFromScode(E_OUTOFMEMORY);

goto error;

}

GetModuleFileName(hinst, achFullName, sizeof(achFullName));

pApplication->m_bstrFullName = SysAllocString(TO_OLE_STRING(achFullName));

if (NULL == pApplication->m_bstrFullName)

{

hr = ResultFromScode(E_OUTOFMEMORY);

goto error;

}

// ProgID

LoadString(hinst, IDS_ProgID, ach, sizeof(ach));

pApplication->m_bstrProgID = SysAllocString(TO_OLE_STRING(ach));

if (NULL == pApplication->m_bstrProgID)

{

hr = ResultFromScode(E_OUTOFMEMORY);

goto error;

}

// Load type information for the application object from type library.

// If required, notify user on failure.

hr = LoadTypeInfo(&pApplication->m_ptinfo, IID_IApplication);

if (FAILED(hr))

{

LoadString(hinst, IDS_ErrorLoadingTypeLib, ach, sizeof(ach));

MessageBox(NULL, ach, FROM_OLE_STRING(pApplication->m_bstrName), MB_OK);

goto error;

}

// Create Pane

hr = CPane::Create(hwnd, &pApplication->m_pPane);

if (FAILED(hr))

goto error;

pApplication->m_pPane->AddRef();

*ppApplication = pApplication;

return NOERROR;

error:

if (pApplication == NULL)

return ResultFromScode(E_OUTOFMEMORY);

if (pApplication->m_bstrFullName)

SysFreeString(pApplication->m_bstrFullName);

if (pApplication->m_bstrName)

SysFreeString(pApplication->m_bstrName);

if (pApplication->m_bstrProgID)

SysFreeString(pApplication->m_bstrProgID);

if (pApplication->m_ptinfo)

pApplication->m_ptinfo->Release();

if (pApplication->m_pPane)

pApplication->m_pPane->Release();

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

pApplication->m_bstrFullName = NULL;

pApplication->m_bstrName = NULL;

pApplication->m_bstrProgID = NULL;

pApplication->m_ptinfo = NULL;

pApplication->m_pPane = NULL;

delete pApplication;

return hr;

}

/*

* CApplication::CApplication

*

* Purpose:

* Constructor for CApplication object. Initializes members to NULL.

*

*/

#pragma warning (disable : 4355)

CApplication::CApplication() : m_SupportErrorInfo(this, IID_IApplication)

#pragma warning (default : 4355)

{

extern ULONG g_cObj;

m_hwnd = NULL;

m_bstrFullName = NULL;

m_bstrName = NULL;

m_bstrProgID = NULL;

m_ptinfo = NULL;

m_pPane = NULL;

m_cRef = 0;

m_bVisible = 0;

m_bUserClosing = FALSE;

}

/*

* CApplication::~CApplication

*

* Purpose:

* Destructor for CApplication object. Frees Application message BSTR and default

* IDispatch implementation. Closes the aplication.

*

*/

CApplication::~CApplication()

{

extern ULONG g_cObj;

if (m_bstrFullName) SysFreeString(m_bstrFullName);

if (m_bstrName) SysFreeString(m_bstrName);

if (m_bstrProgID) SysFreeString(m_bstrProgID);

if (m_ptinfo) m_ptinfo->Release();

if (m_pPane) m_pPane->Release();

if (!m_bUserClosing && IsWindow(m_hwnd)) DestroyWindow(m_hwnd);

}

/*

* CApplication::QueryInterface, AddRef, Release

*

* Purpose:

* Implements IUnknown::QueryInterface, AddRef, Release

*

*/

STDMETHODIMP

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

{

*ppv = NULL;

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

*ppv = this;

else if (iid == IID_ISupportErrorInfo)

*ppv = &m_SupportErrorInfo;

else return ResultFromScode(E_NOINTERFACE);

AddRef();

return NOERROR;

}

STDMETHODIMP_(ULONG)

CApplication::AddRef(void)

{

#ifdef _DEBUG

TCHAR ach[50];

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

OutputDebugString(ach);

#endif

return ++m_cRef;

}

STDMETHODIMP_(ULONG)

CApplication::Release(void)

{

#ifdef _DEBUG

TCHAR ach[50];

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

OutputDebugString(ach);

#endif

if(--m_cRef == 0)

{

delete this;

return 0;

}

return m_cRef;

}

/*

* CApplication::GetTypeInfoCount

*

* Purpose:

* Implements IDispatch::GetTypeInfoCount.

*

*/

STDMETHODIMP

CApplication::GetTypeInfoCount(UINT FAR* pctinfo)

{

*pctinfo = 1;

return NOERROR;

}

/*

* CApplication::GetTypeInfo

*

* Purpose:

* Implements IDispatch::GetTypeInfo.

*

*/

STDMETHODIMP

CApplication::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;

}

/*

* CApplication::GetIDsOfNames

*

* Purpose:

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

* is used.

*

*/

STDMETHODIMP

CApplication::GetIDsOfNames(

REFIID riid,

OLECHAR FAR* FAR* rgszNames,

UINT cNames,

LCID lcid,

DISPID FAR* rgdispid)

{

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

}

/*

* CApplication::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

CApplication::Invoke(

DISPID dispidMember,

REFIID riid,

LCID lcid,

WORD wFlags,

DISPPARAMS FAR* pdispparams,

VARIANT FAR* pvarResult,

EXCEPINFO FAR* pexcepinfo,

UINT FAR* puArgErr)

{

HRESULT hr;

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;

}

/*

* CApplication::get_Application, get_FullName, get_Name, get_Parent, get_Visible, put_Visible, Quit

*

* Purpose:

* Implements the standard Application, FullName, Name, Parent & Visible properties

* and the Quit method.

*

*/

STDMETHODIMP

CApplication::get_Application(IApplication FAR* FAR* ppApplication)

{

HRESULT hr;

hr = QueryInterface(IID_IDispatch, (void FAR* FAR*)ppApplication);

if (FAILED(hr))

return RaiseException(IDS_Unexpected);

return NOERROR;

}

STDMETHODIMP

CApplication::get_FullName(BSTR FAR* pbstr)

{

*pbstr = SysAllocString(m_bstrFullName);

return NOERROR;

}

STDMETHODIMP

CApplication::get_Name(BSTR FAR* pbstr)

{

*pbstr = SysAllocString(m_bstrName);

return NOERROR;

}

STDMETHODIMP

CApplication::get_Parent(IApplication FAR* FAR* ppApplication)

{

HRESULT hr;

hr = QueryInterface(IID_IDispatch, (void FAR* FAR*)ppApplication);

if (FAILED(hr))

return RaiseException(IDS_Unexpected);

return NOERROR;

}

STDMETHODIMP

CApplication::put_Visible(VARIANT_BOOL bVisible)

{

ShowWindow(bVisible ? SW_SHOW : SW_HIDE);

return NOERROR;

}

STDMETHODIMP

CApplication::get_Visible(VARIANT_BOOL FAR* pbVisible)

{

*pbVisible = m_bVisible;

return NOERROR;

}

STDMETHODIMP

CApplication::Quit()

{

// CoDisconnectObject has no effect for an inproc server. So the controller

// will GP fault if it attempts to access the object (including calling IUnknown::Release())

// after Quit has been called. For a local server, CoDisconnectObject will disconnect

// the object from external connections. So the controller will get an RPC error if

// it access the object after calling Quit. The controller will not GP fault in this case.

CoDisconnectObject((LPUNKNOWN)this, 0);

PostMessage(m_hwnd, WM_CLOSE, 0, 0L);

return NOERROR;

}

/*

* CApplication::get_Pane

*

* Purpose:

* Returns pane object.

*

*/

STDMETHODIMP

CApplication::get_Pane(IPane FAR* FAR* ppPane)

{

HRESULT hr;

hr = m_pPane->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPane);

if (FAILED(hr))

return RaiseException(IDS_Unexpected);

return NOERROR;

}

/*

* CApplication::CreateLine

*

* Purpose:

* Returns a newly created line object with no start or end point.

*

*/

STDMETHODIMP

CApplication::CreateLine(ILine FAR* FAR* ppLine)

{

CLine FAR* pline = NULL;

HRESULT hr;

// Create new item and QI for IDispatch

hr = CLine::Create(&pline);

if (FAILED(hr))

{hr = RaiseException(IDS_OutOfMemory); goto error;}

hr = pline->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppLine);

if (FAILED(hr))

{hr = RaiseException(IDS_Unexpected); goto error;}

return NOERROR;

error:

if (pline)

delete pline;

return hr;

}

/*

* CApplication::CreateLine

*

* Purpose:

* Returns a newly created point object intialized to (0,0).

*

*/

STDMETHODIMP

CApplication::CreatePoint(IPoint FAR* FAR* ppPoint)

{

CPoint FAR* ppoint = NULL;

HRESULT hr;

// Create new item and QI for IDispatch

hr = CPoint::Create(&ppoint);

if (FAILED(hr))

{hr = RaiseException(IDS_OutOfMemory); goto error;}

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

if (FAILED(hr))

{hr = RaiseException(IDS_Unexpected); goto error;}

return NOERROR;

error:

if (ppoint)

delete ppoint;

return hr;

}

/*

*

* The following methods are not exposed through Automation

*

*/

STDMETHODIMP_(void)

CApplication::Draw()

{

m_pPane->Draw();

}

/*

* CApplication::OnSize

*

* Purpose:

* Called when application window receives WM_SIZE.

*

*/

STDMETHODIMP_(void)

CApplication::OnSize(unsigned int nWidth, unsigned int nHeight)

{

m_pPane->OnSize(nWidth, nHeight);

}

STDMETHODIMP_(void)

CApplication::ShowWindow(int nCmdShow)

{

// Return if curently hidden and asked to hide or currently visible

// and asked to show.

if ((!m_bVisible && nCmdShow == SW_HIDE) || (m_bVisible && nCmdShow != SW_HIDE))

return;

m_bVisible = (nCmdShow == SW_HIDE) ? FALSE : TRUE;

// The Automation object shutdown behavior is as follows:

// 1. If the object application is visible, it shuts down only in response to an

// explicit user command (File/Exit) or it's programmatic equivalent (for example

// the Quit method of the Application object).

// 2. If the object application is not visible, it goes away when it's last

// object is released.

//

// CoLockObjectExternal can be used to increment the ref count of the application object

// when it is visible. This will implement shutdown behavior 1. When the application

// goes invisible, CoLockObjectExternal is used to decrement the ref count. This will

// implement shutdown behavior 2.

if (m_bVisible)

CoLockObjectExternal(this, TRUE /*fLock*/, TRUE/*ignored when fLock==TRUE*/);

else CoLockObjectExternal(this, FALSE/*fLock*/, TRUE/*fLastLockReleases*/);

::ShowWindow (m_hwnd, nCmdShow);

}

STDMETHODIMP_(void)

CApplication::CreateAndDrawLine()

{

LINEINFO lineinfo;

CLine FAR* pLine = NULL;

CPoint FAR* pPointStart = NULL;

CPoint FAR* pPointEnd = NULL;

ILines FAR* pLines = NULL;

int nRet;

HRESULT hr;

nRet = DialogBoxParam(m_hinst, MAKEINTRESOURCE(IDD_DRAWLINE), m_hwnd,

(DLGPROC)DrawLineDialogFunc, (LPARAM)(LPLINEINFO)&lineinfo);

if (nRet != IDOK)

return;

hr = CLine::Create(&pLine);

if (FAILED(hr))

goto error;

hr = CPoint::Create(&pPointStart);

if (FAILED(hr))

goto error;

hr = CPoint::Create(&pPointEnd);

if (FAILED(hr))

goto error;

pPointStart->put_x(lineinfo.ptStart.x);

pPointStart->put_y(lineinfo.ptStart.y);

pPointEnd->put_x(lineinfo.ptEnd.x);

pPointEnd->put_y(lineinfo.ptEnd.y);

pLine->putref_StartPoint(pPointStart);

pLine->putref_EndPoint(pPointEnd);

pLine->put_Thickness(lineinfo.nThickness);

pLine->put_Color(lineinfo.colorref);

hr = m_pPane->get_Lines(&pLines);

if (FAILED(hr))

goto error;

hr = pLines->Add(pLine);

if (FAILED(hr))

goto error;

pLines->Release();

return;

error:

if (pLine) delete pLine;

if (pPointStart) delete pPointStart;

if (pPointEnd) delete pPointEnd;

if (pLines) pLines->Release();

MessageBox(m_hwnd, TEXT("Cannot create Line"), m_bstrName, MB_OK);

}

STDMETHODIMP_(void)

CApplication::ClearPane()

{

m_pPane->Clear();

}

/*

* CApplication::RaiseException

*

* Purpose:

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

* Sets ErrorInfo object for vtable-binding controllers.

*

*/

STDMETHODIMP

CApplication::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(m_hinst, nID, szError, sizeof(szError)))

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

m_excepinfo.bstrSource = SysAllocString(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_IApplication);

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