A Fast Bresenham Type Algorithm For Drawing Ellipses by John Kennedy
[xy_vsfilter.git] / src / filters / BaseClasses / cprop.cpp
blobebf34ef7643dae599b624c0a8062a2b598ed43b9
1 //------------------------------------------------------------------------------
2 // File: CProp.cpp
3 //
4 // Desc: DirectShow base classes - implements CBasePropertyPage class.
5 //
6 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
10 #include <streams.h>
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
23 CUnknown(pName,pUnk),
24 m_DialogId(DialogId),
25 m_TitleId(TitleId),
26 m_hwnd(NULL),
27 m_Dlg(NULL),
28 m_pPageSite(NULL),
29 m_bObjectSet(FALSE),
30 m_bDirty(FALSE)
34 #ifdef UNICODE
35 CBasePropertyPage::CBasePropertyPage(CHAR *pName, // Debug only name
36 LPUNKNOWN pUnk, // COM Delegator
37 int DialogId, // Resource ID
38 int TitleId) : // To get tital
39 CUnknown(pName,pUnk),
40 m_DialogId(DialogId),
41 m_TitleId(TitleId),
42 m_hwnd(NULL),
43 m_Dlg(NULL),
44 m_pPageSite(NULL),
45 m_bObjectSet(FALSE),
46 m_bDirty(FALSE)
49 #endif
51 // Increment our reference count
53 STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef()
55 LONG lRef = InterlockedIncrement(&m_cRef);
56 ASSERT(lRef > 0);
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) {
68 m_cRef++;
69 SetPageSite(NULL);
70 SetObjects(0,NULL);
71 delete this;
72 return ULONG(0);
73 } else {
74 return max(ULONG(m_cRef),1ul);
79 // Expose our IPropertyPage interface
81 STDMETHODIMP
82 CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,void **ppv)
84 if (riid == IID_IPropertyPage) {
85 return GetInterface((IPropertyPage *)this,ppv);
86 } else {
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
102 LPOLESTR pszTitle;
103 HRESULT hr = AMGetWideString(wszTitle, &pszTitle);
104 if (FAILED(hr)) {
105 NOTE("No caption memory");
106 return hr;
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);
120 return NOERROR;
124 // Handles the messages for our property window
126 INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd,
127 UINT uMsg,
128 WPARAM wParam,
129 LPARAM lParam)
131 CBasePropertyPage *pPropertyPage;
133 switch (uMsg) {
135 case WM_INITDIALOG:
137 SetWindowLongPtr(hwnd, DWLP_USER, lParam);
139 // This pointer may be NULL when calculating size
141 pPropertyPage = (CBasePropertyPage *) lParam;
142 if (pPropertyPage == NULL) {
143 return (LRESULT) 1;
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) {
152 return (LRESULT) 1;
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)
162 if (cObjects == 1) {
164 if ((ppUnk == NULL) || (*ppUnk == NULL)) {
165 return E_POINTER;
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");
180 return E_UNEXPECTED;
184 // Create the window we will use to edit properties
186 STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent,
187 LPCRECT pRect,
188 BOOL fModal)
190 CheckPointer(pRect,E_POINTER);
192 // Return failure if SetObject has not been called.
193 if (m_bObjectSet == FALSE) {
194 return E_UNEXPECTED;
197 if (m_hwnd) {
198 return E_UNEXPECTED;
201 m_hwnd = CreateDialogParam(g_hInst,
202 MAKEINTRESOURCE(m_DialogId),
203 hwndParent,
204 DialogProc,
205 (LPARAM) this);
206 if (m_hwnd == NULL) {
207 return E_OUTOFMEMORY;
210 OnActivate();
211 Move(pRect);
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) {
223 return E_UNEXPECTED;
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
233 return NOERROR;
237 // Display the property dialog
239 STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow)
241 // Have we been activated yet
243 if (m_hwnd == NULL) {
244 return E_UNEXPECTED;
247 // Ignore wrong show flags
249 if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) {
250 return E_INVALIDARG;
253 ShowWindow(m_hwnd,nCmdShow);
254 InvalidateRect(m_hwnd,NULL,TRUE);
255 return NOERROR;
259 // Destroy the property page dialog
261 STDMETHODIMP CBasePropertyPage::Deactivate(void)
263 if (m_hwnd == NULL) {
264 return E_UNEXPECTED;
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
274 // style back in
275 HWND hwnd = m_hwnd;
276 m_hwnd = NULL;
277 SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
278 m_hwnd = hwnd;
280 OnDeactivate();
282 // Destroy the dialog window
284 DestroyWindow(m_hwnd);
285 m_hwnd = NULL;
286 return NOERROR;
290 // Tells the application property page site
292 STDMETHODIMP CBasePropertyPage::SetPageSite(LPPROPERTYPAGESITE pPageSite)
294 if (pPageSite) {
296 if (m_pPageSite) {
297 return E_UNEXPECTED;
300 m_pPageSite = pPageSite;
301 m_pPageSite->AddRef();
303 } else {
305 if (m_pPageSite == NULL) {
306 return E_UNEXPECTED;
309 m_pPageSite->Release();
310 m_pPageSite = NULL;
312 return NOERROR;
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) {
327 return E_UNEXPECTED;
330 // Must have had a site set
332 if (m_pPageSite == NULL) {
333 return E_UNEXPECTED;
336 // Has anything changed
338 if (m_bDirty == FALSE) {
339 return NOERROR;
342 // Commit derived class changes
344 HRESULT hr = OnApplyChanges();
345 if (SUCCEEDED(hr)) {
346 m_bDirty = FALSE;
348 return hr;
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) {
366 return 0;
368 switch (uMsg) {
369 case WM_STYLECHANGING:
370 if (wParam == GWL_EXSTYLE) {
371 LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam;
372 lpss->styleNew |= WS_EX_CONTROLPARENT;
373 return 0;
378 return DefWindowProc(hwnd,uMsg,wParam,lParam);