forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			391 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			391 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | //------------------------------------------------------------------------------
 | ||
|  | // File: CProp.cpp
 | ||
|  | //
 | ||
|  | // Desc: DirectShow base classes - implements CBasePropertyPage class.
 | ||
|  | //
 | ||
|  | // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
 | ||
|  | //------------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  | #undef NOMINMAX
 | ||
|  | #include <streams.h>
 | ||
|  | 
 | ||
|  | #ifndef max
 | ||
|  | #define max(a, b) (((a) > (b)) ? (a) : (b))
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #ifndef min
 | ||
|  | #define min(a, b) (((a) < (b)) ? (a) : (b))
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | // Constructor for the base property page class. As described in the header
 | ||
|  | // file we must be initialised with dialog and title resource identifiers.
 | ||
|  | // The class supports IPropertyPage and overrides AddRef and Release calls
 | ||
|  | // to keep track of the reference counts. When the last count is released
 | ||
|  | // we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
 | ||
|  | // previously obtained by the property page when it had SetObjects called
 | ||
|  | 
 | ||
|  | CBasePropertyPage::CBasePropertyPage(__in_opt LPCTSTR pName,   // Debug only name
 | ||
|  |                                      __inout_opt LPUNKNOWN pUnk, // COM Delegator
 | ||
|  |                                      int DialogId,      // Resource ID
 | ||
|  |                                      int TitleId) :     // To get tital
 | ||
|  |     CUnknown(pName,pUnk), | ||
|  |     m_DialogId(DialogId), | ||
|  |     m_TitleId(TitleId), | ||
|  |     m_hwnd(NULL), | ||
|  |     m_Dlg(NULL), | ||
|  |     m_pPageSite(NULL), | ||
|  |     m_bObjectSet(FALSE), | ||
|  |     m_bDirty(FALSE) | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef UNICODE
 | ||
|  | CBasePropertyPage::CBasePropertyPage(__in_opt LPCSTR pName,     // Debug only name
 | ||
|  |                                      __inout_opt LPUNKNOWN pUnk,  // COM Delegator
 | ||
|  |                                      int DialogId,      // Resource ID
 | ||
|  |                                      int TitleId) :     // To get tital
 | ||
|  |     CUnknown(pName,pUnk), | ||
|  |     m_DialogId(DialogId), | ||
|  |     m_TitleId(TitleId), | ||
|  |     m_hwnd(NULL), | ||
|  |     m_Dlg(NULL), | ||
|  |     m_pPageSite(NULL), | ||
|  |     m_bObjectSet(FALSE), | ||
|  |     m_bDirty(FALSE) | ||
|  | { | ||
|  | } | ||
|  | #endif
 | ||
|  | 
 | ||
|  | // Increment our reference count
 | ||
|  | 
 | ||
