home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap24 / polyprop / polyprop.cpp < prev    next >
C/C++ Source or Header  |  1996-05-23  |  20KB  |  890 lines

  1. /*
  2.  * POLYPROP.CPP
  3.  * Polyline Property Page Chapter 24
  4.  *
  5.  * Server module code and class code CPolyPropertyPage class.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #define INITGUIDS
  16. #include "polyprop.h"
  17.  
  18.  
  19. //Count number of objects and number of locks.
  20. ULONG       g_cObj=0;
  21. ULONG       g_cLock=0;
  22. HINSTANCE   g_hInst=NULL;   //For resources
  23.  
  24. #ifdef WIN32
  25. TCHAR       g_szObj[]=TEXT("Object");
  26. #else
  27. TCHAR       g_szObjHi[]=TEXT("ObjectHi");
  28. TCHAR       g_szObjLo[]=TEXT("ObjectLo");
  29. #endif
  30.  
  31. /*
  32.  * LibMain(32)
  33.  *
  34.  * Purpose:
  35.  *  Entry point conditionally compiled for Win32 and Windows
  36.  *  3.1.  Provides the proper structure for each environment.
  37.  */
  38.  
  39. #ifdef WIN32
  40. BOOL WINAPI LibMain32(HINSTANCE hInstance, ULONG ulReason
  41.     , LPVOID pvReserved)
  42.     {
  43.     g_hInst=hInstance;
  44.  
  45.     if (DLL_PROCESS_DETACH==ulReason)
  46.         {
  47.         return TRUE;
  48.         }
  49.     else
  50.         {
  51.         if (DLL_PROCESS_ATTACH!=ulReason)
  52.             return TRUE;
  53.         }
  54.  
  55.     return TRUE;
  56.     }
  57. #else
  58. int PASCAL LibMain(HINSTANCE hInstance, WORD wDataSeg
  59.     , WORD cbHeapSize, LPSTR lpCmdLine)
  60.     {
  61.     if (0!=cbHeapSize)
  62.         UnlockData(0);
  63.  
  64.     g_hInst=hInstance;
  65.     return (int)hInstance;
  66.     }
  67. #endif
  68.  
  69.  
  70.  
  71. /*
  72.  * DllGetClassObject
  73.  * DllCanUnloadNow
  74.  * Standard COM exports for DLL servers.
  75.  */
  76.  
  77. HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid, REFIID riid
  78.     , PPVOID ppv)
  79.     {
  80.     CPolyPPFactory *pPF;
  81.     HRESULT         hr;
  82.  
  83.     if (CLSID_PolylinePropPage!=rclsid)
  84.         return ResultFromScode(E_FAIL);
  85.  
  86.     //Check that we can provide the interface
  87.     if (IID_IUnknown!=riid && IID_IClassFactory!=riid)
  88.         return ResultFromScode(E_NOINTERFACE);
  89.  
  90.     //Return our factory's IClassFactory
  91.     pPF=new CPolyPPFactory();
  92.  
  93.     if (NULL==pPF)
  94.         return ResultFromScode(E_OUTOFMEMORY);
  95.  
  96.     //If the factory hasn't the interface, delete it
  97.     hr=pPF->QueryInterface(riid, ppv);
  98.  
  99.     if (FAILED(hr))
  100.         delete pPF;
  101.     else
  102.         g_cObj++;
  103.  
  104.     return hr;
  105.     }
  106.  
  107.  
  108. STDAPI DllCanUnloadNow(void)
  109.     {
  110.     SCODE   sc;
  111.  
  112.     //Our answer is whether there are any object or locks
  113.     sc=(0L==g_cObj && 0L==g_cLock) ? S_OK : S_FALSE;
  114.     return ResultFromScode(sc);
  115.     }
  116.  
  117.  
  118.  
  119. /*
  120.  * CPolyPPFactory::CPolyPPFactory
  121.  * CPolyPPFactory::~CPolyPPFactory
  122.  * CPolyPPFactory::QueryInterface
  123.  * CPolyPPFactory::AddRef
  124.  * CPolyPPFactory::Release
  125.  */
  126.  
  127. CPolyPPFactory::CPolyPPFactory(void)
  128.     {
  129.     m_cRef=0L;
  130.     return;
  131.     }
  132.  
  133. CPolyPPFactory::~CPolyPPFactory(void)
  134.     {
  135.     return;
  136.     }
  137.  
  138. STDMETHODIMP CPolyPPFactory::QueryInterface(REFIID riid, PPVOID ppv)
  139.     {
  140.     *ppv=NULL;
  141.  
  142.     if (IID_IUnknown==riid || IID_IClassFactory==riid)
  143.         *ppv=this;
  144.  
  145.     if (NULL!=*ppv)
  146.         {
  147.         ((LPUNKNOWN)*ppv)->AddRef();
  148.         return NOERROR;
  149.         }
  150.  
  151.     return ResultFromScode(E_NOINTERFACE);
  152.     }
  153.  
  154.  
  155. STDMETHODIMP_(ULONG) CPolyPPFactory::AddRef(void)
  156.     {
  157.     return ++m_cRef;
  158.     }
  159.  
  160.  
  161. STDMETHODIMP_(ULONG) CPolyPPFactory::Release(void)
  162.     {
  163.     if (0!=--m_cRef)
  164.         return m_cRef;
  165.  
  166.     delete this;
  167.     g_cObj--;
  168.     return 0;
  169.     }
  170.  
  171.  
  172.  
  173. /*
  174.  * CPolyPPFactory::CreateInstance
  175.  * CPolyPPFactory::LockServer
  176.  */
  177.  
  178. STDMETHODIMP CPolyPPFactory::CreateInstance(LPUNKNOWN pUnkOuter
  179.     , REFIID riid, PPVOID ppvObj)
  180.     {
  181.     PCPolyPropPage      pObj;
  182.     HRESULT             hr;
  183.  
  184.     *ppvObj=NULL;
  185.     hr=ResultFromScode(E_OUTOFMEMORY);
  186.  
  187.     //No aggregation supported
  188.     if (NULL!=pUnkOuter)
  189.         return ResultFromScode(CLASS_E_NOAGGREGATION);
  190.  
  191.     //Create the object passing function to notify on destruction.
  192.     pObj=new CPolyPropPage(g_hInst);
  193.  
  194.     if (NULL==pObj)
  195.         return hr;
  196.  
  197.     if (pObj->Init())
  198.         hr=pObj->QueryInterface(riid, ppvObj);
  199.  
  200.     //Kill the object if initial creation or Init failed.
  201.     if (FAILED(hr))
  202.         delete pObj;
  203.     else
  204.         g_cObj++;
  205.  
  206.     return hr;
  207.     }
  208.  
  209.  
  210. STDMETHODIMP CPolyPPFactory::LockServer(BOOL fLock)
  211.     {
  212.     if (fLock)
  213.         g_cLock++;
  214.     else
  215.         g_cLock--;
  216.  
  217.     return NOERROR;
  218.     }
  219.  
  220.  
  221.  
  222. /***
  223.  *** CPolyPropPage implementation
  224.  ***/
  225.  
  226.  
  227. /*
  228.  * CPolyPropPage::CPolyPropPage
  229.  * CPolyPropPage::~CPolyPropPage
  230.  *
  231.  * Constructor Parameters:
  232.  *  hInst           HINSTANCE of the module
  233.  */
  234.  
  235. CPolyPropPage::CPolyPropPage(HINSTANCE hInst)
  236.     {
  237.     m_cRef=0L;
  238.  
  239.     m_hInst=hInst;
  240.     m_hDlg=NULL;
  241.  
  242.     //Default sizes
  243.     m_cx=300;
  244.     m_cy=100;
  245.  
  246.     m_pIPropertyPageSite=NULL;
  247.     m_ppObj=NULL;
  248.     m_cObjects=0;
  249.  
  250.     m_uIDLastLine=ID_LINESOLID;
  251.     m_crLastBack=0;
  252.     m_crLastLine=0;
  253.  
  254.     m_fDirty=FALSE;
  255.     return;
  256.     }
  257.  
  258. CPolyPropPage::~CPolyPropPage(void)
  259.     {
  260.     if (NULL!=m_hDlg)
  261.         DestroyWindow(m_hDlg);
  262.  
  263.     FreeAllObjects();
  264.     ReleaseInterface(m_pIPropertyPageSite);
  265.     return;
  266.     }
  267.  
  268.  
  269. /*
  270.  * CPolyPropPage::QueryInterface
  271.  * CPolyPropPage::AddRef
  272.  * CPolyPropPage::Release
  273.  */
  274.  
  275. STDMETHODIMP CPolyPropPage::QueryInterface(REFIID riid, PPVOID ppv)
  276.     {
  277.     *ppv=NULL;
  278.  
  279.     if (IID_IUnknown==riid || IID_IPropertyPage==riid)
  280.         *ppv=this;
  281.  
  282.     if (NULL!=*ppv)
  283.         {
  284.         ((LPUNKNOWN)*ppv)->AddRef();
  285.         return NOERROR;
  286.         }
  287.  
  288.     return ResultFromScode(E_NOINTERFACE);
  289.     }
  290.  
  291.  
  292. STDMETHODIMP_(ULONG) CPolyPropPage::AddRef(void)
  293.     {
  294.     return ++m_cRef;
  295.     }
  296.  
  297.  
  298. STDMETHODIMP_(ULONG) CPolyPropPage::Release(void)
  299.     {
  300.     if (0!=--m_cRef)
  301.         return m_cRef;
  302.  
  303.     g_cObj--;
  304.     delete this;
  305.     return 0;
  306.     }
  307.  
  308.  
  309.  
  310.  
  311. /*
  312.  * CPolyPropPage::Init
  313.  *
  314.  * Purpose:
  315.  *  Performs initialization operations that might fail.
  316.  *
  317.  * Parameters:
  318.  *  None
  319.  *
  320.  * Return Value:
  321.  *  BOOL            TRUE if initialization successful, FALSE
  322.  *                  otherwise.
  323.  */
  324.  
  325. BOOL CPolyPropPage::Init(void)
  326.     {
  327.     //Nothing to do
  328.     return TRUE;
  329.     }
  330.  
  331.  
  332.  
  333.  
  334. /*
  335.  * CPolyPropPage::FreeAllObjects
  336.  *
  337.  * Purpose:
  338.  *  Releases all the objects from IPropertyPage::SetObjects
  339.  *
  340.  * Parameters:
  341.  *  None
  342.  */
  343.  
  344. void CPolyPropPage::FreeAllObjects(void)
  345.     {
  346.     UINT        i;
  347.  
  348.     if (NULL==m_ppObj)
  349.         return;
  350.  
  351.     for (i=0; i < m_cObjects; i++)
  352.         ReleaseInterface(m_ppObj[i]);
  353.  
  354.     delete [] m_ppObj;
  355.     m_ppObj=NULL;
  356.     m_cObjects=0;
  357.     return;
  358.     }
  359.  
  360.  
  361.  
  362. /*
  363.  * CPolyPropPage::SetPageSite
  364.  *
  365.  * Purpose:
  366.  *  Provides the property page with the IPropertyPageSite
  367.  *  that contains it.  SetPageSite(NULL) will be called as
  368.  *  part of the close sequence.
  369.  *
  370.  * Parameters:
  371.  *  pPageSite       LPPROPERTYPAGESITE pointer to the site.
  372.  */
  373.  
  374. STDMETHODIMP CPolyPropPage::SetPageSite
  375.     (LPPROPERTYPAGESITE pPageSite)
  376.     {
  377.     if (NULL==pPageSite)
  378.         ReleaseInterface(m_pIPropertyPageSite)
  379.     else
  380.         {
  381.         HWND        hDlg;
  382.         RECT        rc;
  383.  
  384.         m_pIPropertyPageSite=pPageSite;
  385.         m_pIPropertyPageSite->AddRef();
  386.  
  387.         //We ignore locales
  388.  
  389.         /*
  390.          * Load the dialog and determine the size it will be to
  391.          * return through GetPageSize.  We just create the dialog
  392.          * here and destroy it again to retrieve the size,
  393.          * leaving Activate to create it for real.
  394.          */
  395.         hDlg=CreateDialogParam(m_hInst
  396.             , MAKEINTRESOURCE(IDD_POLYLINEPROPS), GetDesktopWindow()
  397.             , (DLGPROC)PolyPropPageProc, 0L);
  398.  
  399.         //If creation fails, use default values set in constructor
  400.         if (NULL!=hDlg)
  401.             {
  402.             GetWindowRect(hDlg, &rc);
  403.             m_cx=rc.right-rc.left;
  404.             m_cy=rc.bottom-rc.top;
  405.  
  406.             DestroyWindow(hDlg);
  407.             }
  408.         }
  409.  
  410.     return NOERROR;
  411.     }
  412.  
  413.  
  414.  
  415. /*
  416.  * CPolyPropPage::Activate
  417.  *
  418.  * Purpose:
  419.  *  Instructs the property page to create a window in which to
  420.  *  display its contents, using the given parent window and
  421.  *  rectangle.  The window should be initially visible.
  422.  *
  423.  * Parameters:
  424.  *  hWndParent      HWND of the parent window.
  425.  *  prc             LPCRECT of the rectangle to use.
  426.  *  fModal          BOOL indicating whether the frame is modal.
  427.  */
  428.  
  429. STDMETHODIMP CPolyPropPage::Activate(HWND hWndParent
  430.     , LPCRECT prc, BOOL fModal)
  431.     {
  432.     if (NULL!=m_hDlg)
  433.         return ResultFromScode(E_UNEXPECTED);
  434.  
  435.     m_hDlg=CreateDialogParam(m_hInst
  436.         , MAKEINTRESOURCE(IDD_POLYLINEPROPS)
  437.         , hWndParent, PolyPropPageProc, (LPARAM)this);
  438.  
  439.     if (NULL==m_hDlg)
  440.         return ResultFromScode(E_OUTOFMEMORY);
  441.  
  442.     //Move the page into position and show it.
  443.     SetWindowPos(m_hDlg, NULL, prc->left, prc->top
  444.         , prc->right-prc->left, prc->bottom-prc->top, 0);
  445.  
  446.     return NOERROR;
  447.     }
  448.  
  449.  
  450.  
  451. /*
  452.  * CPolyPropPage::Deactivate
  453.  *
  454.  * Purpose:
  455.  *  Instructs the property page to destroy its window that was
  456.  *  created in Activate.
  457.  *
  458.  * Parameters:
  459.  *  None
  460.  */
  461.  
  462. STDMETHODIMP CPolyPropPage::Deactivate(void)
  463.     {
  464.     if (NULL==m_hDlg)
  465.         return ResultFromScode(E_UNEXPECTED);
  466.  
  467.     DestroyWindow(m_hDlg);
  468.     m_hDlg=NULL;
  469.     return NOERROR;
  470.     }
  471.  
  472.  
  473.  
  474. /*
  475.  * CPolyPropPage::GetPageInfo
  476.  *
  477.  * Purpose:
  478.  *  Fills a PROPPAGEINFO structure describing the page's size,
  479.  *  contents, and help information.
  480.  *
  481.  * Parameters:
  482.  *  pPageInfo       LPPROPPAGEINFO to the structure to fill.
  483.  */
  484.  
  485. STDMETHODIMP CPolyPropPage::GetPageInfo(LPPROPPAGEINFO pPageInfo)
  486.     {
  487.     IMalloc     *pIMalloc;
  488.  
  489.     if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  490.         return ResultFromScode(E_FAIL);
  491.  
  492.     pPageInfo->pszTitle=(LPOLESTR)pIMalloc->Alloc(80*sizeof(TCHAR));
  493.  
  494.     if (NULL!=pPageInfo->pszTitle)
  495.        #ifdef WIN32ANSI
  496.         wcscpy(pPageInfo->pszTitle, OLETEXT("General"));
  497.        #else
  498.         lstrcpy(pPageInfo->pszTitle, TEXT("General"));
  499.        #endif
  500.  
  501.     pIMalloc->Release();
  502.  
  503.     pPageInfo->size.cx      = m_cx;
  504.     pPageInfo->size.cy      = m_cy;
  505.     pPageInfo->pszDocString = NULL;
  506.     pPageInfo->pszHelpFile  = NULL;
  507.     pPageInfo->dwHelpContext= 0;
  508.     return NOERROR;
  509.     }
  510.  
  511.  
  512.  
  513. /*
  514.  * CPolyPropPage::SetObjects
  515.  *
  516.  * Purpose:
  517.  *  Identifies the objects that are being affected by this property
  518.  *  page (and all other pages in the frame).  These are the object
  519.  *  to which to send new property values in the Apply member.
  520.  *
  521.  * Parameters:
  522.  *  cObjects        ULONG number of objects
  523.  *  ppUnk           IUnknown ** to the array of objects being
  524.  *                  passed to the page.
  525.  */
  526.  
  527. STDMETHODIMP CPolyPropPage::SetObjects(ULONG cObjects
  528.     , IUnknown **ppUnk)
  529.     {
  530.     BOOL        fRet=TRUE;
  531.  
  532.     FreeAllObjects();
  533.  
  534.     if (0!=cObjects)
  535.         {
  536.         UINT        i;
  537.         HRESULT     hr;
  538.  
  539.         m_ppObj=new IPolylineControl * [(UINT)cObjects];
  540.  
  541.         for (i=0; i < cObjects; i++)
  542.             {
  543.             hr=ppUnk[i]->QueryInterface(IID_IPolylineControl
  544.                 , (void **)&m_ppObj[i]);
  545.  
  546.             if (FAILED(hr))
  547.                 fRet=FALSE;
  548.             }
  549.         }
  550.  
  551.     //If we didn't get one of our objects, fail this call.
  552.     if (!fRet)
  553.         return ResultFromScode(E_FAIL);
  554.  
  555.     m_cObjects=cObjects;
  556.     return NOERROR;
  557.     }
  558.  
  559.  
  560.  
  561. /*
  562.  * CPolyPropPage::Show
  563.  *
  564.  * Purpose:
  565.  *  Instructs the page to show or hide its window created in
  566.  *  Activate.
  567.  *
  568.  * Parameters:
  569.  *  nCmdShow        UINT to pass to ShowWindow.
  570.  */
  571.  
  572. STDMETHODIMP CPolyPropPage::Show(UINT nCmdShow)
  573.     {
  574.     if (NULL==m_hDlg)
  575.         ResultFromScode(E_UNEXPECTED);
  576.  
  577.     ShowWindow(m_hDlg, nCmdShow);
  578.  
  579.     //Take the focus
  580.     if (SW_SHOWNORMAL==nCmdShow || SW_SHOW==nCmdShow)
  581.         SetFocus(m_hDlg);
  582.  
  583.     return NOERROR;
  584.     }
  585.  
  586.  
  587.  
  588. /*
  589.  * CPolyPropPage::Move
  590.  *
  591.  * Purpose:
  592.  *  Instructs the property page to change its position.
  593.  *
  594.  * Parameters:
  595.  *  prc             LPCRECT containing the new position.
  596.  */
  597.  
  598. STDMETHODIMP CPolyPropPage::Move(LPCRECT prc)
  599.     {
  600.     SetWindowPos(m_hDlg, NULL, prc->left, prc->top
  601.         , prc->right-prc->left, prc->bottom-prc->top, 0);
  602.  
  603.     return NOERROR;
  604.     }
  605.  
  606.  
  607.  
  608. /*
  609.  * CPolyPropPage::IsPageDirty
  610.  *
  611.  * Purpose:
  612.  *  Asks the page if anything's changed in it, that is, if the
  613.  *  property values in the page are out of sync with the objects
  614.  *  under consideration.
  615.  *
  616.  * Parameters:
  617.  *  None
  618.  *
  619.  * Return Value:
  620.  *  HRESULT         NOERROR if dirty, S_FALSE if not.
  621.  */
  622.  
  623. STDMETHODIMP CPolyPropPage::IsPageDirty(void)
  624.     {
  625.     return ResultFromScode(m_fDirty ? S_OK : S_FALSE);
  626.     }
  627.  
  628.  
  629.  
  630.  
  631. /*
  632.  * CPolyPropPage::Apply
  633.  *
  634.  * Purpose:
  635.  *  Instructs the page to send changes in its page to whatever
  636.  *  objects it knows about through SetObjects.  This is the only
  637.  *  time the page should change the objects' properties, and not
  638.  *  when the value is changed on the page.
  639.  *
  640.  * Parameters:
  641.  *  None
  642.  */
  643.  
  644. STDMETHODIMP CPolyPropPage::Apply(void)
  645.     {
  646.     UINT        i;
  647.     UINT        iLine, iLineNew;
  648.     COLORREF    crNew;
  649.     BOOL        fChanged;
  650.  
  651.     if (0==m_cObjects)
  652.         return NOERROR;
  653.  
  654.     /*
  655.      * The dialog's last known line selection is in m_uIDLastLine,
  656.      * colors in m_crLastBack and m_crLastLine, so we can just
  657.      * send these to IPolylineControl member functions.
  658.      * We the test if the change took place to determine whether
  659.      * we set our dirty flag.
  660.      */
  661.  
  662.     iLine=m_uIDLastLine-ID_LINEMIN;
  663.     fChanged=FALSE;
  664.  
  665.     for (i=0; i < m_cObjects; i++)
  666.         {
  667.         m_ppObj[i]->put_LineStyle(iLine);
  668.         iLineNew=m_ppObj[i]->get_LineStyle();
  669.  
  670.         fChanged |= (iLine!=iLineNew);
  671.  
  672.         m_ppObj[i]->put_BackColor(m_crLastBack);
  673.         crNew=m_ppObj[i]->get_BackColor();
  674.  
  675.         fChanged |= (m_crLastBack!=crNew);
  676.  
  677.         m_ppObj[i]->put_LineColor(m_crLastLine);
  678.         crNew=m_ppObj[i]->get_LineColor();
  679.  
  680.         fChanged |= (m_crLastLine!=crNew);
  681.         }
  682.  
  683.     m_fDirty=!fChanged;
  684.     return NOERROR;
  685.     }
  686.  
  687.  
  688.  
  689. /*
  690.  * CPolyPropPage::Help
  691.  *
  692.  * Purpose:
  693.  *  Invokes help for this property page when the user presses
  694.  *  the Help button.  If you return NULLs for the help file
  695.  *  in GetPageInfo, the button will be grayed.  Otherwise the
  696.  *  page can perform its own help here.
  697.  *
  698.  * Parameters:
  699.  *  pszHelpDir      LPCOLESTR identifying the default location of
  700.  *                  the help information
  701.  *
  702.  * Return Value:
  703.  *  HRESULT         NOERROR to tell the frame that we've done our
  704.  *                  own help.  Returning an error code or S_FALSE
  705.  *                  causes the frame to use any help information
  706.  *                  in PROPPAGEINFO.
  707.  */
  708.  
  709. STDMETHODIMP CPolyPropPage::Help(LPCOLESTR pszHelpDir)
  710.     {
  711.     /*
  712.      * We can either provide help ourselves, or rely on the
  713.      * information in PROPPAGEINFO.
  714.      */
  715.     return ResultFromScode(S_FALSE);
  716.     }
  717.  
  718.  
  719.  
  720.  
  721. /*
  722.  * CPolyPropPage::TranslateAccelerator
  723.  *
  724.  * Purpose:
  725.  *  Provides the page with the messages that occur in the frame.
  726.  *  This gives the page to do whatever it wants with the message,
  727.  *  such as handle keyboard mnemonics.
  728.  *
  729.  * Parameters:
  730.  *  pMsg            LPMSG containing the keyboard message.
  731.  */
  732.  
  733. STDMETHODIMP CPolyPropPage::TranslateAccelerator(LPMSG lpMsg)
  734.     {
  735.     //No keyboard interface supported here
  736.     return ResultFromScode(E_NOTIMPL);
  737.     }
  738.  
  739.  
  740.  
  741. /*
  742.  * PolyPropPageProc
  743.  *
  744.  * Purpose:
  745.  *  Dialog procedure for the Polyline Property Page.
  746.  */
  747.  
  748. BOOL APIENTRY PolyPropPageProc(HWND hDlg, UINT iMsg
  749.     , WPARAM wParam, LPARAM lParam)
  750.     {
  751.     PCPolyPropPage      pObj;
  752.     WORD                wID;
  753.     UINT                i;
  754.     COLORREF            rgColors[16];
  755.     CHOOSECOLOR         cc;
  756.  
  757.    #ifdef WIN32
  758.     pObj=(PCPolyPropPage)(ULONG)GetProp(hDlg, g_szObj);
  759.    #else
  760.     pObj=(PCPolyPropPage)MAKELONG((WORD)GetProp(hDlg, g_szObjLo)
  761.        , (WORD)GetProp(hDlg, g_szObjHi));
  762.    #endif
  763.  
  764.     switch (iMsg)
  765.         {
  766.         case WM_INITDIALOG:
  767.             pObj=(PCPolyPropPage)(ULONG)lParam;
  768.            #ifdef WIN32
  769.             SetProp(hDlg, g_szObj, (HANDLE)lParam);
  770.            #else
  771.             SetProp(hDlg, g_szObjHi, (HANDLE)HIWORD(lParam));
  772.             SetProp(hDlg, g_szObjLo, (HANDLE)LOWORD(lParam));
  773.            #endif
  774.  
  775.             if (NULL==pObj)
  776.                 return TRUE;
  777.  
  778.             /*
  779.              * If we have one object then we can try to set the
  780.              * right field in the dialog box.  Otherwise we could
  781.              * ask for the value from all of the objects and see
  782.              * if they all match.
  783.              */
  784.             if (1==pObj->m_cObjects)
  785.                 {
  786.                 UINT        iLine;
  787.  
  788.                 iLine=pObj->m_ppObj[0]->get_LineStyle();
  789.  
  790.                 CheckRadioButton(hDlg, ID_LINESOLID
  791.                     , ID_LINEDASHDOTDOT, iLine+ID_LINEMIN);
  792.  
  793.                 SetFocus(GetDlgItem(hDlg, iLine+ID_LINEMIN));
  794.  
  795.                 pObj->m_uIDLastLine=iLine;
  796.  
  797.                 pObj->m_crLastBack=pObj->m_ppObj[0]->get_BackColor();
  798.                 pObj->m_crLastLine=pObj->m_ppObj[0]->get_LineColor();
  799.                 }
  800.  
  801.             return FALSE;
  802.  
  803.         case WM_DESTROY:
  804.            #ifdef WIN32
  805.             RemoveProp(hDlg, g_szObj);
  806.            #else
  807.             RemoveProp(hDlg, g_szObjHi);
  808.             RemoveProp(hDlg, g_szObjLo);
  809.            #endif
  810.             return FALSE;
  811.  
  812.         case WM_COMMAND:
  813.             wID=LOWORD(wParam);
  814.  
  815.             switch (wID)
  816.                 {
  817.                 case ID_LINESOLID:
  818.                 case ID_LINEDASH:
  819.                 case ID_LINEDOT:
  820.                 case ID_LINEDASHDOT:
  821.                 case ID_LINEDASHDOTDOT:
  822.                     if (NULL==pObj)
  823.                         break;
  824.  
  825.                     //Selecting the same one doesn't dirty
  826.                     if (pObj->m_uIDLastLine==wID)
  827.                         break;
  828.  
  829.                     //Save the most recently selected
  830.                     pObj->m_uIDLastLine=LOWORD(wParam);
  831.                     pObj->m_fDirty=TRUE;
  832.  
  833.                     if (NULL!=pObj->m_pIPropertyPageSite)
  834.                         {
  835.                         pObj->m_pIPropertyPageSite
  836.                             ->OnStatusChange(PROPPAGESTATUS_DIRTY);
  837.                         }
  838.  
  839.                     break;
  840.  
  841.  
  842.                 case ID_COLORLINE:
  843.                 case ID_COLORBACK:
  844.                     if (NULL==pObj)
  845.                         break;
  846.  
  847.                     for (i=0; i<16; i++)
  848.                         rgColors[i]=RGB(0, 0, i*16);
  849.  
  850.                     memset(&cc, 0, sizeof(CHOOSECOLOR));
  851.                     cc.lStructSize=sizeof(CHOOSECOLOR);
  852.                     cc.lpCustColors=rgColors;
  853.                     cc.hwndOwner=GetParent(hDlg);
  854.                     cc.Flags=CC_RGBINIT;
  855.                     cc.rgbResult=(ID_COLORBACK==wID)
  856.                         ? pObj->m_crLastBack
  857.                         : pObj->m_crLastLine;
  858.  
  859.                     if (ChooseColor(&cc))
  860.                         {
  861.                         COLORREF    cr;
  862.                         ;
  863.                         if (ID_COLORBACK==wID)
  864.                             {
  865.                             cr=pObj->m_crLastBack;
  866.                             pObj->m_crLastBack=cc.rgbResult;
  867.                             }
  868.                         else
  869.                             {
  870.                             cr=pObj->m_crLastLine;
  871.                             pObj->m_crLastLine=cc.rgbResult;
  872.                             }
  873.  
  874.                         pObj->m_fDirty=(cr!=cc.rgbResult);
  875.  
  876.                         if (pObj->m_fDirty
  877.                             && NULL!=pObj->m_pIPropertyPageSite)
  878.                             {
  879.                             pObj->m_pIPropertyPageSite
  880.                                 ->OnStatusChange(PROPPAGESTATUS_DIRTY);
  881.                             }
  882.                         }
  883.                     break;
  884.  
  885.                 }
  886.             break;
  887.         }
  888.     return FALSE;
  889.     }
  890.