topical media & game development

talk show tell print

hush-src-multi-BaseClasses-cprop.cpp / cpp



  //------------------------------------------------------------------------------
  // File: CProp.cpp
  //
  // Desc: DirectShow base classes - implements CBasePropertyPage class.
  //
  // Copyright (c) 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);
  }
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.