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 / pane.cpp < prev    next >
C/C++ Source or Header  |  1997-07-31  |  11KB  |  510 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. **  pane.cpp
  14. **
  15. **  CPane 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.  * CPane::Create
  34.  *
  35.  * Purpose:
  36.  *  Creates an instance of the Pane automation object and initializes it.
  37.  *
  38.  * Parameters:  
  39.  *  hwnd      Handle of the window of the pane.
  40.  *  ppPane    Returns Pane automation object.
  41.  *
  42.  * Return Value:
  43.  *  HRESULT
  44.  *
  45.  */
  46. HRESULT 
  47. CPane::Create(HWND hwnd, CPane FAR* FAR* ppPane ) 
  48. {   
  49.     HRESULT hr;
  50.     CPane FAR* pPane = NULL;
  51.      
  52.     *ppPane = NULL;
  53.     
  54.     pPane = new CPane();
  55.     if (pPane == NULL)
  56.         goto error;
  57.         
  58.     pPane->m_hwnd = hwnd;        
  59.     
  60.     // Create an empty Lines collection of size 100
  61.     hr = CLines::Create(100, 1, pPane, &pPane->m_pLines);    
  62.     if (FAILED(hr))
  63.        goto error;    
  64.     pPane->m_pLines->AddRef();  
  65.     
  66.     // Create an empty Points collection of size 200   
  67.     hr = CPoints::Create(200, 1, pPane, &pPane->m_pPoints);  
  68.     if (FAILED(hr))
  69.        goto error;      
  70.     pPane->m_pPoints->AddRef(); 
  71.     
  72.     // Load type information for the pane object from type library. 
  73.     hr = LoadTypeInfo(&pPane->m_ptinfo, IID_IPane);
  74.     if (FAILED(hr))
  75.         goto error;
  76.  
  77.     *ppPane = pPane;
  78.     return NOERROR;
  79.     
  80. error:                        
  81.     if (pPane == NULL)
  82.         return E_OUTOFMEMORY; 
  83.                     
  84.     if (pPane->m_ptinfo)
  85.         pPane->m_ptinfo->Release();        
  86.     if (pPane->m_pLines)
  87.         pPane->m_pLines->Release();
  88.     if (pPane->m_pPoints)
  89.         pPane->m_pPoints->Release();
  90.     
  91.     // Set to NULL to prevent destructor from attempting to free again
  92.     pPane->m_ptinfo = NULL; 
  93.     pPane->m_pLines = NULL;
  94.     pPane->m_pPoints = NULL;
  95.     
  96.     delete pPane;
  97.     return hr;
  98. }
  99.  
  100. /*
  101.  * CPane::CPane
  102.  *
  103.  * Purpose:
  104.  *  Constructor for CPane object. Initializes members to NULL.
  105.  *
  106.  */
  107. #pragma warning (disable : 4355)
  108. CPane::CPane() : m_SupportErrorInfo(this, IID_IPane)
  109. #pragma warning (default : 4355)
  110. {   
  111.     m_cRef = 0;
  112.     m_hwnd = NULL;
  113.     m_ptinfo = NULL;  
  114.     m_pLines = NULL;
  115.     m_pPoints = NULL;  
  116.     m_nMaxX = -1;
  117.     m_nMaxY = -1;
  118. }
  119.  
  120. /*
  121.  * CPane::~CPane
  122.  *
  123.  * Purpose:
  124.  *  Destructor for CPane object. 
  125.  *
  126.  */
  127. CPane::~CPane()
  128. {            
  129.      if (m_ptinfo) m_ptinfo->Release(); 
  130.      if (m_pLines) m_pLines->Release();
  131.      if (m_pPoints) m_pPoints->Release(); 
  132. }
  133.  
  134. /*
  135.  * CPane::QueryInterface, AddRef, Release
  136.  *
  137.  * Purpose:
  138.  *  Implements IUnknown::QueryInterface, AddRef, Release
  139.  *
  140.  */
  141. STDMETHODIMP
  142. CPane::QueryInterface(REFIID iid, void FAR* FAR* ppv) 
  143. {   
  144.     *ppv = NULL;
  145.     
  146.     if (iid == IID_IUnknown || iid == IID_IDispatch || iid == IID_IPane)
  147.         *ppv = this; 
  148.     else if (iid == IID_ISupportErrorInfo)
  149.         *ppv = &m_SupportErrorInfo;
  150.     else return E_NOINTERFACE; 
  151.  
  152.     AddRef();
  153.     return NOERROR;    
  154. }
  155.  
  156.  
  157. STDMETHODIMP_(ULONG)
  158. CPane::AddRef(void)
  159. {   
  160. #ifdef _DEBUG  
  161.     TCHAR ach[50];
  162.     wsprintf(ach, TEXT("Ref = %ld, Pane\r\n"), m_cRef+1); 
  163.     OutputDebugString(ach); 
  164. #endif    
  165.  
  166.     return ++m_cRef;
  167. }
  168.  
  169. STDMETHODIMP_(ULONG)
  170. CPane::Release(void)
  171. {  
  172. #ifdef _DEBUG  
  173.     TCHAR ach[50];
  174.     wsprintf(ach, TEXT("Ref = %ld, Pane\r\n"), m_cRef-1); 
  175.     OutputDebugString(ach);   
  176. #endif
  177.   
  178.     if(--m_cRef == 0)
  179.     {
  180.         delete this;
  181.         return 0;
  182.     }
  183.     return m_cRef;
  184. }
  185.  
  186. /*
  187.  * CPane::GetTypeInfoCount
  188.  *
  189.  * Purpose:
  190.  *  Implements IDispatch::GetTypeInfoCount.
  191.  *
  192.  */
  193. STDMETHODIMP
  194. CPane::GetTypeInfoCount(UINT FAR* pctinfo)
  195. {
  196.     *pctinfo = 1;
  197.     return NOERROR;
  198. }
  199.  
  200. /*
  201.  * CPane::GetTypeInfo
  202.  *
  203.  * Purpose:
  204.  *  Implements IDispatch::GetTypeInfo. 
  205.  *
  206.  */
  207. STDMETHODIMP
  208. CPane::GetTypeInfo(
  209.       UINT itinfo,
  210.       LCID lcid,
  211.       ITypeInfo FAR* FAR* pptinfo)
  212. {    
  213.     *pptinfo = NULL;
  214.      
  215.     if(itinfo != 0)
  216.         return DISP_E_BADINDEX;
  217.     
  218.     m_ptinfo->AddRef(); 
  219.     *pptinfo = m_ptinfo;
  220.     
  221.     return NOERROR;
  222. }
  223.  
  224. /*
  225.  * CPane::GetIDsOfNames
  226.  *
  227.  * Purpose:
  228.  *  Implements IDispatch::GetIDsOfNames.  The standard implementation, DispGetIDsOfNames,
  229.  *  is used.
  230.  *
  231.  */
  232. STDMETHODIMP 
  233. CPane::GetIDsOfNames(
  234.       REFIID riid,
  235.       OLECHAR FAR* FAR* rgszNames,
  236.       UINT cNames,
  237.       LCID lcid,
  238.       DISPID FAR* rgdispid)
  239. {
  240.     return DispGetIDsOfNames(m_ptinfo, rgszNames, cNames, rgdispid);
  241. }
  242.  
  243. /*
  244.  * CPane::Invoke
  245.  *
  246.  * Purpose:
  247.  *  Implements IDispatch::Invoke.  The standard implementation, DispInvoke,
  248.  *  is used.
  249.  *
  250.  */
  251. STDMETHODIMP
  252. CPane::Invoke(
  253.       DISPID dispidMember,
  254.       REFIID riid,
  255.       LCID lcid,
  256.       WORD wFlags,
  257.       DISPPARAMS FAR* pdispparams,
  258.       VARIANT FAR* pvarResult,
  259.       EXCEPINFO FAR* pexcepinfo,
  260.       UINT FAR* puArgErr)
  261. {        
  262.     return DispInvoke(
  263.         this, m_ptinfo,
  264.         dispidMember, wFlags, pdispparams,
  265.         pvarResult, pexcepinfo, puArgErr); 
  266. }
  267.  
  268. /*
  269.  * CPane::get_Lines
  270.  *
  271.  * Purpose:
  272.  *  Returns the collection of all line objects in the drawing.
  273.  *
  274.  */
  275. STDMETHODIMP
  276. CPane::get_Lines(ILines FAR* FAR* ppLines)
  277. {
  278.     HRESULT hr;
  279.     
  280.     hr = m_pLines->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppLines); 
  281.     if (FAILED(hr))
  282.         return RaiseException(IDS_Unexpected, IID_IPane); 
  283.     return NOERROR;
  284. }
  285.  
  286. /*
  287.  * CPane::get_Points
  288.  *
  289.  * Purpose:
  290.  *  Returns the collection of all point objects in the drawing.
  291.  *
  292.  */
  293. STDMETHODIMP
  294. CPane::get_Points(IPoints FAR* FAR* ppPoints)
  295. {
  296.     HRESULT hr;
  297.     
  298.     hr = m_pPoints->QueryInterface(IID_IDispatch, (void FAR* FAR*)ppPoints); 
  299.     if (FAILED(hr))
  300.         return RaiseException(IDS_Unexpected, IID_IPane);
  301.     return NOERROR;
  302. }
  303.  
  304. /*
  305.  * CPane::get_MaxX, get_MaxY
  306.  *
  307.  * Purpose:
  308.  *  Returns the maximum visible X & Y coordinate values in twips.
  309.  *
  310.  */
  311. STDMETHODIMP
  312. CPane::get_MaxX(int FAR* pnMaxX)
  313. {   
  314.      *pnMaxX = m_nMaxX; 
  315.     if (m_nMaxX == -1)
  316.         return RaiseException(IDS_NoVisibleXCoordinate, IID_IPane);    
  317.     return NOERROR;
  318. }
  319.  
  320. STDMETHODIMP
  321. CPane::get_MaxY(int FAR* pnMaxY)
  322. {   
  323.     *pnMaxY = m_nMaxY; 
  324.     if (m_nMaxY == -1)
  325.         return RaiseException(IDS_NoVisibleYCoordinate, IID_IPane);   
  326.     return NOERROR;
  327. }
  328.  
  329. /*
  330.  * CPane::Clear
  331.  *
  332.  * Purpose:
  333.  *  Removes all the Lines and Points from the drawing and refreshes the client area.
  334.  *  The result is a blank slate as if the application had just been launched.
  335.  *
  336.  */
  337. STDMETHODIMP
  338. CPane::Clear()
  339. {
  340.     m_pLines->Clear();
  341.     m_pPoints->Clear();
  342.     ::InvalidateRect(m_hwnd, NULL, TRUE);
  343.     UpdateWindow(m_hwnd);  
  344.     m_nMaxX = m_nMaxY = -1;  
  345.     return NOERROR;    
  346. }
  347.  
  348. /*
  349.  * CPane::Refresh
  350.  *
  351.  * Purpose:
  352.  *  Invalidates the entire drawing window so the drawing is cleared
  353.  *  and each of the lines in the Lines collection is redrawn.
  354.  *
  355.  */
  356. STDMETHODIMP
  357. CPane::Refresh()
  358. {
  359.     ::InvalidateRect(m_hwnd, NULL, TRUE);
  360.     UpdateWindow(m_hwnd);
  361.     return NOERROR;    
  362. }
  363.  
  364. /* 
  365.  *
  366.  * The following methods are not exposed through Automation
  367.  *
  368.  */
  369.  
  370. STDMETHODIMP_(void)
  371. CPane::Draw(void)
  372. {
  373.     PAINTSTRUCT ps;
  374.     
  375.     BeginPaint(m_hwnd, &ps);
  376.     SetMapMode(ps.hdc, MM_TWIPS);   
  377.     SetWindowOrgEx(ps.hdc, 0, m_nHeight, NULL);
  378.     m_pLines->Draw(ps.hdc);
  379.     EndPaint(m_hwnd, &ps);
  380. }  
  381.  
  382. /*
  383.  * CPane::OnSize
  384.  *
  385.  * Purpose:
  386.  *  Called when the pane is resized. Remembers the new size and gets the new maximum visible
  387.  *  x and y coordinates.
  388.  *
  389.  */ 
  390. STDMETHODIMP_(void)
  391. CPane::OnSize(unsigned int nWidth, unsigned int nHeight) 
  392. {
  393.    HDC hdc;
  394.    POINT pt;      
  395.    RECT rc;
  396.    
  397.    // Translate the height and width of pane from device units to twips.
  398.    hdc = ::GetDC(m_hwnd);
  399.    SetMapMode(hdc, MM_TWIPS); 
  400.    pt.x = nWidth; pt.y = nHeight;
  401.    DPtoLP(hdc, &pt, 1);
  402.    m_nWidth = pt.x;
  403.    m_nHeight = -pt.y;
  404.    ::ReleaseDC(m_hwnd, hdc); 
  405.    
  406.    // Get the new max visible x and y coordinates   
  407.    SetRect(&rc, 0, 0, m_nWidth, m_nHeight);
  408.    m_pPoints->GetMaxXMaxY(&m_nMaxX, &m_nMaxY, &rc);   
  409. }
  410.  
  411. STDMETHODIMP_(HDC)
  412. CPane::GetDC()
  413. {
  414.     HDC hdc;        
  415.     
  416.     hdc = ::GetDC(m_hwnd);  
  417.     SetMapMode(hdc, MM_TWIPS);    
  418.     SetWindowOrgEx(hdc, 0, m_nHeight, NULL);
  419.     return hdc;
  420. }    
  421.  
  422. STDMETHODIMP_(void)
  423. CPane::ReleaseDC(HDC hdc)
  424. {    
  425.     ::ReleaseDC(m_hwnd, hdc);
  426. }  
  427.  
  428. STDMETHODIMP_(void)
  429. CPane::InvalidateRect(LPRECT prc)
  430. {   
  431.     RECT rc;
  432.     HDC hdc;  
  433.     int t;
  434.     
  435.    // Translate the area to be invalidated from twips to device units
  436.    hdc = ::GetDC(m_hwnd);
  437.    SetMapMode(hdc, MM_TWIPS); 
  438.    SetWindowOrgEx(hdc, 0, m_nHeight, NULL);   
  439.    rc = *prc;
  440.    LPtoDP(hdc, (LPPOINT)&rc.left, 1);     
  441.    LPtoDP(hdc, (LPPOINT)&rc.right, 1);   
  442.    
  443.    // Make sure left is not greater than right and top is not greater than bottom. Otherwise
  444.    // InvalidateRect will not invalidate.
  445.    if (rc.right < rc.left)
  446.    {
  447.        t = rc.right;
  448.        rc.right = rc.left;
  449.        rc.left = t;
  450.    }
  451.    if (rc.bottom < rc.top)
  452.    {
  453.        t = rc.bottom;
  454.        rc.bottom = rc.top;
  455.        rc.top = t;
  456.    }  
  457.    
  458.    ::InvalidateRect(m_hwnd, &rc, TRUE);    
  459.    ::ReleaseDC(m_hwnd, hdc);
  460.  
  461. STDMETHODIMP_(void)
  462. CPane::Update(void)
  463. {
  464.     UpdateWindow(m_hwnd);
  465. }
  466.  
  467. /*
  468.  * CPane::AddPoint
  469.  *
  470.  * Purpose:
  471.  *  Adds a point to the point collection. Updates max visible coordinates is required.
  472.  *
  473.  */
  474. STDMETHODIMP_(BOOL)
  475. CPane::AddPoint(CPoint FAR* pPoint)
  476. {
  477.     int nX, nY;
  478.  
  479.     nX = pPoint->get_x();
  480.     nY = pPoint->get_y();
  481.     
  482.     if (nX > m_nMaxX && nX <= m_nWidth)
  483.         m_nMaxX = nX;
  484.     if (nY > m_nMaxY && nY <= m_nHeight)
  485.         m_nMaxY = nY;
  486.         
  487.     return m_pPoints->Add(pPoint);
  488. }
  489.  
  490. /*
  491.  * CPane::RemovePoint
  492.  *
  493.  * Purpose:
  494.  *  Removes point from point collection. Updates max visible coordinates is required.
  495.  *
  496.  */
  497. STDMETHODIMP_(void)
  498. CPane::RemovePoint(CPoint FAR* pPoint)
  499. {   
  500.     RECT rc;    
  501.     
  502.     // If point was removed from the collection, update max visible X & Y coordinates     
  503.     if (m_pPoints->Remove(pPoint)) 
  504.     {
  505.         SetRect(&rc, 0, 0, m_nWidth, m_nHeight);
  506.         m_pPoints->GetMaxXMaxY(&m_nMaxX, &m_nMaxY, &rc);   
  507.     }
  508. }   
  509.