|  | STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef() | ||
|  | { | ||
|  |     LONG lRef = InterlockedIncrement(&m_cRef); | ||
|  |     ASSERT(lRef > 0); | ||
|  |     return max(ULONG(m_cRef),1ul); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Release a reference count and protect against reentrancy
 | ||
|  | 
 | ||
|  | STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease() | ||
|  | { | ||
|  |     // If the reference count drops to zero delete ourselves
 | ||
|  | 
 | ||
|  |     LONG lRef = InterlockedDecrement(&m_cRef); | ||
|  |     if (lRef == 0) { | ||
|  |         m_cRef++; | ||
|  |         SetPageSite(NULL); | ||
|  |         SetObjects(0,NULL); | ||
|  |         delete this; | ||
|  |         return ULONG(0); | ||
|  |     } else { | ||
|  |         //  Don't touch m_cRef again here!
 | ||
|  |         return max(ULONG(lRef),1ul); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Expose our IPropertyPage interface
 | ||
|  | 
 | ||
|  | STDMETHODIMP | ||
|  | CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv) | ||
|  | { | ||
|  |     if (riid == IID_IPropertyPage) { | ||
|  |         return GetInterface((IPropertyPage *)this,ppv); | ||
|  |     } else { | ||
|  |         return CUnknown::NonDelegatingQueryInterface(riid,ppv); | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Get the page info so that the page site can size itself
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::GetPageInfo(__out LPPROPPAGEINFO pPageInfo) | ||
|  | { | ||
|  |     CheckPointer(pPageInfo,E_POINTER); | ||
|  |     WCHAR wszTitle[STR_MAX_LENGTH]; | ||
|  |     WideStringFromResource(wszTitle,m_TitleId); | ||
|  | 
 | ||
|  |     // Allocate dynamic memory for the property page title
 | ||
|  | 
 | ||
|  |     LPOLESTR pszTitle; | ||
|  |     HRESULT hr = AMGetWideString(wszTitle, &pszTitle); | ||
|  |     if (FAILED(hr)) { | ||
|  |         NOTE("No caption memory"); | ||
|  |         return hr; | ||
|  |     } | ||
|  | 
 | ||
|  |     pPageInfo->cb               = sizeof(PROPPAGEINFO); | ||
|  |     pPageInfo->pszTitle         = pszTitle; | ||
|  |     pPageInfo->pszDocString     = NULL; | ||
|  |     pPageInfo->pszHelpFile      = NULL; | ||
|  |     pPageInfo->dwHelpContext    = 0; | ||
|  | 
 | ||
|  |     // Set defaults in case GetDialogSize fails
 | ||
|  |     pPageInfo->size.cx          = 340; | ||
|  |     pPageInfo->size.cy          = 150; | ||
|  | 
 | ||
|  |     GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size); | ||
|  |     return NOERROR; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Handles the messages for our property window
 | ||
|  | 
 | ||
|  | INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd, | ||
|  |                                             UINT uMsg, | ||
|  |                                             WPARAM wParam, | ||
|  |                                             LPARAM lParam) | ||
|  | { | ||
|  |     CBasePropertyPage *pPropertyPage; | ||
|  | 
 | ||
|  |     switch (uMsg) { | ||
|  | 
 | ||
|  |         case WM_INITDIALOG: | ||
|  | 
 | ||
|  |             SetWindowLongPtr(hwnd, DWLP_USER, lParam); | ||
|  | 
 | ||
|  |             // This pointer may be NULL when calculating size
 | ||
|  | 
 | ||
|  |             pPropertyPage = (CBasePropertyPage *) lParam; | ||
|  |             if (pPropertyPage == NULL) { | ||
|  |                 return (LRESULT) 1; | ||
|  |             } | ||
|  |             pPropertyPage->m_Dlg = hwnd; | ||
|  |     } | ||
|  | 
 | ||
|  |     // This pointer may be NULL when calculating size
 | ||
|  | 
 | ||
|  |     pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER); | ||
|  |     if (pPropertyPage == NULL) { | ||
|  |         return (LRESULT) 1; | ||
|  |     } | ||
|  |     return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Tells us the object that should be informed of the property changes
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,__in_ecount_opt(cObjects) LPUNKNOWN *ppUnk) | ||
|  | { | ||
|  |     if (cObjects == 1) { | ||
|  | 
 | ||
|  |         if ((ppUnk == NULL) || (*ppUnk == NULL)) { | ||
|  |             return E_POINTER; | ||
|  |         } | ||
|  | 
 | ||
|  |         // Set a flag to say that we have set the Object
 | ||
|  |         m_bObjectSet = TRUE ; | ||
|  |         return OnConnect(*ppUnk); | ||
|  | 
 | ||
|  |     } else if (cObjects == 0) { | ||
|  | 
 | ||
|  |         // Set a flag to say that we have not set the Object for the page
 | ||
|  |         m_bObjectSet = FALSE ; | ||
|  |         return OnDisconnect(); | ||
|  |     } | ||
|  | 
 | ||
|  |     DbgBreak("No support for more than one object"); | ||
|  |     return E_UNEXPECTED; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Create the window we will use to edit properties
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent, | ||
|  |                                          LPCRECT pRect, | ||
|  |                                          BOOL fModal) | ||
|  | { | ||
|  |     CheckPointer(pRect,E_POINTER); | ||
|  | 
 | ||
|  |     // Return failure if SetObject has not been called.
 | ||
|  |     if (m_bObjectSet == FALSE) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (m_hwnd) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     m_hwnd = CreateDialogParam(g_hInst, | ||
|  |                                MAKEINTRESOURCE(m_DialogId), | ||
|  |                                hwndParent, | ||
|  |                                DialogProc, | ||
|  |                                (LPARAM) this); | ||
|  |     if (m_hwnd == NULL) { | ||
|  |         return E_OUTOFMEMORY; | ||
|  |     } | ||
|  | 
 | ||
|  |     OnActivate(); | ||
|  |     Move(pRect); | ||
|  |     return Show(SW_SHOWNORMAL); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Set the position of the property page
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect) | ||
|  | { | ||
|  |     CheckPointer(pRect,E_POINTER); | ||
|  | 
 | ||
|  |     if (m_hwnd == NULL) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     MoveWindow(m_hwnd,              // Property page handle
 | ||
|  |                pRect->left,         // x coordinate
 | ||
|  |                pRect->top,          // y coordinate
 | ||
|  |                WIDTH(pRect),        // Overall window width
 | ||
|  |                HEIGHT(pRect),       // And likewise height
 | ||
|  |                TRUE);               // Should we repaint it
 | ||
|  | 
 | ||
|  |     return NOERROR; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Display the property dialog
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow) | ||
|  | { | ||
|  |    // Have we been activated yet
 | ||
|  | 
 | ||
|  |     if (m_hwnd == NULL) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Ignore wrong show flags
 | ||
|  | 
 | ||
|  |     if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) { | ||
|  |         return E_INVALIDARG; | ||
|  |     } | ||
|  | 
 | ||
|  |     ShowWindow(m_hwnd,nCmdShow); | ||
|  |     InvalidateRect(m_hwnd,NULL,TRUE); | ||
|  |     return NOERROR; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Destroy the property page dialog
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::Deactivate(void) | ||
|  | { | ||
|  |     if (m_hwnd == NULL) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Remove WS_EX_CONTROLPARENT before DestroyWindow call
 | ||
|  | 
 | ||
|  |     DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE); | ||
|  |     dwStyle = dwStyle & (~WS_EX_CONTROLPARENT); | ||
|  | 
 | ||
|  |     //  Set m_hwnd to be NULL temporarily so the message handler
 | ||
|  |     //  for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
 | ||
|  |     //  style back in
 | ||
|  |     HWND hwnd = m_hwnd; | ||
|  |     m_hwnd = NULL; | ||
|  |     SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle); | ||
|  |     m_hwnd = hwnd; | ||
|  | 
 | ||
|  |     OnDeactivate(); | ||
|  | 
 | ||
|  |     // Destroy the dialog window
 | ||
|  | 
 | ||
|  |     DestroyWindow(m_hwnd); | ||
|  |     m_hwnd = NULL; | ||
|  |     return NOERROR; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Tells the application property page site
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite) | ||
|  | { | ||
|  |     if (pPageSite) { | ||
|  | 
 | ||
|  |         if (m_pPageSite) { | ||
|  |             return E_UNEXPECTED; | ||
|  |         } | ||
|  | 
 | ||
|  |         m_pPageSite = pPageSite; | ||
|  |         m_pPageSite->AddRef(); | ||
|  | 
 | ||
|  |     } else { | ||
|  | 
 | ||
|  |         if (m_pPageSite == NULL) { | ||
|  |             return E_UNEXPECTED; | ||
|  |         } | ||
|  | 
 | ||
|  |         m_pPageSite->Release(); | ||
|  |         m_pPageSite = NULL; | ||
|  |     } | ||
|  |     return NOERROR; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Apply any changes so far made
 | ||
|  | 
 | ||
|  | STDMETHODIMP CBasePropertyPage::Apply() | ||
|  | { | ||
|  |     // In ActiveMovie 1.0 we used to check whether we had been activated or
 | ||
|  |     // not. This is too constrictive. Apply should be allowed as long as
 | ||
|  |     // SetObject was called to set an object. So we will no longer check to
 | ||
|  |     // see if we have been activated (ie., m_hWnd != NULL), but instead
 | ||
|  |     // make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
 | ||
|  | 
 | ||
|  |     if (m_bObjectSet == FALSE) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Must have had a site set
 | ||
|  | 
 | ||
|  |     if (m_pPageSite == NULL) { | ||
|  |         return E_UNEXPECTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Has anything changed
 | ||
|  | 
 | ||
|  |     if (m_bDirty == FALSE) { | ||
|  |         return NOERROR; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Commit derived class changes
 | ||
|  | 
 | ||
|  |     HRESULT hr = OnApplyChanges(); | ||
|  |     if (SUCCEEDED(hr)) { | ||
|  |         m_bDirty = FALSE; | ||
|  |     } | ||
|  |     return hr; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | // Base class definition for message handling
 | ||
|  | 
 | ||
|  | INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) | ||
|  | { | ||
|  |     // we would like the TAB key to move around the tab stops in our property
 | ||
|  |     // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
 | ||
|  |     // style behind our back, so we need to switch it back on now behind its
 | ||
|  |     // back.  Otherwise the tab key will be useless in every page.
 | ||
|  |     //
 | ||
|  | 
 | ||
|  |     CBasePropertyPage *pPropertyPage; | ||
|  |     { | ||
|  |         pPropertyPage = (CBasePropertyPage *) GetWindowLongPtr(hwnd, DWLP_USER); | ||
|  |         if (pPropertyPage->m_hwnd == NULL) { | ||
|  |             return 0; | ||
|  |         } | ||
|  |         switch (uMsg) { | ||
|  |           case WM_STYLECHANGING: | ||
|  |               if (wParam == GWL_EXSTYLE) { | ||
|  |                   LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam; | ||
|  |                   lpss->styleNew |= WS_EX_CONTROLPARENT; | ||
|  |                   return 0; | ||
|  |               } | ||
|  |         } | ||
|  |     } | ||
|  | 		 | ||
|  |     return DefWindowProc(hwnd,uMsg,wParam,lParam); | ||
|  | } | ||
|  | 
 |