home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / oleaut / lines / app.cpp next >
C/C++ Source or Header  |  1997-07-31  |  15KB  |  583 lines

  1. /*************************************************************************
  2. **
  3. **  This is a part of the Microsoft Source Code Samples.
  4. **
  5. **  Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
  6. **
  7. **  This source code is only intended as a supplement to Microsoft Development
  8. **  Tools and/or WinHelp documentation.  See these sources for detailed
  9. **  information regarding the Microsoft samples programs.
  10. **
  11. **  OLE Automation Lines Object.
  12. **
  13. **  app.cpp
  14. **
  15. **  CApplication implementation
  16. **
  17. **  Written by Microsoft Product Support Services, Windows Developer Support
  18. **
  19. *************************************************************************/
  20.  
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #ifdef WIN16   
  24.   #include <ole2.h>
  25.   #include <compobj.h>    
  26.   #include <dispatch.h> 
  27.   #include <variant.h>
  28.   #include <olenls.h>  
  29. #endif 
  30. #include "lines.h"  
  31.  
  32. /*
  33.  * CApplication::Create
  34.  *
  35.  * Purpose:
  36.  *  Creates an instance of the Application automation object and initializes it.
  37.  *
  38.  * Parameters:       
  39.  *  hinst            HINSTANCE of application.
  40.  *  ppApplication    Returns Application automation object.
  41.  *
  42.  * Return Value:
  43.  *  HRESULT
  44.  *
  45.  */
  46. HRESULT
  47. CApplication::Create(HINSTANCE hinst, CApplication FAR* FAR* ppApplication ) 
  48. {   
  49.     TCHAR ach[STR_LEN];   
  50.     TCHAR achFullName[260];
  51.     HRESULT hr;
  52.     CApplication FAR* pApplication = NULL;  
  53.     HWND hwnd;
  54.      
  55.     *ppApplication = NULL;
  56.     
  57.     // Create application object.
  58.     pApplication = new CApplication();
  59.     if (pApplication == NULL)
  60.     {
  61.         hr = E_OUTOFMEMORY; 
  62.         goto error;
  63.     }
  64.     
  65.     LoadString(hinst, IDS_Name, ach, sizeof(ach));
  66.     hwnd = CreateWindow(TEXT("MainWndClass"), ach,
  67.                        WS_OVERLAPPEDWINDOW,
  68.                        CW_USEDEFAULT, CW_USEDEFAULT,
  69.                        650, 650,
  70.                        NULL, NULL, hinst, NULL);
  71.     if (!hwnd)
  72.     {
  73.        hr = E_OUTOFMEMORY;  
  74.        goto error;
  75.     }  
  76.     pApplication->m_hwnd = hwnd;
  77.     pApplication->m_hinst = hinst;
  78.     
  79.     // Set name and fullname of application.  
  80.     pApplication->m_bstrName = SysAllocString(TO_OLE_STRING(ach));
  81.     if (NULL == pApplication->m_bstrName)
  82.     {
  83.         hr = E_OUTOFMEMORY;    
  84.         goto error;
  85.     } 
  86.     GetModuleFileName(hinst, achFullName, sizeof(achFullName));
  87.     pApplication->m_bstrFullName = SysAllocString(TO_OLE_STRING(achFullName));
  88.     if (NULL == pApplication->m_bstrFullName)
  89.     {
  90.         hr = E_OUTOFMEMORY;    
  91.         goto error;
  92.     }
  93.     // ProgID 
  94.     LoadString(hinst, IDS_ProgID, ach, sizeof(ach));  
  95.     pApplication->m_bstrProgID = SysAllocString(TO_OLE_STRING(ach));
  96.     if (NULL == pApplication->m_bstrProgID)
  97.     {
  98.         hr = E_OUTOFMEMORY;    
  99.         goto error;
  100.     }      
  101.     
  102.     // Load type information for the application object from type library.
  103.     // If required, notify user on failure. 
  104.     hr = LoadTypeInfo(&pApplication->m_ptinfo, IID_IApplication);
  105.     if (FAILED(hr)) 
  106.     {       
  107.         LoadString(hinst, IDS_ErrorLoadingTypeLib, ach, sizeof(ach));
  108.         MessageBox(NULL, ach, FROM_OLE_STRING(pApplication->m_bstrName), MB_OK);
  109.         goto error;
  110.     }
  111.         
  112.     // Create Pane    
  113.     hr = CPane::Create(hwnd, &pApplication->m_pPane);
  114.     if (FAILED(hr))
  115.        goto error;    
  116.     pApplication->m_pPane->AddRef();    
  117.  
  118.     *ppApplication = pApplication;
  119.     return NOERROR;
  120.     
  121. error:                        
  122.     if (pApplication == NULL)
  123.         return E_OUTOFMEMORY; 
  124.     
  125.     if (pApplication->m_bstrFullName)
  126.         SysFreeString(pApplication->m_bstrFullName);  
  127.     if (pApplication->m_bstrName)
  128.         SysFreeString(pApplication->m_bstrName);
  129.     if (pApplication->m_bstrProgID) 
  130.         SysFreeString(pApplication->m_bstrProgID);                       
  131.     if (pApplication->m_ptinfo)
  132.         pApplication->m_ptinfo->Release();        
  133.     if (pApplication->m_pPane)
  134.         pApplication->m_pPane->Release();
  135.     
  136.     // Set to NULL to prevent destructor from attempting to free again
  137.     pApplication->m_bstrFullName = NULL;
  138.     pApplication->m_bstrName = NULL;
  139.         pApplication->m_bstrProgID = NULL;
  140.     pApplication->m_ptinfo = NULL;
  141.     pApplication->m_pPane = NULL;
  142.     
  143.     delete pApplication;
  144.     return hr;
  145. }
  146.  
  147. /*
  148.  * CApplication::CApplication
  149.  *
  150.  * Purpose:
  151.  *  Constructor for CApplication object. Initializes members to NULL.
  152.  *
  153.  */
  154. #pragma warning (disable : 4355)
  155. CApplication::CApplication() : m_SupportErrorInfo(this, IID_IApplication)
  156. #pragma warning (default : 4355)
  157. {   
  158.     extern ULONG g_cObj;
  159.      
  160.     m_hwnd = NULL;
  161.     m_bstrFullName = NULL;
  162.     m_bstrName = NULL;
  163.     m_bstrProgID = NULL;
  164.     m_ptinfo = NULL;
  165.     m_pPane = NULL;
  166.     m_cRef = 0;   
  167.     m_bVisible = 0;
  168.     m_bUserClosing = FALSE;
  169. }
  170.  
  171. /*
  172.  * CApplication::~CApplication
  173.  *
  174.  * Purpose:
  175.  *  Destructor for CApplication object. Frees Application message BSTR and default
  176.  *  IDispatch implementation. Closes the aplication.
  177.  *
  178.  */
  179. CApplication::~CApplication()
  180.      extern ULONG g_cObj;
  181.      
  182.      if (m_bstrFullName) SysFreeString(m_bstrFullName);
  183.      if (m_bstrName) SysFreeString(m_bstrName);
  184.      if (m_bstrProgID) SysFreeString(m_bstrProgID);          
  185.      if (m_ptinfo) m_ptinfo->Release();  
  186.      if (m_pPane) m_pPane->Release();
  187.      if (!m_bUserClosing && IsWindow(m_hwnd)) DestroyWindow(m_hwnd);     
  188. }
  189.  
  190. /*
  191.  * CApplication::QueryInterface, AddRef, Release
  192.  *
  193.  * Purpose:
  194.  *  Implements IUnknown::QueryInterface, AddRef, Release
  195.  *
  196.  */
  197. STDMETHODIMP
  198. CApplication::QueryInterface(REFIID iid, void FAR* FAR* ppv) 
  199. {   
  200.     *ppv = NULL;
  201.     
  202.     if (iid == IID_IUnknown || iid == IID_IDispatch || iid == IID_IApplication)
  203.         *ppv = this; 
  204.     else if (iid == IID_ISupportErrorInfo)
  205.         *ppv = &m_SupportErrorInfo;
  206.     else return E_NOINTERFACE; 
  207.  
  208.     AddRef();
  209.     return NOERROR;    
  210. }
  211.  
  212.  
  213. STDMETHODIMP_(ULONG)
  214. CApplication::AddRef(void)
  215. {    
  216. #ifdef _DEBUG  
  217.     TCHAR ach[50];
  218.     wsprintf(ach, TEXT("Ref = %ld, App\r\n"), m_cRef+1); 
  219.     OutputDebugString(ach); 
  220. #endif  
  221.  
  222.     return ++m_cRef;
  223. }
  224.  
  225. STDMETHODIMP_(ULONG)
  226. CApplication::Release(void)
  227. {
  228. #ifdef _DEBUG  
  229.     TCHAR ach[50];
  230.     wsprintf(ach, TEXT("Ref = %ld, App\r\n"), m_cRef-1); 
  231.     OutputDebugString(ach);   
  232. #endif
  233.     
  234.     if(--m_cRef == 0)
  235.     {
  236.         delete this;
  237.         return 0;
  238.     }
  239.     return m_cRef;
  240. }
  241.  
  242. /*
  243.  * CApplication::GetTypeInfoCount
  244.  *
  245.  * Purpose:
  246.  *  Implements IDispatch::GetTypeInfoCount.
  247.  *
  248.  */
  249. STDMETHODIMP
  250. CApplication::GetTypeInfoCount(UINT FAR* pctinfo)
  251. {
  252.     *pctinfo = 1;
  253.     return NOERROR;
  254. }
  255.  
  256. /*
  257.  * CApplication::GetTypeInfo
  258.  *
  259.  * Purpose:
  260.  *  Implements IDispatch::GetTypeInfo. 
  261.  *
  262.  */
  263. STDMETHODIMP
  264. CApplication::GetTypeInfo(
  265.       UINT itinfo,
  266.       LCID lcid,
  267.       ITypeInfo FAR* FAR* pptinfo)
  268. {    
  269.     *pptinfo = NULL;
  270.      
  271.     if(itinfo != 0)
  272.         return DISP_E_BADINDEX;
  273.     
  274.     m_ptinfo->AddRef(); 
  275.     *pptinfo = m_ptinfo;
  276.     
  277.     return NOERROR;
  278. }
  279.  
  280. /*
  281.  * CApplication::GetIDsOfNames
  282.  *
  283.  * Purpose:
  284.  *  Implements IDispatch::GetIDsOfNames.  The standard implementation, DispGetIDsOfNames,
  285.  *  is used.
  286.  *
  287.  */
  288. STDMETHODIMP 
  289. CApplication::GetIDsOfNames(
  290.       REFIID riid,
  291.       OLECHAR FAR* FAR* rgszNames,
  292.       UINT cNames,
  293.       LCID lcid,
  294.       DISPID FAR* rgdispid)
  295. {
  296.     return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);
  297. }
  298.  
  299. /*
  300.  * CApplication::Invoke
  301.  *
  302.  * Purpose:
  303.  *  Implements IDispatch::Invoke.  The standard implementation, DispInvoke,
  304.  *  is used.
  305.  *
  306.  */
  307. STDMETHODIMP
  308. CApplication::Invoke(
  309.       DISPID dispidMember,
  310.       REFIID riid,
  311.       LCID lcid,
  312.       WORD wFlags,
  313.       DISPPARAMS FAR* pdispparams,
  314.       VARIANT FAR* pvarResult,
  315.       EXCEPINFO FAR* pexcepinfo,
  316.       UINT FAR* puArgErr)
  317. {  
  318.    return DispInvoke(
  319.         this, m_ptinfo,
  320.         dispidMember, wFlags, pdispparams,
  321.         pvarResult, pexcepinfo, puArgErr);   
  322. }
  323.  
  324. /*
  325.  * CApplication::get_Application, get_FullName, get_Name, get_Parent, get_Visible, put_Visible, Quit 
  326.  *
  327.  * Purpose:
  328.  *  Implements the standard Application, FullName, Name, Parent & Visible properties
  329.  *  and the Quit method. 
  330.  *
  331.  */
  332. STDMETHODIMP
  333. CApplication::get_Application(IApplication FAR* FAR* ppApplication)
  334. {
  335.     HRESULT hr;
  336.     
  337.     hr = QueryInterface(IID_IDispatch, (void FAR* FAR*)ppApplication); 
  338.     if (FAILED(hr))
  339.         return RaiseException(IDS_Unexpected, IID_IApplication); 
  340.     return NOERROR;
  341. }
  342.  
  343. STDMETHODIMP
  344. CApplication::get_FullName(BSTR FAR* pbstr)
  345. {
  346.     *pbstr = SysAllocString(m_bstrFullName);   
  347.     return NOERROR;
  348. }
  349.  
  350. STDMETHODIMP
  351. CApplication::get_Name(BSTR FAR* pbstr)
  352. {
  353.     *pbstr = SysAllocString(m_bstrName); 
  354.     return NOERROR; 
  355. }
  356.  
  357. STDMETHODIMP
  358. CApplication::get_Parent(IApplication FAR* FAR* ppApplication)      
  359. {
  360.     HRESULT hr;
  361.     
  362.     hr = QueryInterface(IID_IDispatch, (void FAR* FAR*)ppApplication); 
  363.     if (FAILED(hr))
  364.         return RaiseException(IDS_Unexpected, IID_IApplication); 
  365.     return NOERROR;
  366. }
  367.  
  368. STDMETHODIMP
  369. CApplication::put_Visible(VARIANT_BOOL bVisible)
  370. {
  371.     ShowWindow(bVisible ? SW_SHOW : SW_HIDE);  
  372.     return NOERROR;
  373.  
  374. STDMETHODIMP
  375. CApplication::get_Visible(VARIANT_BOOL FAR* pbVisible)
  376. {
  377.     *pbVisible = m_bVisible;     
  378.     return NOERROR;
  379. }
  380.  
  381. STDMETHODIMP
  382. CApplication::Quit()
  383. {
  384.     // CoDisconnectObject has no effect for an inproc server.  So the controller
  385.     // will GP fault if it attempts to access the object (including calling IUnknown::Release())
  386.     // after Quit has been called. For a local server, CoDisconnectObject will disconnect
  387.     // the object from external connections. So the controller will get an RPC error if
  388.     // it access the object after calling Quit. The controller will not GP fault in this case. 
  389.     CoDisconnectObject((LPUNKNOWN)this, 0);  
  390.     PostMessage(m_hwnd, WM_CLOSE, 0, 0L);
  391.     return NOERROR;                                     
  392.  
  393. /*
  394.  * CApplication::get_Pane
  395.  *
  396.  * Purpose:
  397.  *  Returns pane object.
  398.  *
  399.  */      
  400. STDMETHODIMP
  401. CApplication::get_Pane(IPane FAR* FAR* ppPane)
  402. {
  403.     HRESULT hr;
  404.     
  405.     hr = m_pPane->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPane); 
  406.     if (FAILED(hr))
  407.         return RaiseException(IDS_Unexpected, IID_IApplication); 
  408.     return NOERROR;
  409. }
  410.  
  411. /*
  412.  * CApplication::CreateLine
  413.  *
  414.  * Purpose:
  415.  *  Returns a newly created line object with no start or end point.
  416.  *
  417.  */  
  418. STDMETHODIMP
  419. CApplication::CreateLine(ILine FAR* FAR* ppLine)
  420. {
  421.     CLine FAR* pline = NULL;
  422.     HRESULT hr;
  423.     
  424.     // Create new item and QI for IDispatch   
  425.     hr = CLine::Create(&pline);
  426.     if (FAILED(hr)) 
  427.         {hr = RaiseException(IDS_OutOfMemory, IID_IApplication); goto error;} 
  428.               
  429.     hr = pline->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppLine); 
  430.     if (FAILED(hr)) 
  431.         {hr = RaiseException(IDS_Unexpected, IID_IApplication); goto error;}
  432.     return NOERROR;
  433.     
  434. error: 
  435.     if (pline)
  436.         delete pline;       
  437.     return hr;     
  438. }
  439.  
  440. /*
  441.  * CApplication::CreateLine
  442.  *
  443.  * Purpose:
  444.  *  Returns a newly created point object intialized to (0,0).
  445.  *
  446.  */ 
  447. STDMETHODIMP
  448. CApplication::CreatePoint(IPoint FAR* FAR* ppPoint)
  449. {
  450.     CPoint FAR* ppoint = NULL;
  451.     HRESULT hr;
  452.     
  453.     // Create new item and QI for IDispatch   
  454.     hr = CPoint::Create(&ppoint);
  455.     if (FAILED(hr))
  456.         {hr = RaiseException(IDS_OutOfMemory, IID_IApplication); goto error;}          
  457.         
  458.     hr = ppoint->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoint); 
  459.     if (FAILED(hr))
  460.         {hr = RaiseException(IDS_Unexpected, IID_IApplication); goto error;}
  461.     return NOERROR;
  462.     
  463. error: 
  464.     if (ppoint)
  465.         delete ppoint;        
  466.     return hr;     
  467. }   
  468.  
  469. /* 
  470.  *
  471.  * The following methods are not exposed through Automation
  472.  *
  473.  */
  474.  
  475. STDMETHODIMP_(void)
  476. CApplication::Draw()
  477. {
  478.    m_pPane->Draw();
  479. }
  480.  
  481. /*
  482.  * CApplication::OnSize
  483.  *
  484.  * Purpose:
  485.  *  Called when application window receives WM_SIZE.
  486.  *
  487.  */ 
  488. STDMETHODIMP_(void)
  489. CApplication::OnSize(unsigned int nWidth, unsigned int nHeight) 
  490. {
  491.    m_pPane->OnSize(nWidth, nHeight);
  492.  
  493. STDMETHODIMP_(void)
  494. CApplication::ShowWindow(int nCmdShow)
  495. {   
  496.     // Return if curently hidden and asked to hide or currently visible
  497.     // and asked to show.
  498.     if ((!m_bVisible && nCmdShow == SW_HIDE) || (m_bVisible && nCmdShow != SW_HIDE))
  499.         return; 
  500.     
  501.     m_bVisible = (nCmdShow == SW_HIDE) ? FALSE : TRUE;
  502.     
  503.     // The Automation object shutdown behavior is as follows:
  504.     // 1. If the object application is visible, it shuts down only in response to an
  505.     // explicit user command (File/Exit) or it's programmatic equivalent (for example
  506.     // the Quit method of the Application object).
  507.     // 2. If the object application is not visible, it goes away when it's last
  508.     // object is released.   
  509.     //   
  510.     // CoLockObjectExternal can be used to increment the ref count of the application object
  511.     // when it is visible. This will implement shutdown behavior 1. When the application
  512.     // goes invisible, CoLockObjectExternal is used to decrement the ref count. This will
  513.     // implement shutdown behavior 2.
  514.     
  515.     if (m_bVisible)
  516.         CoLockObjectExternal(this, TRUE /*fLock*/, TRUE/*ignored when fLock==TRUE*/);
  517.     else CoLockObjectExternal(this, FALSE/*fLock*/, TRUE/*fLastLockReleases*/);  
  518.     ::ShowWindow (m_hwnd, nCmdShow);
  519. }
  520.  
  521. STDMETHODIMP_(void)
  522. CApplication::CreateAndDrawLine()
  523. {   
  524.     LINEINFO lineinfo;
  525.     CLine FAR* pLine = NULL;
  526.     CPoint FAR* pPointStart = NULL;
  527.     CPoint FAR* pPointEnd = NULL; 
  528.     ILines FAR* pLines = NULL; 
  529.     int nRet;     
  530.     HRESULT hr;
  531.                   
  532.     nRet = DialogBoxParam(m_hinst, MAKEINTRESOURCE(IDD_DRAWLINE), m_hwnd, 
  533.                       (DLGPROC)DrawLineDialogFunc, (LPARAM)(LPLINEINFO)&lineinfo);    
  534.     if (nRet != IDOK) 
  535.         return;
  536.     hr = CLine::Create(&pLine);
  537.     if (FAILED(hr))  
  538.         goto error;
  539.     hr = CPoint::Create(&pPointStart);
  540.     if (FAILED(hr)) 
  541.         goto error; 
  542.     hr = CPoint::Create(&pPointEnd);
  543.     if (FAILED(hr))
  544.         goto error;
  545.  
  546.     pPointStart->put_x(lineinfo.ptStart.x);
  547.     pPointStart->put_y(lineinfo.ptStart.y); 
  548.     pPointEnd->put_x(lineinfo.ptEnd.x);
  549.     pPointEnd->put_y(lineinfo.ptEnd.y);   
  550.  
  551.     pLine->putref_StartPoint(pPointStart);  
  552.     pLine->putref_EndPoint(pPointEnd);  
  553.     pLine->put_Thickness(lineinfo.nThickness);
  554.     pLine->put_Color(lineinfo.colorref);
  555.     
  556.     hr = m_pPane->get_Lines(&pLines); 
  557.     if (FAILED(hr)) 
  558.         goto error; 
  559.     hr = pLines->Add(pLine); 
  560.     if (FAILED(hr)) 
  561.         goto error;  
  562.     pLines->Release();
  563.     return;
  564.  
  565. error:
  566.     if (pLine) delete pLine;
  567.     if (pPointStart) delete pPointStart;
  568.     if (pPointEnd) delete pPointEnd; 
  569.     if (pLines) pLines->Release();   
  570.     MessageBox(m_hwnd, TEXT("Cannot create Line"), FROM_OLE_STRING(m_bstrName), MB_OK);
  571. }
  572.  
  573. STDMETHODIMP_(void)
  574. CApplication::ClearPane()  
  575. {
  576.     m_pPane->Clear();
  577. }  
  578.  
  579.