123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569 |
- /////////////////////////////////////////////////////////////////////////////
- // PropertyPageBase.cpp | Implementation of the TCPropertyPageBase class.
- #pragma warning(disable: 4786)
- #include <vector>
- #include <map>
- #include <set>
- #include <comdef.h>
- #include <typeinfo.h>
- #include "..\TCLib\AdviseHolder.h"
- #include "InsidePropPage.h"
- #include "PageEntry.h"
- #include "PropertyPageBase.h"
- /////////////////////////////////////////////////////////////////////////////
- // TCPropertyPageBase
- /////////////////////////////////////////////////////////////////////////////
- // Group=Construction / Destruction
- TCPropertyPageBase::TCPropertyPageBase() :
- m_iTable(0),
- m_bInitializing(true),
- m_bUpdating(true)
- {
- }
- TCPropertyPageBase::~TCPropertyPageBase()
- {
- // Release any objects saved for inside pages
- ReleaseObjectsForInsidePages();
- // Release any interfaces in the map of supported interfaces
- ReleaseSupportedInterfaces();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=Attributes
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves a pointer to an embedded property page.
- //
- // Retrieves a pointer to the embedded property page specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: An TCInsidePropPage pointer to the embedded property page if
- // /idCtrl/ is valid. Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup
- TCInsidePropPage* TCPropertyPageBase::GetInsidePage(UINT idCtrl)
- {
- // Lookup the specified page
- XInsidePage* pPage = _GetInsidePage(idCtrl);
- if (!pPage)
- return pPage;
- // Return the page
- assert(pPage->m_hWnd);
- return pPage;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves the application-defined 32-bit (DWORD) value
- // associated with an embedded property page.
- //
- // Retrieves the application-defined 32-bit (DWORD) value associated with the
- // embedded property page specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: The application-defined 32-bit (DWORD) value associated with
- // the specified embedded property page, if /idCtrl/ is valid. Otherwise,
- // zero.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePage
- DWORD TCPropertyPageBase::GetInsidePageData(UINT idCtrl)
- {
- // Lookup the specified page
- XInsidePage* pPage = _GetInsidePage(idCtrl);
- // Return the page data
- return pPage ? pPage->m_pEntry->dwData : 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves the application-defined text associated with an
- // embedded property page.
- //
- // Retrieves the application-defined text associated with the embedded
- // property page specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: The application-defined text associated with the specified
- // embedded property page, if /idCtrl/ is valid.
- // Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroupText
- LPCTSTR TCPropertyPageBase::GetInsidePageText(UINT idCtrl)
- {
- // Lookup the specified page
- XInsidePage* pPage = _GetInsidePage(idCtrl);
- // Return the page text
- return pPage ? pPage->m_pEntry->pszText : NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves the state of the dirty flag of an embedded property
- // page.
- //
- // Retrieves the state of the dirty flag of the embedded property page
- // specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: *true* if the embedded property page's dirty flag is set and
- // /idCtrl/ is valid. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePage,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup
- bool TCPropertyPageBase::GetDirtyInsidePage(UINT idCtrl)
- {
- TCInsidePropPage* pPage = GetInsidePage(idCtrl);
- return pPage ? pPage->Page_IsDirty() : false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Modifies the state of the dirty flag of an embedded property
- // page.
- //
- // Modifies the state of the dirty flag of the embedded property page
- // specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- // bDirty - The new state of the embedded property page's dirty flag. If
- // *true*, the embedded property page's state is marked as changed. If
- // *false*, it is marked as unchanged.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup
- void TCPropertyPageBase::SetDirtyInsidePage(UINT idCtrl, bool bDirty)
- {
- TCInsidePropPage* pPage = GetInsidePage(idCtrl);
- if (pPage)
- pPage->SetDirty(bDirty);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves a pointer to an embedded property page within a
- // group of embedded property pages.
- //
- // Retrieves a pointer to the embedded property page specified by /dw/,
- // within the embedded property page group specified by /idGroup/.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: An TCInsidePropPage pointer to the embedded property page if
- // /idGroup/ and /dw/ are valid. Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePage
- TCInsidePropPage* TCPropertyPageBase::GetInsidePageOfGroup(UINT idGroup,
- DWORD dw)
- {
- // Lookup the specified group/page
- XInsidePage* pPage = _GetInsidePageOfGroup(idGroup, dw);
- if (!pPage)
- return pPage;
- // Return the page
- assert(pPage->m_hWnd);
- return pPage;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves the application-defined text associated with an
- // embedded property page within a group of embedded property pages.
- //
- // Retrieves the application-defined text associated with the embedded
- // property page specified by /dw/, within the embedded property page group
- // specified by /idGroup/.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: The application-defined text associated with the embedded
- // property page, if /idGroup/ and /dw/ are valid. Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageText
- LPCTSTR TCPropertyPageBase::GetInsidePageOfGroupText(UINT idGroup, DWORD dw)
- {
- // Lookup the specified group/page
- XInsidePage* pPage = _GetInsidePageOfGroup(idGroup, dw);
- if (!pPage)
- return NULL;
- // Return the text pointer
- return pPage->m_pEntry->pszText;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves the state of the dirty flag of an embedded
- // property page within a group of embedded property pages.
- //
- // Retrieves the state of the dirty flag of the embedded property page
- // specified by /dw/, within the embedded property page group specified by
- // /idGroup/.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: *true* if the embedded property page's dirty flag is set and
- // /idGroup/ and /dw/ are valid. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup,
- // TCPropertyPageBase::GetDirtyInsidePage
- bool TCPropertyPageBase::GetDirtyInsidePageOfGroup(UINT idGroup, DWORD dw)
- {
- TCInsidePropPage* pPage = GetInsidePageOfGroup(idGroup, dw);
- return pPage ? pPage->Page_IsDirty() : false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Modifies the state of the dirty flag of an embedded property
- // page within a group of embedded property pages.
- //
- // Modifies the state of the dirty flag of the embedded property page
- // specified by /dw/, within the embedded property page group specified by
- // /idGroup/.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- // bDirty - The new state of the embedded property page's dirty flag. If
- // *true*, the embedded property page's state is marked as changed. If
- // *false*, it is marked as unchanged.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePage
- void TCPropertyPageBase::SetDirtyInsidePageOfGroup(UINT idGroup,
- DWORD dw, bool bDirty)
- {
- TCInsidePropPage* pPage = GetInsidePageOfGroup(idGroup, dw);
- if (pPage)
- pPage->SetDirty(bDirty);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves a pointer to the currently visible embedded
- // property page within a group of embedded property pages.
- //
- // Retrieves a pointer to the currently visible embedded property page within
- // a group of embedded property pages.
- //
- // Only one property page, at most, within a group of embedded property pages
- // may be visible. In other words, the visibility of pages within a group is
- // mutually exclusive.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- //
- // Return Value: An TCInsidePropPage pointer to the currently visible
- // embedded property page within the group, if any. Otherwise, *NULL*. If
- // /idGroup/ is not valid, *NULL* is also returned.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup
- TCInsidePropPage* TCPropertyPageBase::GetVisiblePageOfGroup(UINT idGroup)
- {
- // Find the specified group ID in the map of groups
- CPageGroupIterator itGroup = m_mapPageGroups.find(idGroup);
- if (m_mapPageGroups.end() == itGroup)
- return NULL;
- // Find the currently visible page in the group
- CPageMap* pmap = itGroup->second;
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if (IsWindow(*pPage) && pPage->IsWindowVisible())
- return pPage;
- }
- // Couldn't find a visible page in the group
- return NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=Operations
- /////////////////////////////////////////////////////////////////////////////
- // Description: Makes the window visible of an embedded property page.
- //
- // Makes the window visible of the embedded property page specified by
- // /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: *true* if /idCtrl/ is valid and the operation completed
- // successfully. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::HideInsidePage,
- // TCPropertyPageBase::ShowInsidePageOfGroup
- bool TCPropertyPageBase::ShowInsidePage(UINT idCtrl)
- {
- TCInsidePropPage* pPage = GetInsidePage(idCtrl);
- return pPage ? (IsWindow(*pPage) && pPage->ShowWindow(SW_SHOW)) : false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Hides the window of an embedded property page.
- //
- // Hides the window of the embedded property page specified by /idCtrl/.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: *true* if /idCtrl/ is valid and the operation completed
- // successfully. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::GetInsidePageData,
- // TCPropertyPageBase::GetInsidePageText,
- // TCPropertyPageBase::GetDirtyInsidePage,
- // TCPropertyPageBase::SetDirtyInsidePage,
- // TCPropertyPageBase::ShowInsidePage,
- // TCPropertyPageBase::HideInsidePageOfGroup
- bool TCPropertyPageBase::HideInsidePage(UINT idCtrl)
- {
- TCInsidePropPage* pPage = GetInsidePage(idCtrl);
- return pPage ? (IsWindow(*pPage) && pPage->ShowWindow(SW_HIDE)) : false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Makes the window visible of an embedded property page within
- // a group of embedded property pages, hiding any previously visible page
- // within the same group.
- //
- // Makes the window visible of the embedded property page specified by
- // /dw/, within the embedded property page group specified by /idGroup/. If
- // another page within the same group was visible it now becomes hidden.
- //
- // Only one property page, at most, within a group of embedded property pages
- // may be visible. In other words, the visibility of pages within a group is
- // mutually exclusive.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: *true* if /idGroup/ and /dw/ are valid and the operation
- // completed successfully. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageOfGroupData,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePage
- bool TCPropertyPageBase::ShowInsidePageOfGroup(UINT idGroup, DWORD dw)
- {
- // Find the specified group ID in the map of groups
- CPageGroupIterator itGroup = m_mapPageGroups.find(idGroup);
- if (m_mapPageGroups.end() == itGroup)
- return false;
- // Find the specified page in the group
- CPageMap* pmap = itGroup->second;
- CPageIterator itPage = pmap->find(dw);
- if (pmap->end() == itPage)
- return false;
- // Buffer the window positioning
- TCDeferWindowPosHandle hdwp = ::BeginDeferWindowPos(2);
- UINT uFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER;
- // Find the currently visible page in the group and hide it
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if (IsWindow(*pPage) && pPage->IsWindowVisible())
- {
- if (itPage != it)
- ::DeferWindowPos(hdwp, *pPage, NULL, 0, 0, 0, 0,
- uFlags | SWP_HIDEWINDOW);
- break;
- }
- }
- // Show the specified property page, if not already visible
- if (itPage != it)
- {
- // Create the page, if not already created
- XInsidePage* pPage = itPage->second;
- if (pPage->m_hWnd || CreateInsidePage(pPage, true))
- ::DeferWindowPos(hdwp, *pPage, HWND_TOP, 0, 0, 0, 0,
- uFlags | SWP_SHOWWINDOW);
- }
- // Indicate success
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Hides the window of an embedded property page within a group
- // of embedded property pages.
- //
- // Hides the window of the embedded property page specified by /dw/, within
- // the embedded property page group specified by /idGroup/.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: *true* if /idGroup/ and /dw/ are valid and the operation
- // completed successfully. Otherwise, *false*.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCInsidePropPage, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::GetInsidePageOfGroupData,
- // TCPropertyPageBase::GetInsidePageOfGroupText,
- // TCPropertyPageBase::GetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::SetDirtyInsidePageOfGroup,
- // TCPropertyPageBase::ShowInsidePageOfGroup,
- // TCPropertyPageBase::HideInsidePage
- bool TCPropertyPageBase::HideInsidePageOfGroup(UINT idGroup, DWORD dw)
- {
- // Lookup the specified group/page
- XInsidePage* pPage = _GetInsidePageOfGroup(idGroup, dw);
- if (!pPage)
- return false;
- // Hide the window, if it's valid
- if (IsWindow(*pPage))
- pPage->ShowWindow(SW_HIDE);
- // Indicate success
- return true;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=Overrides
- /////////////////////////////////////////////////////////////////////////////
- // Description: Override to allow derived classes a proper place to
- // initialize user interface elements.
- //
- // A derived class should override this method to perform initialization that
- // needs to be done only when the property page dialog is first created. Such
- // initialization typically includes attaching member variables to fields on
- // the dialog box.
- //
- // Note: This is *not* the appropriate place to initialize the /values/ of
- // the dialog box fields. For more information on such initialization, see
- // the Property Page Field Update Macros.
- //
- // This method is called by the OnInitDialogHandler method, which is the
- // message handler for the *WM_INITDIALOG* message. When this method is
- // called, the following conditions are guaranteed:
- //
- // + The m_bInitializing flag is set to *true*.
- // + Embedded property pages specified in the property page table, if any,
- // have been created.
- // + Advisory connections with the set of objects being edited/viewed, if
- // any, have been established.
- //
- // Following the return from this method, the UpdateFields method is called,
- // which, in turn, will call the update methods specified in the entries of
- // the property field map.
- //
- // Return Value: The default return value is *false*, indicating that the
- // input focus should not be set to the first tabstop control.
- //
- // Note: The return value is effectively *void* since the base class
- // currently ignores it. Input focus control is not given to the derived
- // classes.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::OnInitDialogHandler
- bool TCPropertyPageBase::OnInitDialog()
- {
- // Return false to not set focus to the first tabstop control
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Override to allow derived classes to specify a table of
- // embedded property pages.
- //
- // Overridden by derived classes to specify a table of embedded property
- // pages. This table is used by the CreateInsidePages method.
- //
- // Note: A derived class should *not* override this method directly. Instead,
- // the derived class should use the Embedded Property Page Table Macros,
- // which provide the proper override of this method.
- //
- // Parameters:
- // ppTable - [out] A pointer to where the address of the table is to be
- // returned.
- // iTable - [in] Specifies the index of the page table which is being
- // requested. Most property pages have only 1 table, with an index of zero.
- // For more information on alternate page tables, see the ALT_INSIDE_PAGE_MAP
- // macro.
- //
- // Return Value: The number of entries in the page table returned thru the
- // /ppTable/ parameter. The default implementation returns zero.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePageEntry
- // TCPropertyPageBase::CreateInsidePages
- UINT TCPropertyPageBase::GetInsidePageTable(
- const XInsidePageEntry** ppTable, UINT iTable)
- {
- UNUSED(iTable);
- // Default does nothing
- if (ppTable)
- *ppTable = NULL;
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Override to allow derived classes to establish any further
- // advisory connections with the objects being edited/viewed.
- //
- // This method is called to allow a derived class an appropriate place to
- // establish advisory connections with the objects being edited/viewed.
- //
- // Note: It is *not* necessary to connect *IPropertyNotifySink* advises here,
- // since that is done automatically by the SetAllAdvises method, based on the
- // entries in the property field map. Therefore, this override is provided
- // only for the possible cases when connections *other* than
- // *IPropertyNotifySink* need to be established.
- //
- // Any advisory connections established in this method should be disconnected
- // in the derived class's override of OnClearAllAdvises.
- //
- // This method is called by the SetAllAdvises method, which is called from
- // both the SetObjects and OnInitDialogHandler methods. When this method is
- // called, the following conditions are guaranteed:
- //
- // + The property page is active, meaning that a window has been created for
- // the page.
- // + All *IPropertyNotifySink* advisory connections, if any, have already
- // been established, based on the entries in the property field map.
- // + The set of objects specified by the /cObjects/ and /ppUnk/ parameters
- // has been filtered down to only the set of objects that support the
- // interfaces specified by the entries of the property field map. This does
- // *not* include the property field map of any embedded property pages.
- //
- // Note: To assist with establishing advisory connections, consider using the
- // TCAdviseHolder class, of which instances can be stored in a collection.
- //
- // The default implementation of this method does nothing.
- //
- // Parameters:
- // cObjects - [in] Number of *IUnknown* pointers in the array pointed to by
- // /ppUnk/.
- // ppUnk - [in] Pointer to an array of *IUnknown* interface pointers, which
- // represents the set of objects being edited/viewed by this property page.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::OnClearAllAdvises,
- // TCPropertyPageBase::SetAllAdvises,
- // TCPropertyPageBase::OnInitDialogHandler
- void TCPropertyPageBase::OnSetAllAdvises(ULONG cObjects, IUnknown** ppUnk)
- {
- UNUSED(cObjects);
- UNUSED(ppUnk);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Override to allow derived classes to disconnect any advisory
- // connections established in OnSetAllAdvises.
- //
- // This method is called to allow a derived class an appropriate place to
- // disconnect advisory connections previously established with the objects
- // being edited/viewed.
- //
- // Note: It is *not* necessary to disconnect *IPropertyNotifySink* advises
- // here, since that is done automatically by the ClearAllAdvises method.
- //
- // The advisory connections disconnected in this method should exactly match
- // those established in the derived class's override of OnSetAllAdvises.
- //
- // This method is called by the ClearAllAdvises method, which is called from
- // both the SetObjects and OnNcDestroyHandler methods. When this method is
- // called, the following condition is guaranteed:
- //
- // + All established *IPropertyNotifySink* advisory connections, if any, have
- // not yet been broken.
- //
- // Following the return from this method, all established
- // *IPropertyNotifySink* advisory connections, if any, will be disconnected.
- //
- // Note: If the TCAdviseHolder class was used to establish a connection, it
- // will be broken when the instance is destroyed. So, if a collection of them
- // were being maintained, simply erasing the contents of the collection would
- // break the connections. This assumes, of course, that the collection holds
- // actual instances, rather than pointers to instances.
- //
- // The default implementation of this method does nothing.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::OnSetAllAdvises,
- // TCPropertyPageBase::SetAllAdvises,
- // TCPropertyPageBase::OnNcDestroyHandler
- void TCPropertyPageBase::OnClearAllAdvises()
- {
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=Implementation
- /////////////////////////////////////////////////////////////////////////////
- // Description: Creates the window of an embedded property page.
- //
- // This method is used by the implementation to create the window of the
- // specified embedded property page.
- //
- // Parameters:
- // pPage - The embedded property page instance for which a window is to be
- // created.
- // bOfGroup - Indicator of whether or not /pPage/ is a page belonging to a
- // mutually exclusive group of embedded property pages. *true* indicates
- // that it is a member of a group; *false* indicates that it is not.
- //
- // Return Value: *true* if the page was successfully created; otherwise
- // *false*.
- //
- // See Also: XInsidePage, TCPropertyPageBase::CreateInsidePages
- bool TCPropertyPageBase::CreateInsidePage(XInsidePage* pPage, bool bOfGroup)
- {
- // Save the focus window
- HWND hwndFocus = GetFocus();
- // Create the page
- HRESULT hr = SetObjectsToInsidePage(pPage);
- bool bCreated = pPage->Create(GetPageWindow(),
- IPropertyPageSitePtr(GetPageUnknown()), pPage->m_pEntry->idPosCtrl,
- *pPage->m_pEntry->pclsid, pPage->m_pEntry->bVisible,
- pPage->m_pEntry->bSizeToCtrl, !bOfGroup);
- #ifdef _DEBUG
- if (!bCreated)
- {
- char sz1[64], sz3[64];
- sprintf(sz1, "TCPropertyPageImpl<%hs>::CreateInsidePage", TypeName());
- LPCSTR sz2 = "Failed to create child property page ";
- if (!bOfGroup)
- sprintf(sz3, "with control id 0x%08X.", pPage->m_pEntry->idPosCtrl);
- else
- sprintf(sz3, "in page group 0x%08X with DWORD value 0x%08X.",
- pPage->m_pEntry->idPosCtrl, pPage->m_pEntry->dwData);
- _TRACE3("%hs%hs%hs\n", sz1, sz2, sz3);
- assert(bCreated);
- }
- #endif
- // Restore the focus to the previous focus window
- SetFocus(hwndFocus);
- return bCreated;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Creates the embedded property pages specified in the property
- // page map.
- //
- // This method is used by the implementation to create all the embedded
- // property pages specified in the property page map.
- //
- // This method loops thru the entries of the derived class's property page
- // map and creates an XInsidePage instance. Throughout this process, the
- // entries that represent pages within a group are seperated out and stored
- // appropriately.
- //
- // Once the objects are created, grouped, and stored, the pages that are to
- // be initially visible are created by calling the CreateInsidePage method.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePageEntry,
- // XInsidePage, TCPropertyPageBase::CPageMap,
- // TCPropertyPageBase::CreateInsidePage,
- // TCPropertyPageBase::DestroyInsidePages
- void TCPropertyPageBase::CreateInsidePages()
- {
- // Get the table of child property pages
- const XInsidePageEntry* pEntries = NULL;
- UINT nCount = GetInsidePageTable(&pEntries, m_iTable);
- if (!nCount)
- return;
- // Seperate the group entries
- for (UINT i = 0; i < nCount; i++)
- {
- // Get the next entry in the table
- const XInsidePageEntry& entry = pEntries[i];
- UINT idCtrl = entry.idPosCtrl;
- // Find the entry's control ID in the map of pages
- CPageIterator it = m_mapPages.find(idCtrl);
- if (m_mapPages.end() == it)
- {
- // Find the entry's control ID in the map of page groups
- CPageGroupIterator itGroup = m_mapPageGroups.find(idCtrl);
- if (m_mapPageGroups.end() == itGroup)
- {
- // Map the control ID to a new page
- XInsidePage* pPage = new XInsidePage(&entry);
- CPageMap::value_type value(idCtrl, pPage);
- m_mapPages.insert(value);
- }
- else
- {
- // Get the page map for the group
- CPageMap* pmap = itGroup->second;
- // Map the DWORD value to a new page
- DWORD dw = entry.dwData;
- XInsidePage* pPage = new XInsidePage(&entry);
- CPageMap::value_type value(dw, pPage);
- bool bInserted = pmap->insert(value).second;
- if (!bInserted)
- {
- delete pPage;
- #ifdef _DEBUG
- char sz[_MAX_PATH];
- sprintf(sz, "TCPropertyPageImpl<%hs>::CreateInsidePages(): "
- "More than one entry\n\tin page group 0x%08X, was specified "
- "with a DWORD value of 0x%08x.\n\tDuplicate is being ignored.",
- TypeName(), idCtrl, dw);
- _TRACE1("%hs\n", sz);
- assert(bInserted);
- #endif
- }
- }
- }
- else
- {
- // Map the control ID to a new page group
- CPageMap* pPageMap = new CPageMap;
- CPageGroupMap::value_type valuePageMap(idCtrl, pPageMap);
- m_mapPageGroups.insert(valuePageMap);
- // Move the located page to the new page group
- XInsidePage* pPage = it->second;
- CPageMap::value_type valuePage(pPage->m_pEntry->dwData, pPage);
- pPageMap->insert(valuePage);
- m_mapPages.erase(it);
- // Repeat the loop iteration to add the new page to the new page group
- --i;
- }
- }
- // Create each page marked as visible
- for (CPageIterator it = m_mapPages.begin(); it != m_mapPages.end(); ++it)
- {
- XInsidePage* pPage = it->second;
- const XInsidePageEntry& entry = *pPage->m_pEntry;
- if (entry.bVisible)
- CreateInsidePage(pPage, false);
- }
- // Create, at most, one page marked as visible in each page group
- CPageGroupIterator itGroup = m_mapPageGroups.begin();
- for (; itGroup != m_mapPageGroups.end(); ++itGroup)
- {
- #ifdef _DEBUG
- bool bOneIsVisible = false;
- #endif // _DEBUG
-
- CPageMap* pmap = itGroup->second;
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- XInsidePage* pPage = it->second;
- const XInsidePageEntry& entry = *pPage->m_pEntry;
- if (entry.bVisible)
- {
- #ifdef _DEBUG
- if (bOneIsVisible)
- {
- char sz[_MAX_PATH];
- sprintf(sz, "TCPropertyPageImpl<%hs>::CreateInsidePages(): "
- "More than one entry\n\tin page group 0x%08X was specified"
- "with a bVisible value of true.\n\tOnly the first one has"
- "been created.", TypeName(), entry.idPosCtrl);
- _TRACE1("%hs\n", sz);
- assert(!bOneIsVisible);
- }
- #endif // _DEBUG
- if (CreateInsidePage(pPage, true))
- {
- #ifdef _DEBUG
- bOneIsVisible = true;
- #else // _DEBUG
- break;
- #endif // _DEBUG
- }
- }
- }
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Destroys all instances of embedded property pages.
- //
- // This method is used by the implementation to destroy all instances of
- // embedded property pages, if any. This includes page groups and the pages
- // within them.
- //
- // See Also: TCPropertyPageBase::DestroyInsidePageMap
- void TCPropertyPageBase::DestroyInsidePages()
- {
- // Destroy the main page map
- DestroyInsidePageMap(&m_mapPages);
- // Destroy the page map of each page group
- CPageGroupIterator it;
- for (it = m_mapPageGroups.begin(); it != m_mapPageGroups.end(); ++it)
- {
- CPageMap* pmap = it->second;
- DestroyInsidePageMap(pmap);
- delete pmap;
- }
- // Clear the page group map
- m_mapPageGroups.clear();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Destroys all embedded property pages within a specified map.
- //
- // This method is used by the implementation to destroy all embedded property
- // pages within the specified map and clear the map of all entries.
- //
- // Parameters:
- // pmap - A pointer to the page map for whose pages are to be destroyed.
- //
- // See Also: TCPropertyPageBase::DestroyInsidePages,
- // TCPropertyPageBase::CPageMap
- void TCPropertyPageBase::DestroyInsidePageMap(
- TCPropertyPageBase::CPageMap* pmap)
- {
- // Loop thru each page of the specified map
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- // Get the next page
- XInsidePage* pPage = it->second;
- // Ensure that the page window is destroyed
- assert(!IsWindow(*pPage));
- // Delete the page object
- delete pPage;
- }
- // Clear the map of all dead page entries
- pmap->clear();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves a pointer to an embedded property page, and ensures
- // that a window is created for the page.
- //
- // This method is used by the implementation to retrieve a pointer to the
- // embedded property page specified by /idCtrl/. If the page is not active
- // (does not have a window created for it), it calls CreateInsidePage to
- // create the window.
- //
- // Parameters:
- // idCtrl - The identifier of the embedded property page.
- //
- // Return Value: An XInsidePage pointer to the embedded property page if
- // /idCtrl/ is valid. Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePage,
- // TCPropertyPageBase::GetInsidePage,
- // TCPropertyPageBase::_GetInsidePageOfGroup
- XInsidePage* TCPropertyPageBase::_GetInsidePage(UINT idCtrl)
- {
- // Find the specified control ID in the map of pages
- CPageIterator it = m_mapPages.find(idCtrl);
- if (m_mapPages.end() == it)
- return NULL;
- // Create the page, if not already created
- XInsidePage* pPage = it->second;
- if (!pPage->m_hWnd)
- return CreateInsidePage(pPage, false) ? pPage : NULL;
- return pPage;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Retrieves a pointer to an embedded property page within a
- // group of embedded property pages, and ensures that a window is created for
- // the page.
- //
- // This method is used by the implementation to retrieve a pointer to the
- // embedded property page specified by /dw/, within the embedded property
- // page group specified by /idGroup/. If the page is not active (does not
- // have a window created for it), it calls CreateInsidePage to create the
- // window.
- //
- // Parameters:
- // idGroup - The identifier of the embedded property page group.
- // dw - The application-defined 32-bit (DWORD) value that uniquely
- // identifies the page within the page group.
- //
- // Return Value: An XInsidePage pointer to the embedded property page if
- // /idGroup/ and /dw/ are valid. Otherwise, *NULL*.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePage,
- // TCPropertyPageBase::GetInsidePageOfGroup,
- // TCPropertyPageBase::_GetInsidePage
- XInsidePage* TCPropertyPageBase::_GetInsidePageOfGroup(UINT idGroup,
- DWORD dw)
- {
- // Find the specified group ID in the map of groups
- CPageGroupIterator itGroup = m_mapPageGroups.find(idGroup);
- if (m_mapPageGroups.end() == itGroup)
- return NULL;
- // Find the specified DWORD value in the map of pages for the group
- CPageMap* pmap = itGroup->second;
- CPageIterator it = pmap->find(dw);
- if (pmap->end() == it)
- return NULL;
- // Return the page
- XInsidePage* pPage = it->second;
- return pPage;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Filters a set of objects based on the entries in the property
- // field map.
- //
- // This method is used by the implementation to filter the specified set of
- // objects. Only the objects that support interfaces specified in the entries
- // of the property field map are copied to the destination array.
- //
- // This method first forwards the specified set of objects to each embedded
- // property page, including those within groups. It does this by calling the
- // SetObjectsOfInsidePages method. This gives each embedded property page the
- // opportunity to perform its own filtering from the original set of objects.
- //
- // Next, the method releases the previous set of interface pointers specified
- // by the /cObjectsDest/ and /ppUnkDest/ parameters and deletes the array. A
- // new array is then created and stored in the same parameters. The new array
- // is populated with the filtered set of objects.
- //
- // Finally, if the property page is active (a window has been created for
- // it), the UpdateFields and SetAllAdvises methods are called. If the page is
- // not active, those method calls are deferred to OnInitDialogHandler, which
- // will be called when the page does become active.
- //
- // TODO: Shouldn't the advises be set /prior/ to UpdateFields?
- //
- // Parameters:
- // cObjectsDest - [in, out] A reference to the number of *IUnknown* „
- // pointers in the array pointed to by /ppUnkDest/. The referenced variable
- // also receives the count of filtered objects upon return.
- // ppUnkDest - [in, out] A reference to a pointer to an array of
- // *IUnknown* interface pointers which is replaced with a pointer to the
- // filtered array of objects upon return.
- // cObjects - [in] The number of *IUnknown* pointers in the array pointed
- // to by /ppUnk/.
- // ppUnk - [in] A pointer to an array of *IUnknown* interface pointers
- // where each pointer identifies a unique object affected by the property
- // page. This array is considered the /original/ set, from which the
- // /filtered/ set is determined.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::SetObjectsOfInsidePages,
- // TCPropertyPageBase::UpdateFields,
- // TCPropertyPageBase::SetAllAdvises,
- // TCPropertyPageBase::OnInitDialogHandler
- HRESULT TCPropertyPageBase::SetObjects(ULONG& cObjectsDest,
- IUnknown**& ppUnkDest, ULONG cObjects, IUnknown** ppUnk)
- {
- // Only save each object that this page knows how to talk to
- HRESULT hr = S_OK;
- CUnkVector pVec = NULL;
- __try
- {
- // Forward the method to each embedded property page, including groups
- if (SUCCEEDED(hr = SetObjectsOfInsidePages(cObjects, ppUnk)))
- {
- // Loop thru the specified objects, filtering out the unknown ones
- ReleaseSupportedInterfaces();
- CUnkVector& vec = *(pVec = new CUnkVector);
- for (ULONG i = 0; i < cObjects; i++)
- if (ppUnk[i] && IsObjectKnown(ppUnk[i]))
- vec.push_back(ppUnk[i]);
- // Release the previous set of destination interface pointers
- for (UINT iObj = 0; iObj < cObjectsDest; ++iObj)
- ppUnkDest[iObj]->Release();
- if (ppUnkDest != NULL)
- {
- delete [] ppUnkDest;
- ppUnkDest = NULL;
- cObjectsDest = 0;
- }
- assert(0 == cObjectsDest);
- // Save the filtered objects in the specified destination fields
- if (vec.size())
- {
- ATLTRY(ppUnkDest = new IUnknown*[vec.size()]);
- if (NULL == ppUnkDest)
- hr = E_OUTOFMEMORY;
- else
- {
- for (i = 0; i < vec.size(); ++i)
- (ppUnkDest[i] = vec[i])->AddRef();
- cObjectsDest = vec.size();
- }
- }
- // Populate the dialog fields and set all advises, if the window exists
- if (SUCCEEDED(hr) && ::IsWindow(GetPageWindow()))
- {
- // TODO: Shouldn't the advises be set /prior/ to UpdateFields?
- UpdateFields();
- SetAllAdvises(cObjectsDest, ppUnkDest);
- }
- }
- }
- __except(1)
- {
- _TRACE1(
- "TCPropertyPageBase[%hs]::SetObjects(): Unknown Exception Caught!\n",
- TypeName());
- // Remove and unadvise all connections
- ClearAllAdvises();
- // Release any objects saved for inside pages
- ReleaseObjectsForInsidePages();
- // Release the previous set of interface pointers
- ReleaseSupportedInterfaces();
- for (UINT iObj = 0; iObj < cObjectsDest; ++iObj)
- ppUnkDest[iObj]->Release();
- if (ppUnkDest != NULL)
- {
- delete [] ppUnkDest;
- ppUnkDest = NULL;
- cObjectsDest = 0;
- }
- // Update dialog fields from objects, if the window exists
- if (::IsWindow(GetPageWindow()))
- UpdateFields();
- // Interpret the exception as a server exception
- hr = RPC_E_SERVERFAULT;
- }
- // Delete the vector object, if we used one
- if (pVec)
- delete pVec;
- // Return last result
- return hr;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Forwards the original set of objects to each embedded
- // property page, if any.
- //
- // This method is used by the implementation to forward the original set of
- // objects to each embedded property page, if any. This gives each embedded
- // property page the opportunity to perform its own filtering from the
- // original set of objects.
- //
- // Parameters:
- // cObjects - [in] The number of *IUnknown* pointers in the array pointed
- // to by /ppUnk/.
- // ppUnk - [in] A pointer to an array of *IUnknown* interface pointers
- // where each pointer identifies a unique object affected by the property
- // page.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePage,
- // TCPropertyPageBase::SetObjects,
- // TCPropertyPageBase::SaveObjectsForInsidePages
- HRESULT TCPropertyPageBase::SetObjectsOfInsidePages(ULONG cObjects,
- IUnknown** ppUnk)
- {
- // Save the entire array of objects for use by inside pages
- SaveObjectsForInsidePages(cObjects, ppUnk);
- // Forward the method to each embedded property page
- for (CPageIterator it = m_mapPages.begin(); it != m_mapPages.end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if (pPage->m_hWnd)
- RETURN_FAILED(pPage->SetObjects(cObjects, ppUnk));
- }
- // Forward the method to each embedded property page of each group
- CPageGroupIterator itGroup = m_mapPageGroups.begin();
- for (; itGroup != m_mapPageGroups.end(); ++itGroup)
- {
- CPageMap* pmap = itGroup->second;
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if (pPage->m_hWnd)
- RETURN_FAILED(pPage->SetObjects(cObjects, ppUnk));
- }
- }
- // Indicate success
- return S_OK;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Saves the original set of objects in order to be able to
- // forward them on to any new embedded property pages, if any.
- //
- // This method is used by the implementation to save the original set of
- // objects. This allows any new embedded property pages to be given the
- // opportunity to perform its own filtering from the original set of
- // objects.
- //
- // Parameters:
- // cObjects - [in] The number of *IUnknown* pointers in the array pointed
- // to by /ppUnk/.
- // ppUnk - [in] A pointer to an array of *IUnknown* interface pointers
- // where each pointer identifies a unique object affected by the property
- // page.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePage,
- // TCPropertyPageBase::SetObjects,
- // TCPropertyPageBase::SetObjectsOfInsidePages
- void TCPropertyPageBase::SaveObjectsForInsidePages(ULONG cObjects,
- IUnknown** ppUnk)
- {
- // Do nothing if there are no table entries
- if (!GetInsidePageTable(NULL, m_iTable))
- return;
- // Release any current array of objects
- ReleaseObjectsForInsidePages();
- // Copy the specified array of objects
- m_vecForInsidePages.resize(cObjects, NULL);
- for (ULONG i = 0; i < cObjects; ++i)
- {
- IUnknown* punk = ppUnk[i];
- m_vecForInsidePages[i] = punk;
- if (punk)
- punk->AddRef();
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Forwards the original set of objects to an embedded property
- // page when it is first created.
- //
- // This method is used by the implementation to forward the original set of
- // objects to the embedded property page specified byt /pPage/. The original
- // set of objects is saved by the SaveObjectsForInsidePages method. This
- // allows the freshly-created embedded property page the opportunity to
- // perform its own filtering from the original set of objects.
- //
- // Parameters:
- // pPage - A pointer to the embedded property page just create, to which
- // the original set of objects will be forwarded.
- //
- // See Also: Embedded Property Page Table Macros, TCInsidePropPage,
- // TCPropertyPageBase::SaveObjectsForInsidePages,
- // TCPropertyPageBase::CreateInsidePage
- HRESULT TCPropertyPageBase::SetObjectsToInsidePage(TCInsidePropPage* pPage)
- {
- ULONG cObjects = m_vecForInsidePages.size();
- IUnknown** ppUnk = m_vecForInsidePages.begin();
- return pPage->SetObjects(cObjects, ppUnk);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Forwards the /Apply/ operation to each embedded property
- // page, if any.
- //
- // This method is used by the implementation to forward the /Apply/ operation
- // to each embedded property page, if any.
- //
- // See Also: Embedded Property Page Table Macros, XInsidePage,
- // TCPropertyPageImpl::Apply
- HRESULT TCPropertyPageBase::ApplyToInsidePages()
- {
- // Forward the method to each embedded property page
- for (CPageIterator it = m_mapPages.begin(); it != m_mapPages.end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if ((IsWindow(*pPage) && pPage->IsWindowVisible())
- || pPage->m_pEntry->bAlwaysApply)
- RETURN_FAILED(pPage->Page_Apply());
- }
- // Forward the method to each embedded property page of each group
- CPageGroupIterator itGroup = m_mapPageGroups.begin();
- for (; itGroup != m_mapPageGroups.end(); ++itGroup)
- {
- CPageMap* pmap = itGroup->second;
- CPageIterator itVisible = pmap->end();
- for (CPageIterator it = pmap->begin(); it != pmap->end(); ++it)
- {
- XInsidePage* pPage = it->second;
- if (IsWindow(*pPage))
- {
- if (pPage->IsWindowVisible())
- itVisible = it;
- else if (pPage->m_pEntry->bAlwaysApply)
- RETURN_FAILED(pPage->Page_Apply());
- }
- }
- if (pmap->end() != itVisible)
- {
- XInsidePage* pPage = itVisible->second;
- RETURN_FAILED(pPage->Page_Apply());
- }
- }
- // Indicate success
- return S_OK;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Releases the original set of objects that are maintained for
- // when a new embedded property page is created.
- //
- // This method is used by the implementation to release the original set of
- // objects that were saved by the SaveObjectsForInsidePages method.
- //
- // See Also: Embedded Property Page Table Macros,
- // TCPropertyPageBase::SaveObjectsForInsidePages
- void TCPropertyPageBase::ReleaseObjectsForInsidePages()
- {
- CUnkIterator it = m_vecForInsidePages.begin();
- for (; it != m_vecForInsidePages.end(); ++it)
- {
- IUnknown* punk = *it;
- if (punk)
- punk->Release();
- }
- m_vecForInsidePages.clear();
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Releases the set of interfaces supported by this property
- // page.
- //
- // This method is used by the implementation to release the set of interfaces
- // supported by this property page, as previously determined from the
- // property field map by the CreateInsidePages method.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::CreateInsidePages
- void TCPropertyPageBase::ReleaseSupportedInterfaces()
- {
- CUnkVectorMap::iterator it = m_mapInterfaces.begin();
- for (; m_mapInterfaces.end() != it; ++it)
- {
- CUnkVector& vec = it->second;
- for (CUnkIterator itUnk = vec.begin(); vec.end() != itUnk; ++itUnk)
- {
- IUnknown* punk = *itUnk;
- punk->Release();
- }
- vec.clear();
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Establishes *IPropertyNotifySink* advisory connections with
- // each of the specified objects.
- //
- // This method is used by the implementation to establish
- // *IPropertyNotifySink* advisory connections with each of the specified
- // objects. Special care is taken to ensure that an objects that is already
- // connected is not broken and immediately reconnected, which would incur
- // unnecessary DCOM round-trips.
- //
- // After established all of the connections, the OnSetAllAdvises virtual
- // override is called to allow the derived class an opportunity to establish
- // any other advisory connections it may need.
- //
- //
- // See Also: TCPropertyPageBase::ClearAllAdvises,
- // TCPropertyPageBase::SetAdvises, TCPropertyPageBase::OnSetAllAdvises
- void TCPropertyPageBase::SetAllAdvises(ULONG cObjects, IUnknown** ppUnk)
- {
- // Keep a set of IConnectionPointContainer pointers
- typedef std::set<IConnectionPointContainer*> CCPCSet;
- typedef CCPCSet::iterator CCPCSetIterator;
- CCPCSet setCPC;
- // Set advises on each object
- IUnknown* punkThis = GetPageUnknown();
- IUnknown** ppunkEnd = ppUnk + cObjects;
- for (IUnknown** it = ppUnk; it != ppunkEnd; ++it)
- {
- IConnectionPointContainer* pCPC = SetAdvises(*it, punkThis);
- if (NULL != pCPC)
- setCPC.insert(pCPC);
- }
- // Remove and unadvise each map item not in the array of objects
- CAdviseIterator itAdv = m_mapAdvise.begin();
- while (itAdv != m_mapAdvise.end())
- {
- // Lookup the object in the set
- CCPCSetIterator itCPC = setCPC.find(itAdv->first);
- if (setCPC.end() == itCPC)
- itAdv = m_mapAdvise.erase(itAdv);
- else
- ++itAdv;
- }
- // Allow derived classes to set advises
- OnSetAllAdvises(cObjects, ppUnk);
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Establishes a single *IPropertyNotifySink* advisory
- // connection with the specified object.
- //
- // This method is used by the implementation to establish a single
- // *IPropertyNotifySink* advisory connection with the specified object.
- //
- // See Also: TCPropertyPageBase::SetAdvises
- IConnectionPointContainer* TCPropertyPageBase::SetAdvises(
- IUnknown* punk, IUnknown* punkThis)
- {
- IConnectionPointContainer* pResult = NULL;
- TCAdviseHolder pAdv = new TCAdviseHolder;
- __try
- {
- // Find the IID_IPropertyNotifySink connection point
- TCAdviseHolder& adv = *pAdv;
- hr = adv.FindConnectionPoint(punk, IID_IPropertyNotifySink)
- if (SUCCEEDED(hr))
- {
- // Ensure that we don't already hold an advise on this object
- if (m_mapAdvise.end() == m_mapAdvise.find(adv.GetCPC()))
- {
- // Insert the connection advise holder into the map
- if (SUCCEEDED(hr = adv.Advise(punkThis)))
- m_mapAdvise.insert(CAdviseMap::value_type(adv.GetCPC(), adv));
- }
- // Return the IConnectionPointContainer pointer as identity
- pResult = adv.GetCPC();
- }
- }
- __except(1)
- {
- _TRACE1("%hs: Caught an unknown exception\n", szFn);
- return NULL;
- }
- // Delete the advise holder
- delete pAdv;
- // Return the last result
- return pResult;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Group=Message Handlers
- /////////////////////////////////////////////////////////////////////////////
- // Description: Message handler for *WM_INITDIALOG*.
- //
- // Handles the *WM_INITDIALOG* window message by creating any embedded
- // property pages needed, establishing advisory connections, allowing the
- // derived class to initialize itself, and updating the fields of the
- // property page. Within the scope of this method, the m_bInitializing data
- // member is set to *true*, returning to *false* at the end of the scope.
- //
- // See Also: TCPropertyPageBase::OnInitDialog,
- // TCPropertyPageBase::m_bInitializing
- void TCPropertyPageBase::OnInitDialogHandler(ULONG cObjects,
- IUnknown** ppUnk)
- {
- // Set the initialization flag
- m_bInitializing = true;
- // Create the embedded property pages
- CreateInsidePages();
- // Set the advises for all the objects
- if (!m_mapAdvise.size())
- SetAllAdvises(cObjects, ppUnk);
- // Allow derived class to initialize controls and such
- bool bResult = OnInitDialog();
- // Update dialog fields from objects
- UpdateFields();
- // Reset the initialization flag
- m_bInitializing = false;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Message handler for the TCPropertyPageImpl::wm_OnChanged
- // message.
- //
- // Handles the TCPropertyPageImpl::wm_OnChanged window message which is
- // posted from TCPropertyPageImpl's implementation of the
- // *IPropertyNotifySink::OnChanged* interface method. That method posts the
- // message in order to defer processing of the property change notification
- // onto the window's main thread.
- //
- // This method simply calls the UpdateFields method with the DISPID of the
- // property that has changed.
- //
- // See Also: Property Page Field Update Macros,
- // TCPropertyPageBase::UpdateFields, TCPropertyPageImpl::wm_OnChanged
- LRESULT TCPropertyPageBase::OnChangedHandler(UINT, WPARAM wp, LPARAM, BOOL&)
- {
- // Parse the message parameters
- DISPID dispid = DISPID(wp);
- _TRACE3("TCPropertyPageBase[%hs]::OnChangedHandler(): dispid = 0x%08X (%d)\n",
- TypeName(), dispid, dispid);
- // Update dialog fields from objects
- UpdateFields(dispid);
- // Obligatory return code
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Description: Message handler for *WM_NCDESTROY*.
- //
- // Handles the *WM_NCDESTROY* window message by calling ClearAllAdvises and
- // DestroyInsidePages.
- //
- // See Also: TCPropertyPageBase::ClearAllAdvises,
- // TCPropertyPageBase::DestroyInsidePages
- LRESULT TCPropertyPageBase::OnNcDestroyHandler(UINT, WPARAM, LPARAM,
- BOOL& bHandled)
- {
- _TRACE1("TCPropertyPageBase[%hs]::OnNcDestroyHandler()\n", TypeName());
- // Remove and unadvise all connections
- ClearAllAdvises();
- // Destroy the embedded property pages
- DestroyInsidePages();
- // Allow default processing
- return bHandled = FALSE;
- }
|