cprop.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //------------------------------------------------------------------------------
  2. // File: CProp.cpp
  3. //
  4. // Desc: DirectShow base classes - implements CBasePropertyPage class.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #include <streams.h>
  9. // Constructor for the base property page class. As described in the header
  10. // file we must be initialised with dialog and title resource identifiers.
  11. // The class supports IPropertyPage and overrides AddRef and Release calls
  12. // to keep track of the reference counts. When the last count is released
  13. // we call SetPageSite(NULL) and SetObjects(0,NULL) to release interfaces
  14. // previously obtained by the property page when it had SetObjects called
  15. CBasePropertyPage::CBasePropertyPage(__in_opt LPCTSTR pName, // Debug only name
  16. __inout_opt LPUNKNOWN pUnk, // COM Delegator
  17. int DialogId, // Resource ID
  18. int TitleId) : // To get tital
  19. CUnknown(pName,pUnk),
  20. m_DialogId(DialogId),
  21. m_TitleId(TitleId),
  22. m_hwnd(NULL),
  23. m_Dlg(NULL),
  24. m_pPageSite(NULL),
  25. m_bObjectSet(FALSE),
  26. m_bDirty(FALSE)
  27. {
  28. }
  29. #ifdef UNICODE
  30. CBasePropertyPage::CBasePropertyPage(__in_opt LPCSTR pName, // Debug only name
  31. __inout_opt LPUNKNOWN pUnk, // COM Delegator
  32. int DialogId, // Resource ID
  33. int TitleId) : // To get tital
  34. CUnknown(pName,pUnk),
  35. m_DialogId(DialogId),
  36. m_TitleId(TitleId),
  37. m_hwnd(NULL),
  38. m_Dlg(NULL),
  39. m_pPageSite(NULL),
  40. m_bObjectSet(FALSE),
  41. m_bDirty(FALSE)
  42. {
  43. }
  44. #endif
  45. // Increment our reference count
  46. STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingAddRef()
  47. {
  48. LONG lRef = InterlockedIncrement(&m_cRef);
  49. ASSERT(lRef > 0);
  50. return max(ULONG(m_cRef),1ul);
  51. }
  52. // Release a reference count and protect against reentrancy
  53. STDMETHODIMP_(ULONG) CBasePropertyPage::NonDelegatingRelease()
  54. {
  55. // If the reference count drops to zero delete ourselves
  56. LONG lRef = InterlockedDecrement(&m_cRef);
  57. if (lRef == 0) {
  58. m_cRef++;
  59. SetPageSite(NULL);
  60. SetObjects(0,NULL);
  61. delete this;
  62. return ULONG(0);
  63. } else {
  64. // Don't touch m_cRef again here!
  65. return max(ULONG(lRef),1ul);
  66. }
  67. }
  68. // Expose our IPropertyPage interface
  69. STDMETHODIMP
  70. CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv)
  71. {
  72. if (riid == IID_IPropertyPage) {
  73. return GetInterface((IPropertyPage *)this,ppv);
  74. } else {
  75. return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  76. }
  77. }
  78. // Get the page info so that the page site can size itself
  79. STDMETHODIMP CBasePropertyPage::GetPageInfo(__out LPPROPPAGEINFO pPageInfo)
  80. {
  81. CheckPointer(pPageInfo,E_POINTER);
  82. WCHAR wszTitle[STR_MAX_LENGTH];
  83. WideStringFromResource(wszTitle,m_TitleId);
  84. // Allocate dynamic memory for the property page title
  85. LPOLESTR pszTitle;
  86. HRESULT hr = AMGetWideString(wszTitle, &pszTitle);
  87. if (FAILED(hr)) {
  88. NOTE("No caption memory");
  89. return hr;
  90. }
  91. pPageInfo->cb = sizeof(PROPPAGEINFO);
  92. pPageInfo->pszTitle = pszTitle;
  93. pPageInfo->pszDocString = NULL;
  94. pPageInfo->pszHelpFile = NULL;
  95. pPageInfo->dwHelpContext = 0;
  96. // Set defaults in case GetDialogSize fails
  97. pPageInfo->size.cx = 340;
  98. pPageInfo->size.cy = 150;
  99. GetDialogSize(m_DialogId, DialogProc,0L,&pPageInfo->size);
  100. return NOERROR;
  101. }
  102. // Handles the messages for our property window
  103. INT_PTR CALLBACK CBasePropertyPage::DialogProc(HWND hwnd,
  104. UINT uMsg,
  105. WPARAM wParam,
  106. LPARAM lParam)
  107. {
  108. CBasePropertyPage *pPropertyPage;
  109. switch (uMsg) {
  110. case WM_INITDIALOG:
  111. _SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  112. // This pointer may be NULL when calculating size
  113. pPropertyPage = (CBasePropertyPage *) lParam;
  114. if (pPropertyPage == NULL) {
  115. return (LRESULT) 1;
  116. }
  117. pPropertyPage->m_Dlg = hwnd;
  118. }
  119. // This pointer may be NULL when calculating size
  120. pPropertyPage = _GetWindowLongPtr<CBasePropertyPage*>(hwnd, DWLP_USER);
  121. if (pPropertyPage == NULL) {
  122. return (LRESULT) 1;
  123. }
  124. return pPropertyPage->OnReceiveMessage(hwnd,uMsg,wParam,lParam);
  125. }
  126. // Tells us the object that should be informed of the property changes
  127. STDMETHODIMP CBasePropertyPage::SetObjects(ULONG cObjects,__in_ecount_opt(cObjects) LPUNKNOWN *ppUnk)
  128. {
  129. if (cObjects == 1) {
  130. if ((ppUnk == NULL) || (*ppUnk == NULL)) {
  131. return E_POINTER;
  132. }
  133. // Set a flag to say that we have set the Object
  134. m_bObjectSet = TRUE ;
  135. return OnConnect(*ppUnk);
  136. } else if (cObjects == 0) {
  137. // Set a flag to say that we have not set the Object for the page
  138. m_bObjectSet = FALSE ;
  139. return OnDisconnect();
  140. }
  141. DbgBreak("No support for more than one object");
  142. return E_UNEXPECTED;
  143. }
  144. // Create the window we will use to edit properties
  145. STDMETHODIMP CBasePropertyPage::Activate(HWND hwndParent,
  146. LPCRECT pRect,
  147. BOOL fModal)
  148. {
  149. CheckPointer(pRect,E_POINTER);
  150. // Return failure if SetObject has not been called.
  151. if (m_bObjectSet == FALSE) {
  152. return E_UNEXPECTED;
  153. }
  154. if (m_hwnd) {
  155. return E_UNEXPECTED;
  156. }
  157. m_hwnd = CreateDialogParam(g_hInst,
  158. MAKEINTRESOURCE(m_DialogId),
  159. hwndParent,
  160. DialogProc,
  161. (LPARAM) this);
  162. if (m_hwnd == NULL) {
  163. return E_OUTOFMEMORY;
  164. }
  165. OnActivate();
  166. Move(pRect);
  167. return Show(SW_SHOWNORMAL);
  168. }
  169. // Set the position of the property page
  170. STDMETHODIMP CBasePropertyPage::Move(LPCRECT pRect)
  171. {
  172. CheckPointer(pRect,E_POINTER);
  173. if (m_hwnd == NULL) {
  174. return E_UNEXPECTED;
  175. }
  176. MoveWindow(m_hwnd, // Property page handle
  177. pRect->left, // x coordinate
  178. pRect->top, // y coordinate
  179. WIDTH(pRect), // Overall window width
  180. HEIGHT(pRect), // And likewise height
  181. TRUE); // Should we repaint it
  182. return NOERROR;
  183. }
  184. // Display the property dialog
  185. STDMETHODIMP CBasePropertyPage::Show(UINT nCmdShow)
  186. {
  187. // Have we been activated yet
  188. if (m_hwnd == NULL) {
  189. return E_UNEXPECTED;
  190. }
  191. // Ignore wrong show flags
  192. if ((nCmdShow != SW_SHOW) && (nCmdShow != SW_SHOWNORMAL) && (nCmdShow != SW_HIDE)) {
  193. return E_INVALIDARG;
  194. }
  195. ShowWindow(m_hwnd,nCmdShow);
  196. InvalidateRect(m_hwnd,NULL,TRUE);
  197. return NOERROR;
  198. }
  199. // Destroy the property page dialog
  200. STDMETHODIMP CBasePropertyPage::Deactivate(void)
  201. {
  202. if (m_hwnd == NULL) {
  203. return E_UNEXPECTED;
  204. }
  205. // Remove WS_EX_CONTROLPARENT before DestroyWindow call
  206. DWORD dwStyle = GetWindowLong(m_hwnd, GWL_EXSTYLE);
  207. dwStyle = dwStyle & (~WS_EX_CONTROLPARENT);
  208. // Set m_hwnd to be NULL temporarily so the message handler
  209. // for WM_STYLECHANGING doesn't add the WS_EX_CONTROLPARENT
  210. // style back in
  211. HWND hwnd = m_hwnd;
  212. m_hwnd = NULL;
  213. SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
  214. m_hwnd = hwnd;
  215. OnDeactivate();
  216. // Destroy the dialog window
  217. DestroyWindow(m_hwnd);
  218. m_hwnd = NULL;
  219. return NOERROR;
  220. }
  221. // Tells the application property page site
  222. STDMETHODIMP CBasePropertyPage::SetPageSite(__in_opt LPPROPERTYPAGESITE pPageSite)
  223. {
  224. if (pPageSite) {
  225. if (m_pPageSite) {
  226. return E_UNEXPECTED;
  227. }
  228. m_pPageSite = pPageSite;
  229. m_pPageSite->AddRef();
  230. } else {
  231. if (m_pPageSite == NULL) {
  232. return E_UNEXPECTED;
  233. }
  234. m_pPageSite->Release();
  235. m_pPageSite = NULL;
  236. }
  237. return NOERROR;
  238. }
  239. // Apply any changes so far made
  240. STDMETHODIMP CBasePropertyPage::Apply()
  241. {
  242. // In ActiveMovie 1.0 we used to check whether we had been activated or
  243. // not. This is too constrictive. Apply should be allowed as long as
  244. // SetObject was called to set an object. So we will no longer check to
  245. // see if we have been activated (ie., m_hWnd != NULL), but instead
  246. // make sure that m_bObjectSet is TRUE (ie., SetObject has been called).
  247. if (m_bObjectSet == FALSE) {
  248. return E_UNEXPECTED;
  249. }
  250. // Must have had a site set
  251. if (m_pPageSite == NULL) {
  252. return E_UNEXPECTED;
  253. }
  254. // Has anything changed
  255. if (m_bDirty == FALSE) {
  256. return NOERROR;
  257. }
  258. // Commit derived class changes
  259. HRESULT hr = OnApplyChanges();
  260. if (SUCCEEDED(hr)) {
  261. m_bDirty = FALSE;
  262. }
  263. return hr;
  264. }
  265. // Base class definition for message handling
  266. INT_PTR CBasePropertyPage::OnReceiveMessage(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  267. {
  268. // we would like the TAB key to move around the tab stops in our property
  269. // page, but for some reason OleCreatePropertyFrame clears the CONTROLPARENT
  270. // style behind our back, so we need to switch it back on now behind its
  271. // back. Otherwise the tab key will be useless in every page.
  272. //
  273. CBasePropertyPage *pPropertyPage;
  274. {
  275. pPropertyPage = _GetWindowLongPtr<CBasePropertyPage*>(hwnd, DWLP_USER);
  276. if (pPropertyPage->m_hwnd == NULL) {
  277. return 0;
  278. }
  279. switch (uMsg) {
  280. case WM_STYLECHANGING:
  281. if (wParam == GWL_EXSTYLE) {
  282. LPSTYLESTRUCT lpss = (LPSTYLESTRUCT)lParam;
  283. lpss->styleNew |= WS_EX_CONTROLPARENT;
  284. return 0;
  285. }
  286. }
  287. }
  288. return DefWindowProc(hwnd,uMsg,wParam,lParam);
  289. }