///////////////////////////////////////////////////////////////////////////// // PropertyPageSite.cpp | Implementation of the TCPropertyPageSite class. // #include "pch.h" #include "..\Inc\TCLib.h" #include "PropertyPageSite.h" #include "AutoHandle.h" ///////////////////////////////////////////////////////////////////////////// // TCPropertyPageSite ///////////////////////////////////////////////////////////////////////////// // Group=Construction / Destruction ///////////////////////////////////////////////////////////////////////////// // Parameters: // clsidPage - The CLSID of a property page to be created and managed by // this object. Calls Page_Create to create the object. // pPage - An IPropertyPage* of an existing property page component object // to be managed by this object. Calls Page_Attach to attach to the page. // // See Also: TCPropertyPageSite::Page_Create, TCPropertyPageSite::Page_Attach TCPropertyPageSite::TCPropertyPageSite() { CommonConstruct(); } TCPropertyPageSite::TCPropertyPageSite(REFCLSID clsidPage) { CommonConstruct(); HRESULT hr = Page_Create(clsidPage); ZSucceeded(hr); } TCPropertyPageSite::TCPropertyPageSite(IPropertyPage* pPage) { CommonConstruct(); HRESULT hr = Page_Attach(pPage); ZSucceeded(hr); } TCPropertyPageSite::~TCPropertyPageSite() { CommonDestruct(); } ///////////////////////////////////////////////////////////////////////////// // Description: Creates and attaches to a property page component object. // // Attempts to create an instance of the property page component object // specified by the /clsidPage/ CLSID. If successful, this method delegates // to the Page_Attach method and saves the page's CLSID. // // Parameters: // clsidPage - The CLSID of the property page to be created and managed by // this object. // // Return Value: S_OK if successful, otherwise a standard COM error code. // // See Also: TCPropertyPageSite::Page_Attach, TCPropertyPageSite::GetClassID HRESULT TCPropertyPageSite::Page_Create(REFCLSID clsidPage) { // Attempt to create the specified property page IPropertyPagePtr pPage; HRESULT hr = pPage.CreateInstance(clsidPage); if (FAILED(hr)) return hr; // Delegate to the Attach method if (FAILED(hr = Page_Attach(pPage))) return hr; // Save the page's CLSID m_clsid = clsidPage; // Indicate success return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Description: Attaches an existing IPropertyPage interface. // // Manages the specified IPropertyPage interface and sets m_xPageSite as the // page's site by calling IPropertyPage::SetPageSite. It then retrieves and // stores the page's general informatioin by calling the // IPropertyPage::GetPageInfo method and informs the page, by calling the // IPropertyPage::SetObjects method, of the array of objects which it will // be editing. If the site window is visible, the Page_Show method is called // to activate and display the property page. // // This method is used internally (by Page_Create) and does not need to be // called directly. It is public, however, to allow a more advanced usage. // // When this method is called directly (not from Page_Create), the CLSID of // the property page cannot be determined, so GetClassID will return // CLSID_NULL. // // Parameters: // pPage - An IPropertyPage* of an existing property page component object // to be managed by this object. // // Return Value: S_OK if successful, otherwise the result of the failed // interface method. // // See Also: TCPropertyPageSite::constructor, // TCPropertyPageSite::Page_Create, TCPropertyPageSite::Page_Show, // TCPropertyPageSite::OnGetWindow, TCPropertyPageSite::GetTitle, // TCPropertyPageSite::GetSize, TCPropertyPageSite::GetDocString, // TCPropertyPageSite::GetHelpFile, TCPropertyPageSite::GetHelpContext, // TCPropertyPageSite::SetObjects HRESULT TCPropertyPageSite::Page_Attach(IPropertyPage* pPage) { // Ensure that no previous page is attached assert(NULL == m_pPage); // Set ourself as the page site for the page HRESULT hr = pPage->SetPageSite(&m_xPageSite); if (FAILED(hr)) return hr; // Get the page information hr = pPage->GetPageInfo(&m_info); if (FAILED(hr)) return hr; // Set the objects of the page if (m_vecObjects.size()) { std::vector vecUnk; vecUnk.resize(m_vecObjects.size()); std::copy(m_vecObjects.begin(), m_vecObjects.end(), vecUnk.begin()); hr = pPage->SetObjects(vecUnk.size(), vecUnk.begin()); if (FAILED(hr)) return hr; } // Save the page pointer m_pPage = pPage; // Show the page if the page site window is visible HWND hwnd = OnGetWindow(); if (NULL != hwnd && ::IsWindowVisible(hwnd)) hr = Page_Show(); // Indicate success return hr; } ///////////////////////////////////////////////////////////////////////////// // Description: Detaches the managed property page. // // Detaches the managed property page by releasing the strings in m_info, // deactivating the property page, if active, and detaching the IPropertyPage // interface pointer. // // TODO: Should this also set the managed property page's site to NULL? // // Return Value: The IPropertyPage interface pointer that was detached from // this site object. // // See Also: TCPropertyPageSite::constructor, TCPropertyPageSite::destructor, // TCPropertyPageSite::Page_Create, TCPropertyPageSite::Page_Attach, // TCPropertyPageSite::m_info IPropertyPage* TCPropertyPageSite::Page_Detach() { __try { // Release the PROPPAGEINFO structure CoTaskMemFree(m_info.pszTitle); CoTaskMemFree(m_info.pszDocString); CoTaskMemFree(m_info.pszHelpFile); ZeroMemory(&m_info, sizeof(m_info)); m_info.cb = sizeof(m_info); // Deactivate the page, if it is activated if (m_bActivated && NULL != m_pPage) m_pPage->Deactivate(); m_bActivated = false; // Clear the CLSID of the page m_clsid = CLSID_NULL; // Detach the pointer return m_pPage.Detach(); } __except(1) { _TRACE0("TCPropertyPageSite::Detach(): Exception Caught!\n"); return NULL; } } ///////////////////////////////////////////////////////////////////////////// // Description: Common construction processing. // // Performs common construction processing. void TCPropertyPageSite::CommonConstruct() { m_xPageSite.m_pThis = this; m_clsid = CLSID_NULL; ZeroMemory(&m_info, sizeof(m_info)); m_info.cb = sizeof(m_info); m_bActivated = false; m_bDirty = false; } ///////////////////////////////////////////////////////////////////////////// // Description: Common destruction processing. // // Destructs the object by calling Page_Detach and releasing the detached // pointer. // // See Also: TCPropertyPageSite::destructor, TCPropertyPageSite::Page_Detach void TCPropertyPageSite::CommonDestruct() { __try { IPropertyPage* pPage = Page_Detach(); if (NULL != pPage) pPage->Release(); } __except(1) { _TRACE0("TCPropertyPageSite::CommonDestruct(): Exception Caught!\n"); } } ///////////////////////////////////////////////////////////////////////////// // Group=Attributes ///////////////////////////////////////////////////////////////////////////// // Description: Provides the IUnknown pointers of the objects affected by // the managed property page. // // Provides the IUnknown pointers of the objects affected by the managed // property page. The pointers are copied to the m_vecObjects data member. If // a property page is attached, the IPropertyPage::SetObjects method of the // page is called. // // Parameters: // cObjects - [in] Number of *IUnknown* pointers in the array pointed to by // /ppUnk/. // ppUnk - [in] Pointer to an array of *IUnknown* interface pointers where // each pointer identifies a unique object affected by the managed property // page. // // Return Value: S_OK if successful, otherwise the return code from the // property page's interface method. HRESULT TCPropertyPageSite::SetObjects(ULONG cObjects, IUnknown** ppUnk) { // Release any previous vector of objects m_vecObjects.clear(); // Copy the specified array to the vector of objects m_vecObjects.resize(cObjects); std::copy(ppUnk, ppUnk + cObjects, m_vecObjects.begin()); // Set the objects of the page, if the page exists if (NULL != m_pPage) return m_pPage->SetObjects(cObjects, ppUnk); // Indicate success return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Group=Operations ///////////////////////////////////////////////////////////////////////////// // Description: Message processing method to be called by the derived class. // // Handles the WM_CREATE, WM_SIZE, and WM_DESTROY window messages to affect // the managed property page appropriately. // // A derived class must call this somewhere in it's message handling logic. // For an MFC CWnd-derived class, the OnWndMsg virtual function is and ideal // place for this: // // BOOL TCActiveXPropertyPage::OnWndMsg(UINT message, WPARAM wParam, // LPARAM lParam, LRESULT* plResult) // { // // Allow the TCPropertyPageSite class a crack at the message // if (OnPageSiteWndMsg(message, wParam, lParam, plResult)) // return TRUE; // … // // Perform default processing // return CPropertyPage::OnWndMsg(message, wParam, lParam, plResult); // } // // Return Value: TRUE if message processing should cease; otherwise FALSE. // // Parameters: // message - [in] Specifies the message being processed. // wParam - [in] Specifies additional message-dependent information. // lParam - [in] Specifies additional message-dependent information. // plResult - [out] The return value of the message handling. BOOL TCPropertyPageSite::OnPageSiteWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* plResult) { // Handle certain messages switch (message) { case WM_CREATE: { // Ensure that the page is activated if (!m_bActivated && FAILED(Activate())) { *plResult = LRESULT(-1); return TRUE; } break; } case WM_SIZE: { // Size the property page to match if (NULL != m_pPage) { RECT rect = {0, 0, LOWORD(lParam), HIWORD(lParam)}; m_pPage->Move(&rect); } break; } case WM_DESTROY: { // Deactivate the page, if activated if (m_bActivated) { m_pPage->Deactivate(); m_bActivated = false; } break; } } // Allow processing to continue return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Description: Displays the managed property page. // // Displays the managed property page by first activating the page, if not // already active, and then calling the IPropertyPage::Show method with the // SW_SHOW parameter. // // Return Value: S_OK if successful, otherwise the return code from the // property page's interface method. // // See Also: TCPropertyPageSite::Page_Hide, TCPropertyPageSite::Activate HRESULT TCPropertyPageSite::Page_Show() { // Activate the page, if not already active HRESULT hr; if (!m_bActivated && FAILED(hr = Activate())) return hr; // Show the property page and this window hr = m_pPage->Show(SW_SHOW); return hr; } ///////////////////////////////////////////////////////////////////////////// // Description: Hides the managed property page. // // Hides the managed property page by calling the IPropertyPage::Show method // with the SW_HIDE parameter. // // Return Value: S_OK if successful, otherwise the return code from the // property page's interface method. // // See Also: TCPropertyPageSite::Page_Show HRESULT TCPropertyPageSite::Page_Hide() { // Hide the property page return m_pPage->Show(SW_HIDE); } ///////////////////////////////////////////////////////////////////////////// // Description: Displays help for the managed property page. // // Displays help for the managed property page by first deriving the path // name for the page's help file. The "HelpDir" and "InProcServer32" registry // subkeys are used, in that order, to determine where in the file system the // page's help file might be located. This path is then specified in a call // to the IPropertyPage::Help method, which allows the page to display it's // help in some alternate way. If that method call fails, the GetHelpFile and // GetHelpContext methods are used in a call to the Win32 WinHelp API. // // Return Value: S_OK if successful, otherwise the return code from the // property page's failed interface method or from a failed registry API. // // See Also: TCPropertyPageSite::GetHelpFile, // TCPropertyPageSite::GetHelpContext, TCRegKeyHandle HRESULT TCPropertyPageSite::Page_Help() { // Create the registry key name OLECHAR szCLSID[_MAX_PATH] = OLESTR("CLSID\\"); int cchCLSIDKey = wcslen(szCLSID); // Convert the stored CLSID to a string representation StringFromGUID2(GetClassID(), szCLSID + cchCLSIDKey, sizeofArray(szCLSID) - cchCLSIDKey); // Open the registry key DWORD dw; USES_CONVERSION; TCRegKeyHandle hkey; LRESULT lr = RegCreateKeyEx(HKEY_CLASSES_ROOT, OLE2T(szCLSID), 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dw); if (ERROR_SUCCESS != lr) return lr; // Open the registry subkey TCHAR szPath[_MAX_PATH]; TCRegKeyHandle hkeySub; lr = RegCreateKeyEx(hkey, TEXT("HelpDir"), 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeySub, &dw); if (ERROR_SUCCESS == lr) { // Read the default subkey value DWORD dwType = REG_SZ, cbData = sizeof(szPath); lr = RegQueryValueEx(hkeySub, NULL, NULL, &dwType, (PBYTE)szPath, &cbData); } // Try another registry subkey if "HelpDir" failed if (ERROR_SUCCESS != lr) { lr = RegCreateKeyEx(hkey, TEXT("InProcServer32"), 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeySub, &dw); if (ERROR_SUCCESS == lr) { // Read the default subkey value DWORD dwType = REG_SZ, cbData = sizeof(szPath); if (ERROR_SUCCESS == (lr = RegQueryValueEx(hkeySub, NULL, NULL, &dwType, (PBYTE)szPath, &cbData))) { // Trim down to just the pathname TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR]; _tsplitpath(szPath, szDrive, szDir, NULL, NULL); _tmakepath(szPath, szDrive, szDir, NULL, NULL); } } } // Return if "InProcServer32" failed if (ERROR_SUCCESS != lr) return lr; // Allow the property page to display it's help HRESULT hr = m_pPage->Help(T2COLE(szPath)); if (SUCCEEDED(hr)) return hr; // Property page failed on call to Help, so use PROPPAGEINFO TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR]; _tsplitpath(szPath, szDrive, szDir, NULL, NULL); _tmakepath(szPath, szDrive, szDir, STRTYPE2CT(GetHelpFile()), NULL); if (!WinHelp(OnGetWindow(), szPath, HELP_CONTEXTPOPUP, GetHelpContext())) return HRESULT_FROM_WIN32(::GetLastError()); // Indicate success return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Description: Processes keystroke messages. // // Simply delegates to the IPropertyPage::TranslateAccelerator method. // // Parameters: // pMsg - [in] Pointer to the MSG structure describing the keystroke to // process. // // Return Value: S_OK if successful, otherwise the return code from the // property page's interface method. HRESULT TCPropertyPageSite::Page_TranslateAccelerator(MSG* pMsg) { assert(NULL != m_pPage); return m_pPage->TranslateAccelerator(pMsg); } ///////////////////////////////////////////////////////////////////////////// // Description: Queries the property page for the specified interface. // // Delegates to the QueryInterface method of the property page. However, the // interfaces IPropertyPage and IPropertyPage2 are explicitly never supported // through this method. This is to help ensure that the dirty flag of the // property page is always modified through the TCPropertyPageSite class, and // not directly through the IPropertyPage or IPropertyPage2 interfaces. This // could obviously be abused if the property page supported some other // interface that directly modified its dirty flags (e.g. IPropertyPage3). // // Parameters: // riid - Identifier of the interface being requested. // ppvObject - Indirectly points to the interface specified in /iid/. If // the object does not support the interface specified in iid, *ppvObject // is set to NULL. // // Return Value: S_OK if the interface is supported, E_NOINTERFACE if not. HRESULT TCPropertyPageSite::Page_QI(REFIID iid, void** ppvObject) { // Check for forbidden interface if (IID_IPropertyPage == iid || IID_IPropertyPage2 == iid) return E_NOINTERFACE; // Otherwise, delegate to the property page assert(NULL != m_pPage); return m_pPage->QueryInterface(iid, ppvObject); } ///////////////////////////////////////////////////////////////////////////// // Group=Overrides ///////////////////////////////////////////////////////////////////////////// // Description: Override to perform additional processing of the // IPropertyPageSite::OnStatusChange interface method. // // A derived class can override this to perform additional processing when // the IPropertyPageSite::OnStatusChange interface method is called by the // managed property page. // // Parameters: // dwFlags - [in] Flags to indicate what changes have occurred. // // Return Value: S_OK to indicate that the status change was noted. // // See Also: TCPropertyPageSite::XPageSite::OnStatusChange HRESULT TCPropertyPageSite::OnStatusChange(DWORD dwFlags) { UNUSED(dwFlags); return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Description: Override to perform additional processing of the // IPropertyPageSite::GetLocaleID interface method. // // A derived class can override this to provide a locale ID to the managed // property page. The default implementation returns the current thread's // locale. // // Parameters: // pLocaleID - [out] Pointer to locale identifier. // // Return Value: S_OK to indicate that the locale was returned successfully. // // See Also: TCPropertyPageSite::XPageSite::GetLocaleID HRESULT TCPropertyPageSite::OnGetLocaleID(LCID* pLocaleID) { *pLocaleID = GetThreadLocale(); return S_OK; } ///////////////////////////////////////////////////////////////////////////// // Description: Override to perform additional processing of the // IPropertyPageSite::GetPageContainer interface method. // // A derived class can override this to provide an interface pointer of the // interface pointer to the managed property page. The default // implementation simply returns E_NOTIMPL. // // Parameters: // ppUnk - [out] Address of IUnknown* pointer variable that receives the // interface pointer to the container object. // // Return Value: E_NOTIMPL is the only return value allowed at this time. See // TCPropertyPageSite::XPageSite::GetPageContainer for possible ideas of how // this could be used. // // See Also: TCPropertyPageSite::XPageSite::GetPageContainer HRESULT TCPropertyPageSite::OnGetPageContainer(IUnknown** ppUnk) { UNUSED(ppUnk); return E_NOTIMPL; } ///////////////////////////////////////////////////////////////////////////// // Description: Override to perform additional processing of the // IPropertyPageSite::TranslateAccelerator interface method. // // A derived class can override this to process a keystroke message, if it // desires. The default implementation simply returns E_NOTIMPL. // // Parameters: // pMsg - [in] Pointer to the MSG structure describing the keystroke to // process. // // Return Value: // S_OK - The page site processed the message. // S_FALSE - The page site did not process the message. // E_NOTIMPL - The page site does not support keyboard processing. // // See Also: TCPropertyPageSite::XPageSite::TranslateAccelerator HRESULT TCPropertyPageSite::OnTranslateAccelerator(MSG* pMsg) { UNUSED(pMsg); return E_NOTIMPL; } ///////////////////////////////////////////////////////////////////////////// // Description: Override to specify if the page site's frame window is modal // or modeless. // // A derived class can override this to specify that it's frame window is // modeless. The default returns TRUE, indicating that the site's frame // window is modal. This is used by the Activate method to supply a parameter // to the IPropertyPage::Activate interface method. // // Return Value: TRUE to specify that the site's frame window is modal; FALSE // to specify that it's modeless. // // See Also: TCPropertyPageSite::Activate BOOL TCPropertyPageSite::OnIsModal() { return TRUE; } ///////////////////////////////////////////////////////////////////////////// // Description: Override to specify the page site's window. // // A derived class should override this to specify it's site window. This // override is provided so that the class is independent of any particular // windowing framework, aside from Win32 itself. // // Return Value: The page site's window. This window will be used as the // parent window of the managed property page's window. // // TODO: Shouldn't this method be *pure* virtual to enforce a derived class // to override it? // // See Also: TCPropertyPageSite::Activate HWND TCPropertyPageSite::OnGetWindow() { return NULL; } ///////////////////////////////////////////////////////////////////////////// // Group=Implementation ///////////////////////////////////////////////////////////////////////////// // Description: Activates the managed property page. // // Activates the managed property page, if not already active. The // IPropertyPage::Activate method of the managed property page is used to // create the property page window in the entire client area of the site's // window. // // Note: Upon activating the property page, the window styles of the page // site and property page windows are modified to enable Win32's built-in // child dialog box keyboard handling. After many futile attempt, this proved // to be much easier and more compatible than attempting to use the // TranslateAccelerators interface methods. // // Return Value: S_OK if successful, otherwise the return code from the // property page's interface method. // // See Also: TCPropertyPageSite::OnGetWindow, TCPropertyPageSite::OnIsModal HRESULT TCPropertyPageSite::Activate() { __try { // Do nothing if page is already activated if (m_bActivated) { _TRACE0("TCPropertyPageSite::Activate(): Already activated.\n"); return S_OK; } // Get the page site window HWND hwnd = OnGetWindow(); assert(NULL != hwnd); // Compute the page's rectangle RECT rect; ::GetClientRect(hwnd, &rect); // Activate the property page HRESULT hr = m_pPage->Activate(hwnd, &rect, OnIsModal()); if (m_bActivated = SUCCEEDED(hr)) { // Modify the style and extended style of this window UINT nFlags = SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE; DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); DWORD dwStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE); if (WC_DIALOG == MAKEINTRESOURCE(GetClassLong(hwnd, GCW_ATOM))) { SetWindowLong(hwnd, GWL_STYLE, dwStyle | DS_CONTROL); SetWindowLong(hwnd, GWL_EXSTYLE, dwStyleEx | WS_EX_CONTROLPARENT); SetWindowPos(hwnd, NULL, 0, 0, 0, 0, nFlags); } // Modify the style and extended style of all child dialog windows hwnd = ::GetWindow(hwnd, GW_CHILD); while (NULL != hwnd) { if (WC_DIALOG == MAKEINTRESOURCE(GetClassLong(hwnd, GCW_ATOM))) { dwStyle = GetWindowLong(hwnd, GWL_STYLE); SetWindowLong(hwnd, GWL_STYLE, dwStyle | DS_CONTROL); dwStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, dwStyleEx | WS_EX_CONTROLPARENT); SetWindowPos(hwnd, NULL, 0, 0, 0, 0, nFlags); } hwnd = ::GetWindow(hwnd, GW_HWNDNEXT); } } return hr; } __except(1) { _TRACE0("TCPropertyPageSite::Activate(): Unknown exception.\n"); return E_UNEXPECTED; } } ///////////////////////////////////////////////////////////////////////////// // Group=IUnknown Interface Methods ///////////////////////////////////////////////////////////////////////////// // Description: Returns pointers to supported interfaces. // // Supports the IUnknown and IPropertyPageSite interfaces. // // Return Value: Returns one of the following standard results: // // S_OK - The specified IID is supported on this object. // E_NOINTERFACE - The specified IID is *not* supported on this object. // E_POINTER - /ppvObject/ is an invalid pointer. // // See Also: TCPropertyPageSite STDMETHODIMP TCPropertyPageSite::XPageSite::QueryInterface(REFIID riid, void** ppvObject) { __try { // Determine the requested interface if (IID_IUnknown == riid || IID_IPropertyPageSite == riid) { *((IUnknown**)ppvObject) = this; return S_OK; } // Requested interface is not implemented by this object *ppvObject = NULL; return E_NOINTERFACE; } __except(1) { return E_POINTER; } } ///////////////////////////////////////////////////////////////////////////// // Description: Increments reference count. // // Does nothing since the lifetime of this object is not dependent on a // reference count. // // Return Value: This implementation always returns 1. // // See Also: TCPropertyPageSite STDMETHODIMP_(ULONG) TCPropertyPageSite::XPageSite::AddRef() { return 1; } ///////////////////////////////////////////////////////////////////////////// // Description: Decrements reference count. // // Does nothing since the lifetime of this object is not dependent on a // reference count. // // Return Value: This implementation always returns 1. // // See Also: TCPropertyPageSite STDMETHODIMP_(ULONG) TCPropertyPageSite::XPageSite::Release() { return 1; } ///////////////////////////////////////////////////////////////////////////// // Group=IPropertyPageSite Interface Methods ///////////////////////////////////////////////////////////////////////////// // Description: Indicates that the user has modified property values on the // property page. // // This method is called by the managed property page to indicate a change in // status. This implementation ignores status changes until the page becomes // active. Otherwise, the dirty flag of the site object is set and the // TCPropertyPageSite::OnStatusChange virtual override is called. // // Parameters: // dwFlags - [in] Flags to indicate what changes have occurred. The dwFlags // parameter can contain either of these two values to indicate the type of // status change: // // PROPPAGESTATUS_DIRTY - Values in page have changed so the state of the // Apply button should be updated. // // PROPPAGESTATUS_VALIDATE - Now is an appropriate time to apply changes. // // Return Value: The result of the TCPropertyPageSite::OnStatusChange virtual // override is returned. // // See Also: TCPropertyPageSite, TCPropertyPageSite::OnStatusChange, // TCPropertyPageSite::Page_IsDirty STDMETHODIMP TCPropertyPageSite::XPageSite::OnStatusChange(DWORD dwFlags) { // Display a trace message under _DEBUG builds #ifdef _DEBUG _bstr_t bstrFlags; if (dwFlags & PROPPAGESTATUS_DIRTY) bstrFlags += L"PROPPAGESTATUS_DIRTY "; if (dwFlags & PROPPAGESTATUS_VALIDATE) bstrFlags += L"PROPPAGESTATUS_VALIDATE "; if (dwFlags & PROPPAGESTATUS_CLEAN) bstrFlags += L"PROPPAGESTATUS_CLEAN"; _TRACE_BEGIN _TRACE_PART2("TCPropertyPageSite::XPageSite::OnStatusChange(0x%08X)\n\t%ls\n", dwFlags, LPCWSTR(bstrFlags)); _TRACE_PART1("\tIsPageDirty() returns %s\n", m_pThis->Page_IsDirty() ? TEXT("true") : TEXT("false")); _TRACE_END #endif // _DEBUG // Ignore status change until page is activated if (!m_pThis->m_bActivated) return S_OK; // Set the dirty flag m_pThis->m_bDirty = true; // Delegate to virtual function return m_pThis->OnStatusChange(dwFlags); } ///////////////////////////////////////////////////////////////////////////// // Description: Returns the locale identifier so the property page can adjust // itself to country-specific settings. // // Returns the locale identifier (an LCID) that the managed property page can // use to adjust itself to the language in use and other country-specific // settings. // // This implementation gets the locale of the current thread and then calls // the TCPropertyPageSite::OnGetLocaleID virtual override. // // Parameters: // pLocaleID - [out] Pointer to locale identifier. // // Return Value: The result of the TCPropertyPageSite::OnGetLocaleID virtual // override is returned. // // See Also: TCPropertyPageSite, TCPropertyPageSite::OnGetLocaleID STDMETHODIMP TCPropertyPageSite::XPageSite::GetLocaleID(LCID* pLocaleID) { __try { // Display a trace message under _DEBUG builds _TRACE0("TCPropertyPageSite::XPageSite::GetLocaleID()\n"); // Initialize the [out] parameter *pLocaleID = GetThreadLocale(); // Delegate to virtual function return m_pThis->OnGetLocaleID(pLocaleID); } __except(1) { return E_POINTER; } } ///////////////////////////////////////////////////////////////////////////// // Description: Returns an IUnknown pointer for the object representing the // entire property frame dialog box that contains all the pages. // // Returns an IUnknown pointer to the object representing the entire property // frame dialog box that contains all the pages. Calling this method could // potentially allow one page to navigate to another. // // However, there are no "container" interfaces currently defined for this // role, so this method always fails in the current standard property frame // implementation. But since the role of TCPropertyPageSite is to create // non-standard property frames, this method could be used as a channel for // property pages to communicate with a custom property frame. // // This implementation initializes */ppUnk/ to NULL and then calls the // TCPropertyPageSite::OnGetPageContainer virtual override. // // Parameters: // ppUnk - [out] Address of IUnknown* pointer variable that receives the // interface pointer to the container object. // // Return Value: The result of the TCPropertyPageSite::OnGetPageContainer // virtual override is returned. // // See Also: TCPropertyPageSite, TCPropertyPageSite::OnGetPageContainer STDMETHODIMP TCPropertyPageSite::XPageSite::GetPageContainer(IUnknown** ppUnk) { __try { // Display a trace message under _DEBUG builds _TRACE0("TCPropertyPageSite::XPageSite::GetPageContainer()\n"); // Initialize the [out] parameter *ppUnk = NULL; // Delegate to virtual function return m_pThis->OnGetPageContainer(ppUnk); } __except(1) { return E_POINTER; } } ///////////////////////////////////////////////////////////////////////////// // Description: Passes a keystroke to the property frame for processing. // // Instructs the page site to process a keystroke if it desires. This // implementation does nothing more than call the // TCPropertyPageSite::OnTranslateAccelerator virtual override. // // Parameters: // pMsg - [in] Pointer to the MSG structure to be processed. // // Return Value: The result of the TCPropertyPageSite::OnTranslateAccelerator // virtual override is returned. // // See Also: TCPropertyPageSite, TCPropertyPageSite::OnTranslateAccelerator STDMETHODIMP TCPropertyPageSite::XPageSite::TranslateAccelerator(MSG* pMsg) { __try { // Display a trace message under _DEBUG builds _TRACE0("TCPropertyPageSite::XPageSite::TranslateAccelerator()\n"); // Delegate to virtual function return m_pThis->OnTranslateAccelerator(pMsg); } __except(1) { return E_POINTER; } }