1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - implements CBasePropertyPage class.
6 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
12 // Constructor for the base property page class. As described in the header
13 // file we must be initialised with dialog and title resource identifiers.
14 // The class supports IPropertyPage and overrides AddRef and Release calls
15 // to keep track of the reference counts. When the last count is released
16 // we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
17 // previously obtained by the property page when it had SetObjects called
19 CBasePropertyPage::CBasePropertyPage(TCHAR
*pName
, // Debug only name
20 LPUNKNOWN pUnk
, // COM Delegator
21 int DialogId
, // Resource ID
22 int TitleId
) : // To get tital
35 CBasePropertyPage::CBasePropertyPage(CHAR
*pName
, // Debug only name
36 LPUNKNOWN pUnk
, // COM Delegator
37 int DialogId
, // Resource ID
38 int TitleId
) : // To get tital
51 // Increment our reference count
53 STDMETHODIMP_(ULONG
) CBasePropertyPage::NonDelegatingAddRef()
55 LONG lRef
= InterlockedIncrement(&m_cRef
);
57 return max(ULONG(m_cRef
),1ul);
61 // Release a reference count and protect against reentrancy
63 STDMETHODIMP_(ULONG
) CBasePropertyPage::NonDelegatingRelease()
65 // If the reference count drops to zero delete ourselves
67 if (InterlockedDecrement(&m_cRef
) == 0) {
74 return max(ULONG(m_cRef
),1ul);
79 // Expose our IPropertyPage interface
82 CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid
,void **ppv
)
84 if (riid
== IID_IPropertyPage
) {
85 return GetInterface((IPropertyPage
*)this,ppv
);
87 return CUnknown::NonDelegatingQueryInterface(riid
,ppv
);
92 // Get the page info so that the page site can size itself
94 STDMETHODIMP
CBasePropertyPage::GetPageInfo(LPPROPPAGEINFO pPageInfo
)
96 CheckPointer(pPageInfo
,E_POINTER
);
97 WCHAR wszTitle
[STR_MAX_LENGTH
];
98 WideStringFromResource(wszTitle
,m_TitleId
);
100 // Allocate dynamic memory for the property page title
103 HRESULT hr
= AMGetWideString(wszTitle
, &pszTitle
);
105 NOTE("No caption memory");
109 pPageInfo
->cb
= sizeof(PROPPAGEINFO
);
110 pPageInfo
->pszTitle
= pszTitle
;
111 pPageInfo
->pszDocString
= NULL
;
112 pPageInfo
->pszHelpFile
= NULL
;
113 pPageInfo
->dwHelpContext
= 0;
115 // Set defaults in case GetDialogSize fails
116 pPageInfo
->size
.cx
= 340;
117 pPageInfo
->size
.cy
= 150;
119 GetDialogSize(m_DialogId
, DialogProc
,0L,&pPageInfo
->size
);
124 // Handles the messages for our property window
126 INT_PTR CALLBACK
CBasePropertyPage::DialogProc(HWND hwnd
,
131 CBasePropertyPage
*pPropertyPage
;
137 SetWindowLongPtr(hwnd
, DWLP_USER
, lParam
);
139 // This pointer may be NULL when calculating size
141 pPropertyPage
= (CBasePropertyPage
*) lParam
;
142 if (pPropertyPage
== NULL
) {
145 pPropertyPage
->m_Dlg
= hwnd
;
148 // This pointer may be NULL when calculating size
150 pPropertyPage
= (CBasePropertyPage
*) GetWindowLongPtr(hwnd
, DWLP_USER
);
151 if (pPropertyPage
== NULL
) {
154 return pPropertyPage
->OnReceiveMessage(hwnd
,uMsg
,wParam
,lParam
);
158 // Tells us the object that should be informed of the property changes
160 STDMETHODIMP
CBasePropertyPage::SetObjects(ULONG cObjects
,LPUNKNOWN
*ppUnk
)
164 if ((ppUnk
== NULL
) || (*ppUnk
== NULL
)) {
168 // Set a flag to say that we have set the Object
169 m_bObjectSet
= TRUE
;
170 return OnConnect(*ppUnk
);
172 } else if (cObjects
== 0) {
174 // Set a flag to say that we have not set the Object for the page
175 m_bObjectSet
= FALSE
;
176 return OnDisconnect();
179 DbgBreak("No support for more than one object");
184 // Create the window we will use to edit properties
186 STDMETHODIMP
CBasePropertyPage::Activate(HWND hwndParent
,
190 CheckPointer(pRect
,E_POINTER
);
192 // Return failure if SetObject has not been called.
193 if (m_bObjectSet
== FALSE
) {
201 m_hwnd
= CreateDialogParam(g_hInst
,
202 MAKEINTRESOURCE(m_DialogId
),
206 if (m_hwnd
== NULL
) {
207 return E_OUTOFMEMORY
;
212 return Show(SW_SHOWNORMAL
);
216 // Set the position of the property page
218 STDMETHODIMP
CBasePropertyPage::Move(LPCRECT pRect
)
220 CheckPointer(pRect
,E_POINTER
);
222 if (m_hwnd
== NULL
) {
226 MoveWindow(m_hwnd
, // Property page handle
227 pRect
->left
, // x coordinate
228 pRect
->top
, // y coordinate
229 WIDTH(pRect
), // Overall window width
230 HEIGHT(pRect
), // And likewise height
231 TRUE
); // Should we repaint it
237 // Display the property dialog
239 STDMETHODIMP
CBasePropertyPage::Show(UINT nCmdShow
)
241 // Have we been activated yet
243 if (m_hwnd
== NULL
) {
247 // Ignore wrong show flags
249 if ((nCmdShow
!= SW_SHOW
) && (nCmdShow
!= SW_SHOWNORMAL
) && (nCmdShow
!= SW_HIDE
)) {
253 ShowWindow(m_hwnd
,nCmdShow
);
254 InvalidateRect(m_hwnd
,NULL
,TRUE
);
259 // Destroy the property page dialog
261 STDMETHODIMP
CBasePropertyPage::Deactivate(void)
263 if (m_hwnd
== NULL
) {
267 // Remove WS_EX_CONTROLPARENT before DestroyWindow call
269 DWORD dwStyle
= GetWindowLong(m_hwnd
, GWL_EXSTYLE
);
270 dwStyle
= dwStyle
& (~WS_EX_CONTROLPARENT
);
272 // Set m_hwnd to be NULL temporarily so the message handler
273 // for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
277 SetWindowLong(hwnd
, GWL_EXSTYLE
, dwStyle
);
282 // Destroy the dialog window
284 DestroyWindow(m_hwnd
);
290 // Tells the application property page site
292 STDMETHODIMP
CBasePropertyPage::SetPageSite(LPPROPERTYPAGESITE pPageSite
)
300 m_pPageSite
= pPageSite
;
301 m_pPageSite
->AddRef();
305 if (m_pPageSite
== NULL
) {
309 m_pPageSite
->Release();
316 // Apply any changes so far made
318 STDMETHODIMP
CBasePropertyPage::Apply()
320 // In ActiveMovie 1.0 we used to check whether we had been activated or
321 // not. This is too constrictive. Apply should be allowed as long as
322 // SetObject was called to set an object. So we will no longer check to
323 // see if we have been activated (ie., m_hWnd != NULL), but instead
324 // make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
326 if (m_bObjectSet
== FALSE
) {
330 // Must have had a site set
332 if (m_pPageSite
== NULL
) {
336 // Has anything changed
338 if (m_bDirty
== FALSE
) {
342 // Commit derived class changes
344 HRESULT hr
= OnApplyChanges();
352 // Base class definition for message handling
354 INT_PTR
CBasePropertyPage::OnReceiveMessage(HWND hwnd
,UINT uMsg
,WPARAM wParam
,LPARAM lParam
)
356 // we would like the TAB key to move around the tab stops in our property
357 // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
358 // style behind our back, so we need to switch it back on now behind its
359 // back. Otherwise the tab key will be useless in every page.
362 CBasePropertyPage
*pPropertyPage
;
364 pPropertyPage
= (CBasePropertyPage
*) GetWindowLongPtr(hwnd
, DWLP_USER
);
365 if (pPropertyPage
->m_hwnd
== NULL
) {
369 case WM_STYLECHANGING
:
370 if (wParam
== GWL_EXSTYLE
) {
371 LPSTYLESTRUCT lpss
= (LPSTYLESTRUCT
)lParam
;
372 lpss
->styleNew
|= WS_EX_CONTROLPARENT
;
378 return DefWindowProc(hwnd
,uMsg
,wParam
,lParam
);