Click here to Skip to main content
15,896,606 members
Articles / Desktop Programming / MFC

DirectShow Editing Services (DES) and combining AVI files

Rate me:
Please Sign up or sign in to vote.
4.64/5 (4 votes)
9 Sep 2011CPOL5 min read 36K   5.8K   12  
A sample C++ project that uses DES to combine two or more AVI files.
//------------------------------------------------------------------------------
// 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(__in_opt LPCTSTR pName,   // Debug only name
                                     __inout_opt 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(__in_opt LPCSTR pName,     // Debug only name
                                     __inout_opt 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

    LONG lRef = InterlockedDecrement(&m_cRef);
    if (lRef == 0) {
        m_cRef++;
        SetPageSite(NULL);
        SetObjects(0,NULL);
        delete this;
        return ULONG(0);
    } else {
        //  Don't touch m_cRef again here!
        return max(ULONG(lRef),1ul);
    }
}


// Expose our IPropertyPage interface

STDMETHODIMP
CBasePropertyPage::NonDelegatingQueryInterface(REFIID riid,__deref_out 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(__out 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 = _GetWindowLongPtr<CBasePropertyPage*>(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,__in_ecount_opt(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(__in_opt 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 = _GetWindowLongPtr<CBasePropertyPage*>(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);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions