home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / activexcontrol / basectl / framewrk / proppage.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  20.0 KB  |  769 lines

  1. //=--------------------------------------------------------------------------=
  2. // PropPage.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1997 Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of CPropertyPage object.
  13. //
  14. #include "IPServer.H"
  15. #include "PropPage.H"
  16. #include "Util.H"
  17. #include "Globals.H"
  18.  
  19. // for ASSERT and FAIL
  20. //
  21. SZTHISFILE
  22.  
  23. // this variable is used to pass the pointer to the object to the hwnd.
  24. //
  25. static CPropertyPage *s_pLastPageCreated;
  26.  
  27. //=--------------------------------------------------------------------------=
  28. // CPropertyPage::CPropertyPage
  29. //=--------------------------------------------------------------------------=
  30. // constructor.
  31. //
  32. // Parameters:
  33. //    IUnknown *          - [in] controlling unknown
  34. //    int                 - [in] object type.
  35. //
  36. // Notes:
  37. //
  38. #pragma warning(disable:4355)  // using 'this' in constructor
  39. CPropertyPage::CPropertyPage
  40. (
  41.     IUnknown         *pUnkOuter,
  42.     int               iObjectType
  43. )
  44. : CUnknownObject(pUnkOuter, this), m_ObjectType(iObjectType)
  45. {
  46.     // initialize various dudes.
  47.     //
  48.     m_pPropertyPageSite = NULL;
  49.     m_hwnd = NULL;
  50.     m_fDirty = FALSE;
  51.     m_fActivated = FALSE;
  52.     m_cObjects = 0;
  53. }
  54. #pragma warning(default:4355)  // using 'this' in constructor
  55.  
  56.  
  57. //=--------------------------------------------------------------------------=
  58. // CPropertyPage::~CPropertyPage
  59. //=--------------------------------------------------------------------------=
  60. // destructor.
  61. //
  62. // Notes:
  63. //
  64. CPropertyPage::~CPropertyPage()
  65. {
  66.     // clean up our window.
  67.     //
  68.     if (m_hwnd) {
  69.         SetWindowLong(m_hwnd, GWL_USERDATA, 0xffffffff);
  70.         DestroyWindow(m_hwnd);
  71.     }
  72.  
  73.     // release all the objects we're holding on to.
  74.     //
  75.     m_ReleaseAllObjects();
  76.  
  77.     // release the site
  78.     //
  79.     QUICK_RELEASE(m_pPropertyPageSite);
  80. }
  81.  
  82. //=--------------------------------------------------------------------------=
  83. // CPropertyPage::InternalQueryInterface
  84. //=--------------------------------------------------------------------------=
  85. // we support IPP and IPP2.
  86. //
  87. // Parameters:
  88. //    REFIID        - [in]  interface they want
  89. //    void **       - [out] where they want to put the resulting object ptr.
  90. //
  91. // Output:
  92. //    HRESULT       - S_OK, E_NOINTERFACE
  93. //
  94. // Notes:
  95. //
  96. HRESULT CPropertyPage::InternalQueryInterface
  97. (
  98.     REFIID  riid,
  99.     void  **ppvObjOut
  100. )
  101. {
  102.     IUnknown *pUnk;
  103.  
  104.     *ppvObjOut = NULL;
  105.  
  106.     if (DO_GUIDS_MATCH(IID_IPropertyPage, riid)) {
  107.         pUnk = (IUnknown *)this;
  108.     } else if (DO_GUIDS_MATCH(IID_IPropertyPage2, riid)) {
  109.         pUnk = (IUnknown *)this;
  110.     } else {
  111.         return CUnknownObject::InternalQueryInterface(riid, ppvObjOut);
  112.     }
  113.  
  114.     pUnk->AddRef();
  115.     *ppvObjOut = (void *)pUnk;
  116.     return S_OK;
  117. }
  118.  
  119. //=--------------------------------------------------------------------------=
  120. // CPropertyPage::SetPageSite    [IPropertyPage]
  121. //=--------------------------------------------------------------------------=
  122. // the initialization function for a property page through which the page
  123. // receives an IPropertyPageSite pointer.
  124. //
  125. // Parameters:
  126. //    IPropertyPageSite *        - [in] new site.
  127. //
  128. // Output:
  129. //    HRESULT
  130. //
  131. // Notes;
  132. //
  133. STDMETHODIMP CPropertyPage::SetPageSite
  134. (
  135.     IPropertyPageSite *pPropertyPageSite
  136. )
  137. {
  138.     RELEASE_OBJECT(m_pPropertyPageSite);
  139.     m_pPropertyPageSite = pPropertyPageSite;
  140.     ADDREF_OBJECT(pPropertyPageSite);
  141.  
  142.     return S_OK;
  143. }
  144.  
  145. //=--------------------------------------------------------------------------=
  146. // CPropertyPage::Activate    [IPropertyPage]
  147. //=--------------------------------------------------------------------------=
  148. // instructs the page to create it's display window as a child of hwndparent
  149. // and to position it according to prc.
  150. //
  151. // Parameters:
  152. //    HWND                - [in]  parent window
  153. //    LPCRECT             - [in]  where to position ourselves
  154. //    BOOL                - [in]  whether we're modal or not.
  155. //
  156. // Output:
  157. //    HRESULT
  158. //
  159. // Notes:
  160. //
  161. STDMETHODIMP CPropertyPage::Activate
  162. (
  163.     HWND    hwndParent,
  164.     LPCRECT prcBounds,
  165.     BOOL    fModal
  166. )
  167. {
  168.     HRESULT hr;
  169.  
  170.     // first make sure the dialog window is loaded and created.
  171.     //
  172.     hr = m_EnsureLoaded();
  173.     RETURN_ON_FAILURE(hr);
  174.  
  175.     // set our parent window if we haven't done so yet.
  176.     //
  177.     if (!m_fActivated) {
  178.         SetParent(m_hwnd, hwndParent);
  179.         m_fActivated = TRUE;
  180.     }
  181.  
  182.     // now move ourselves to where we're told to be and show ourselves
  183.     //
  184.     Move(prcBounds);
  185.     ShowWindow(m_hwnd, SW_SHOW);
  186.  
  187.     return S_OK;
  188. }
  189.  
  190. //=--------------------------------------------------------------------------=
  191. // CPropertyPage::Deactivate    [IPropertyPage]
  192. //=--------------------------------------------------------------------------=
  193. // instructs the page to destroy the window created in activate
  194. //
  195. // Output:
  196. //    HRESULT
  197. //
  198. // Notes:
  199. //
  200. STDMETHODIMP CPropertyPage::Deactivate
  201. (
  202.     void
  203. )
  204. {
  205.     // blow away yon window.
  206.     //
  207.     if (m_hwnd)
  208.         DestroyWindow(m_hwnd);
  209.     m_hwnd = NULL;
  210.     m_fActivated = FALSE;
  211.  
  212.     return S_OK;
  213. }
  214.  
  215. //=--------------------------------------------------------------------------=
  216. // CPropertyPage::GetPageInfo    [IPropertyPage]
  217. //=--------------------------------------------------------------------------=
  218. // asks the page to fill a PROPPAGEINFO structure
  219. //
  220. // Parameters:
  221. //    PROPPAGEINFO *    - [out] where to put info.
  222. //
  223. // Output:
  224. //    HRESULT
  225. //
  226. // Notes:
  227. //
  228. STDMETHODIMP CPropertyPage::GetPageInfo
  229. (
  230.     PROPPAGEINFO *pPropPageInfo
  231. )
  232. {
  233.     RECT rect;
  234.  
  235.     CHECK_POINTER(pPropPageInfo);
  236.  
  237.     m_EnsureLoaded();
  238.  
  239.     // clear it out first.
  240.     //
  241.     memset(pPropPageInfo, 0, sizeof(PROPPAGEINFO));
  242.  
  243.     pPropPageInfo->pszTitle = OLESTRFROMRESID(TITLEIDOFPROPPAGE(m_ObjectType));
  244.     pPropPageInfo->pszDocString = OLESTRFROMRESID(DOCSTRINGIDOFPROPPAGE(m_ObjectType));
  245.     pPropPageInfo->pszHelpFile = OLESTRFROMANSI(HELPFILEOFPROPPAGE(m_ObjectType));
  246.     pPropPageInfo->dwHelpContext = HELPCONTEXTOFPROPPAGE(m_ObjectType);
  247.  
  248.     if (!(pPropPageInfo->pszTitle && pPropPageInfo->pszDocString && pPropPageInfo->pszHelpFile))
  249.         goto CleanUp;
  250.  
  251.     // if we've got a window yet, go and set up the size information they want.
  252.     //
  253.     if (m_hwnd) {
  254.         GetWindowRect(m_hwnd, &rect);
  255.  
  256.         pPropPageInfo->size.cx = rect.right - rect.left;
  257.         pPropPageInfo->size.cy = rect.bottom - rect.top;
  258.     }
  259.  
  260.     return S_OK;
  261.  
  262.   CleanUp:
  263.     if (pPropPageInfo->pszDocString) CoTaskMemFree(pPropPageInfo->pszDocString);
  264.     if (pPropPageInfo->pszHelpFile) CoTaskMemFree(pPropPageInfo->pszHelpFile);
  265.     if (pPropPageInfo->pszTitle) CoTaskMemFree(pPropPageInfo->pszTitle);
  266.  
  267.     return E_OUTOFMEMORY;
  268. }
  269.  
  270. //=--------------------------------------------------------------------------=
  271. // CPropertyPage::SetObjects    [IPropertyPage]
  272. //=--------------------------------------------------------------------------=
  273. // provides the page with the objects being affected by the changes.
  274. //
  275. // Parameters:
  276. //    ULONG            - [in] count of objects.
  277. //    IUnknown **      - [in] objects.
  278. //
  279. // Output:
  280. //    HRESULT
  281. //
  282. // Notes:
  283. //
  284. STDMETHODIMP CPropertyPage::SetObjects
  285. (
  286.     ULONG      cObjects,
  287.     IUnknown **ppUnkObjects
  288. )
  289. {
  290.     HRESULT hr;
  291.     ULONG   x;
  292.  
  293.     // free up all the old objects first.
  294.     //
  295.     m_ReleaseAllObjects();
  296.  
  297.     if (!cObjects)
  298.         return S_OK;
  299.  
  300.     // now go and set up the new ones.
  301.     //
  302.     m_ppUnkObjects = (IUnknown **)HeapAlloc(g_hHeap, 0, cObjects * sizeof(IUnknown *));
  303.     RETURN_ON_NULLALLOC(m_ppUnkObjects);
  304.  
  305.     // loop through and copy over all the objects.
  306.     //
  307.     for (x = 0; x < cObjects; x++) {
  308.         m_ppUnkObjects[x] = ppUnkObjects[x];
  309.         ADDREF_OBJECT(m_ppUnkObjects[x]);
  310.     }
  311.  
  312.     // go and tell the object that there are new objects
  313.     //
  314.     hr = S_OK;
  315.     m_cObjects = cObjects;
  316.     // if we've got a window, go and notify it that we've got new objects.
  317.     //
  318.     if (m_hwnd)
  319.         SendMessage(m_hwnd, PPM_NEWOBJECTS, 0, (LPARAM)&hr);
  320.     if (SUCCEEDED(hr)) m_fDirty = FALSE;
  321.  
  322.     return hr;
  323. }
  324.  
  325. //=--------------------------------------------------------------------------=
  326. // CPropertyPage::Show    [IPropertyPage]
  327. //=--------------------------------------------------------------------------=
  328. // asks the page to show or hide its window
  329. //
  330. // Parameters:
  331. //    UINT             - [in] whether to show or hide
  332. //
  333. // Output:
  334. //    HRESULT
  335. //
  336. // Notes:
  337. //
  338. STDMETHODIMP CPropertyPage::Show
  339. (
  340.     UINT nCmdShow
  341. )
  342. {
  343.     if (m_hwnd)
  344.         ShowWindow(m_hwnd, nCmdShow);
  345.     else
  346.         return E_UNEXPECTED;
  347.  
  348.     return S_OK;
  349. }
  350.  
  351. //=--------------------------------------------------------------------------=
  352. // CPropertyPage::Move    [IPropertyPage]
  353. //=--------------------------------------------------------------------------=
  354. // asks the page to relocate and resize itself to a position other than what
  355. // was specified through Activate
  356. //
  357. // Parameters:
  358. //    LPCRECT        - [in] new position and size
  359. //
  360. // Output:
  361. //    HRESULT
  362. //
  363. // Notes:
  364. //
  365. STDMETHODIMP CPropertyPage::Move
  366. (
  367.     LPCRECT prcBounds
  368. )
  369. {
  370.     // do what they sez
  371.     //
  372.     if (m_hwnd)
  373.         SetWindowPos(m_hwnd, NULL, prcBounds->left, prcBounds->top,
  374.                      prcBounds->right - prcBounds->left,
  375.                      prcBounds->bottom - prcBounds->top,
  376.                      SWP_NOZORDER);
  377.     else
  378.         return E_UNEXPECTED;
  379.  
  380.     return S_OK;
  381. }
  382.  
  383. //=--------------------------------------------------------------------------=
  384. // CPropertyPage::IsPageDirty    [IPropertyPage]
  385. //=--------------------------------------------------------------------------=
  386. // asks the page whether it has changed its state
  387. //
  388. // Output
  389. //    S_OK            - yep
  390. //    S_FALSE         - nope
  391. //
  392. // Notes:
  393. //
  394. STDMETHODIMP CPropertyPage::IsPageDirty
  395. (
  396.     void
  397. )
  398. {
  399.     return m_fDirty ? S_OK : S_FALSE;
  400. }
  401.  
  402. //=--------------------------------------------------------------------------=
  403. // CPropertyPage::Apply    [IPropertyPage]
  404. //=--------------------------------------------------------------------------=
  405. // instructs the page to send its changes to all the objects passed through
  406. // SetObjects()
  407. //
  408. // Output:
  409. //    HRESULT
  410. //
  411. // Notes:
  412. //
  413. STDMETHODIMP CPropertyPage::Apply
  414. (
  415.     void
  416. )
  417. {
  418.     HRESULT hr = S_OK;
  419.  
  420.     if (m_hwnd) {
  421.         SendMessage(m_hwnd, PPM_APPLY, 0, (LPARAM)&hr);
  422.         RETURN_ON_FAILURE(hr);
  423.  
  424.         if (m_fDirty) {
  425.             m_fDirty = FALSE;
  426.             if (m_pPropertyPageSite)
  427.                 m_pPropertyPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
  428.         }
  429.     } else
  430.         return E_UNEXPECTED;
  431.  
  432.     return S_OK;
  433. }
  434.  
  435. //=--------------------------------------------------------------------------=
  436. // CPropertyPage::Help    [IPropertyPage]
  437. //=--------------------------------------------------------------------------=
  438. // instructs the page that the help button was clicked.
  439. //
  440. // Parameters:
  441. //    LPCOLESTR        - [in] help directory
  442. //
  443. // Output:
  444. //    HRESULT
  445. //
  446. // Notes:
  447. //
  448. STDMETHODIMP CPropertyPage::Help
  449. (
  450.     LPCOLESTR pszHelpDir
  451. )
  452. {
  453.     BOOL f;
  454.  
  455.     ASSERT(m_hwnd, "How can somebody have clicked Help, but we don't have an hwnd?");
  456.  
  457.     // oblige them and show the help.
  458.     //
  459.     MAKE_ANSIPTR_FROMWIDE(psz, pszHelpDir);
  460.     f = WinHelp(m_hwnd, psz, HELP_CONTEXT, HELPCONTEXTOFPROPPAGE(m_ObjectType));
  461.  
  462.     return f ? S_OK : E_FAIL;
  463. }
  464.  
  465. //=--------------------------------------------------------------------------=
  466. // CPropertyPage::TranslateAccelerator    [IPropertyPage]
  467. //=--------------------------------------------------------------------------=
  468. // informs the page of keyboard events, allowing it to implement it's own
  469. // keyboard interface.
  470. //
  471. // Parameters:
  472. //    LPMSG            - [in] message that triggered this
  473. //
  474. // Output:
  475. //    HRESULT
  476. //
  477. // Notes:
  478. //
  479. STDMETHODIMP CPropertyPage::TranslateAccelerator
  480. (
  481.     LPMSG pmsg
  482. )
  483. {
  484.     ASSERT(m_hwnd, "How can we get a TranslateAccelerator call if we're not visible?");
  485.  
  486.     // just pass this message on to the dialog proc and see if they want it.
  487.     //
  488.     return IsDialogMessage(m_hwnd, pmsg) ? S_OK : S_FALSE;
  489. }
  490.  
  491. //=--------------------------------------------------------------------------=
  492. // CPropertyPage::EditProperty    [IPropertyPage2]
  493. //=--------------------------------------------------------------------------=
  494. // instructs the page to set the focus to the property matching the dispid.
  495. //
  496. // Parameters:
  497. //    DISPID            - [in] dispid of property to set focus to.
  498. //
  499. // Output:
  500. //    HRESULT
  501. //
  502. // Notes:
  503. //
  504. STDMETHODIMP CPropertyPage::EditProperty
  505. (
  506.     DISPID dispid
  507. )
  508. {
  509.     HRESULT hr = E_NOTIMPL;
  510.  
  511.     // send the message on to the control, and see what they want to do with it.
  512.     //
  513.     SendMessage(m_hwnd, PPM_EDITPROPERTY, (WPARAM)dispid, (LPARAM)&hr);
  514.  
  515.     return hr;
  516. }
  517.  
  518. //=--------------------------------------------------------------------------=
  519. // CPropertyPage::m_EnsureLoaded
  520. //=--------------------------------------------------------------------------=
  521. // makes sure the dialog is actually loaded
  522. //
  523. // Output:
  524. //    HRESULT
  525. //
  526. // Notes:
  527. //
  528. HRESULT CPropertyPage::m_EnsureLoaded
  529. (
  530.     void
  531. )
  532. {
  533.     HRESULT hr = S_OK;
  534.  
  535.     // duh
  536.     //
  537.     if (m_hwnd)
  538.         return S_OK;
  539.  
  540.     // set up the global variable so that when we're in the dialog proc, we can
  541.     // stuff this in the hwnd
  542.     //
  543.     // crit sect this whole creation process for apartment threading support.
  544.     //
  545.     EnterCriticalSection(&g_CriticalSection);
  546.     s_pLastPageCreated = this;
  547.  
  548.     // create the dialog window
  549.     //
  550.     CreateDialog(GetResourceHandle(), TEMPLATENAMEOFPROPPAGE(m_ObjectType), GetParkingWindow(),
  551.                           (DLGPROC)CPropertyPage::PropPageDlgProc);
  552.     ASSERT(m_hwnd, "Couldn't load Dialog Resource!!!");
  553.     if (!m_hwnd) {
  554.         LeaveCriticalSection(&g_CriticalSection);
  555.         return HRESULT_FROM_WIN32(GetLastError());
  556.     }
  557.  
  558.     // clean up variables and leave the critical section
  559.     //
  560.     s_pLastPageCreated = NULL;
  561.     LeaveCriticalSection(&g_CriticalSection);
  562.  
  563.     // go and notify the window that it should pick up any objects that are
  564.     // available
  565.     //
  566.     SendMessage(m_hwnd, PPM_NEWOBJECTS, 0, (LPARAM)&hr);
  567.  
  568.     return hr;
  569. }
  570.  
  571. //=--------------------------------------------------------------------------=
  572. // CPropertyPage::m_ReleaseAllObjects
  573. //=--------------------------------------------------------------------------=
  574. // releases all the objects that we're working with
  575. //
  576. // Notes:
  577. //
  578. void CPropertyPage::m_ReleaseAllObjects
  579. (
  580.     void
  581. )
  582. {
  583.     HRESULT hr;
  584.     UINT x;
  585.  
  586.     if (!m_cObjects)
  587.         return;
  588.  
  589.     // some people will want to stash pointers in the PPM_INITOBJECTS case, so
  590.     // we want to tell them to release them now.
  591.     //
  592.     SendMessage(m_hwnd, PPM_FREEOBJECTS, 0, (LPARAM)&hr);
  593.  
  594.     // loop through and blow them all away.
  595.     //
  596.     for (x = 0; x < m_cObjects; x++)
  597.         QUICK_RELEASE(m_ppUnkObjects[x]);
  598.  
  599.     HeapFree(g_hHeap, 0, m_ppUnkObjects);
  600.     m_ppUnkObjects = NULL;
  601. }
  602.  
  603. //=--------------------------------------------------------------------------=
  604. // CPropertyPage::PropPageDlgProc
  605. //=--------------------------------------------------------------------------=
  606. // static global helper dialog proc that gets called before we pass the message
  607. // on to anybody ..
  608. //
  609. // Parameters:
  610. //    - see win32sdk docs on DialogProc
  611. //
  612. // Notes:
  613. //
  614. BOOL CALLBACK CPropertyPage::PropPageDlgProc
  615. (
  616.     HWND    hwnd,
  617.     UINT    msg,
  618.     WPARAM  wParam,
  619.     LPARAM  lParam
  620. )
  621. {
  622.     CPropertyPage *pPropertyPage;
  623.  
  624.     // get the window long, and see if it's been set to the object this hwnd
  625.     // is operating against.  if not, go and set it now.
  626.     //
  627.     pPropertyPage = (CPropertyPage *)GetWindowLong(hwnd, GWL_USERDATA);
  628.     if ((ULONG)pPropertyPage == 0xffffffff)
  629.         return FALSE;
  630.     if (!pPropertyPage) {
  631.         SetWindowLong(hwnd, GWL_USERDATA, (LONG)s_pLastPageCreated);
  632.         pPropertyPage = s_pLastPageCreated;
  633.         pPropertyPage->m_hwnd = hwnd;
  634.     }
  635.  
  636.     ASSERT(pPropertyPage, "Uh oh.  Got a window, but no CpropertyPage for it!");
  637.  
  638.     // just call the user dialog proc and see if they want to do anything.
  639.     //
  640.     return pPropertyPage->DialogProc(hwnd, msg, wParam, lParam);
  641. }
  642.  
  643.  
  644. //=--------------------------------------------------------------------------=
  645. // CPropertyPage::FirstControl
  646. //=--------------------------------------------------------------------------=
  647. // returns the first controlish object that we are showing ourselves for.
  648. // returns a cookie that must be passed in for Next ...
  649. //
  650. // Parameters:
  651. //    DWORD *    - [out] cookie to be used for Next
  652. //
  653. // Output:
  654. //    IUnknown *
  655. //
  656. // Notes:
  657. //
  658. IUnknown *CPropertyPage::FirstControl
  659. (
  660.     DWORD *pdwCookie
  661. )
  662. {
  663.     // just use the implementation of NEXT.
  664.     //
  665.     *pdwCookie = 0;
  666.     return NextControl(pdwCookie);
  667. }
  668.  
  669. //=--------------------------------------------------------------------------=
  670. // CPropertyPage::NextControl
  671. //=--------------------------------------------------------------------------=
  672. // returns the next control in the chain of people to work with given a cookie
  673. //
  674. // Parameters:
  675. //    DWORD *            - [in/out] cookie to get next from, and new cookie.
  676. //
  677. // Output:
  678. //    IUnknown *
  679. //
  680. // Notes:
  681. //
  682. IUnknown *CPropertyPage::NextControl
  683. (
  684.     DWORD *pdwCookie
  685. )
  686. {
  687.     UINT      i;
  688.  
  689.     // go looking through all the objects that we've got, and find the
  690.     // first non-null one.
  691.     //
  692.     for (i = *pdwCookie; i < m_cObjects; i++) {
  693.         if (!m_ppUnkObjects[i]) continue;
  694.  
  695.         *pdwCookie = i + 1;                // + 1 so we start at next item next time
  696.         return m_ppUnkObjects[i];
  697.     }
  698.  
  699.     // couldn't find it .
  700.     //
  701.     *pdwCookie = 0xffffffff;
  702.     return NULL;
  703. }
  704.  
  705. //=--------------------------------------------------------------------------=
  706. // CPropertyPage::MakeDirty    [helper, callable]
  707. //=--------------------------------------------------------------------------=
  708. // marks a page as dirty.
  709. //
  710. // Notes:
  711. //
  712. void CPropertyPage::MakeDirty
  713. (
  714.     void
  715. )
  716. {
  717.     m_fDirty = TRUE;
  718.     if (m_pPropertyPageSite)
  719.         m_pPropertyPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY|PROPPAGESTATUS_VALIDATE);
  720. }
  721.  
  722.  
  723. // from Globals.C
  724. //
  725. extern HINSTANCE g_hInstResources;
  726.  
  727.  
  728. //=--------------------------------------------------------------------------=
  729. // CPropertyPage::GetResourceHandle    [helper, callable]
  730. //=--------------------------------------------------------------------------=
  731. // returns current resource handle, based on pagesites ambient LCID.
  732. //
  733. // Output:
  734. //    HINSTANCE
  735. //
  736. // Notes:
  737. //
  738. HINSTANCE CPropertyPage::GetResourceHandle
  739. (
  740.     void
  741. )
  742. {
  743.     if (!g_fSatelliteLocalization)
  744.         return g_hInstance;
  745.  
  746.     // if we've already got it, then there's not all that much to do.
  747.     // don't need to crit sect this one right here since even if they do fall
  748.     // into the ::GetResourceHandle call, it'll properly deal with things.
  749.     //
  750.     if (g_hInstResources)
  751.         return g_hInstResources;
  752.  
  753.     // we'll get the ambient localeid from the host, and pass that on to the
  754.     // automation object.
  755.     //
  756.     // enter a critical section for g_lcidLocale and g_fHavelocale
  757.     //
  758.     EnterCriticalSection(&g_CriticalSection);
  759.     if (!g_fHaveLocale) {
  760.         if (m_pPropertyPageSite) {
  761.             m_pPropertyPageSite->GetLocaleID(&g_lcidLocale);
  762.             g_fHaveLocale = TRUE;
  763.         }
  764.     }
  765.     LeaveCriticalSection(&g_CriticalSection);
  766.  
  767.     return ::GetResourceHandle();
  768. }
  769.