|
|
//------------------------------------------------------------------------------
// File: CProp.cpp
//
// Desc: DirectShow base classes - implements CBasePropertyPage class.
//
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include <streams.h>
// 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(TCHAR *pName, // Debug only name
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(CHAR *pName, // Debug only name
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
if (InterlockedDecrement(&m_cRef) == 0) { m_cRef++; SetPageSite(NULL); SetObjects(0,NULL); delete this; return ULONG(0); } else { return max(ULONG(m_cRef),1ul); } }
// Expose our IPropertyPage interface
STDMETHODIMP CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,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(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,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(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); }
|