⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blenderdlg.cpp

📁 最近在学习directshow, Directshow实务精选的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//------------------------------------------------------------------------------
// File: BlenderDlg.cpp
//
// Desc: DirectShow sample code - an MFC application that blends two video
//       streams using the Video Mixing Renderer.  Controls are provided for
//       manipulating each video stream's X, Y, size, and alpha values.
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------

#include "stdafx.h"
#include "Blender.h"
#include "BlenderDlg.h"

#include <atlbase.h>
#include <tchar.h>
#include <atlbase.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Uncomment this line to render video component only (no audio rendering)
// #define NO_AUDIO

//
//  Global data
//
typedef struct
{
    FLOAT     xPos,  yPos;
    FLOAT     xSize, ySize;
    FLOAT     Alpha;
    BOOL      bFlipped, bMirrored;
} STRM_PARAM;

// Default initialization values for the video streams
const STRM_PARAM strParamInit[1] = {
    {0.0F, 0.0F, 1.0F, 1.0F, 0.7F, 0, 0}
};

// Contains initial and current values for the video streams
STRM_PARAM strParam[2] = {
    {0.0F, 0.0F, 1.0F, 1.0F, 0.7F, 0, 0},
    {0.0F, 0.0F, 1.0F, 1.0F, 0.7F, 0, 0}
};

// Resource IDs for dialog controls (for simple enumeration)
const int NUM_SLIDERS=10;
int nSliderIDs[NUM_SLIDERS] = {
    IDC_SLIDER_X,       IDC_SLIDER_X2,
    IDC_SLIDER_Y,       IDC_SLIDER_Y2,
    IDC_SLIDER_WIDTH,   IDC_SLIDER_WIDTH2,
    IDC_SLIDER_HEIGHT,  IDC_SLIDER_HEIGHT2,
    IDC_SLIDER_ALPHA,   IDC_SLIDER_ALPHA2
    };

const int NUM_CHECKS=4;
int nCheckIDs[NUM_CHECKS] = {
    IDC_CHECK_FLIP,     IDC_CHECK_FLIP2,
    IDC_CHECK_MIRROR,   IDC_CHECK_MIRROR2
};


/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
    CAboutDlg();

// Dialog Data
    //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
    //}}AFX_DATA

    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CAboutDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    //}}AFX_VIRTUAL

// Implementation
protected:
    //{{AFX_MSG(CAboutDlg)
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
    //{{AFX_DATA_INIT(CAboutDlg)
    //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CAboutDlg)
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
        // No message handlers
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBlenderDlg dialog

CBlenderDlg::CBlenderDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CBlenderDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CBlenderDlg)
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CBlenderDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CBlenderDlg)
    DDX_Control(pDX, IDC_POSITION, m_StrPosition);
    DDX_Control(pDX, IDC_DURATION, m_StrDuration);
    DDX_Control(pDX, IDC_STOP, m_ButtonStop);
    DDX_Control(pDX, IDC_PAUSE, m_ButtonPause);
    DDX_Control(pDX, IDC_PLAY, m_ButtonPlay);
    DDX_Control(pDX, IDC_SCREEN, m_Screen);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CBlenderDlg, CDialog)
    //{{AFX_MSG_MAP(CBlenderDlg)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON_STREAM1, OnButtonStream1)
    ON_BN_CLICKED(IDC_BUTTON_STREAM2, OnButtonStream2)
    ON_BN_CLICKED(IDC_STOP, OnStop)
    ON_BN_CLICKED(IDC_PAUSE, OnPause)
    ON_BN_CLICKED(IDC_PLAY, OnPlay)
    ON_WM_CLOSE()
    ON_WM_DESTROY()
    ON_WM_TIMER()
    ON_BN_CLICKED(IDC_CHECK_FLIP, OnCheckFlip)
    ON_BN_CLICKED(IDC_CHECK_MIRROR, OnCheckMirror)
    ON_BN_CLICKED(IDC_CHECK_FLIP2, OnCheckFlip2)
    ON_BN_CLICKED(IDC_CHECK_MIRROR2, OnCheckMirror2)
    ON_BN_CLICKED(IDC_BUTTON_ABOUT, OnButtonAbout)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBlenderDlg message handlers

void CBlenderDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialog::OnSysCommand(nID, lParam);
    }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CBlenderDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        // When using VMR Windowless mode, you must explicitly tell the
        // renderer when to repaint the video in response to WM_PAINT
        // messages.  This is most important when the video is stopped
        // or paused, since the VMR won't be automatically updating the
        // window as the video plays.
        MoveVideoWindow();
        RepaintVideo();

        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CBlenderDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

BOOL CBlenderDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    // Initialize COM
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    // Verify that the VMR is present on this system
    if(!VerifyVMR9())
        exit(1);

    // Initialize the video screen
    m_Screen.ModifyStyle(0, WS_CLIPCHILDREN);
    m_hwndScreen = m_Screen.GetSafeHwnd();

    // Initialize global variables
    pGB = NULL;
    pMC = NULL;
    pMS = NULL;
    pME = NULL;
    pWC = NULL;
    pMix = NULL;
    m_szFile1[0] = m_szFile2[0] = TEXT('\0');
    g_wTimerID = 0;
    InitControls();
    
    return TRUE;  // return TRUE  unless you set the focus to a control
}

#ifdef REGISTER_FILTERGRAPH

HRESULT CBlenderDlg::AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister) 
{
    IMoniker * pMoniker;
    IRunningObjectTable *pROT;
    if (FAILED(GetRunningObjectTable(0, &pROT))) 
    {
        return E_FAIL;
    }

    WCHAR wsz[128];
    wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, 
              GetCurrentProcessId());

    HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
    if (SUCCEEDED(hr)) 
    {
        // Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
        // to the object.  Using this flag will cause the object to remain
        // registered until it is explicitly revoked with the Revoke() method.
        //
        // Not using this flag means that if GraphEdit remotely connects
        // to this graph and then GraphEdit exits, this object registration 
        // will be deleted, causing future attempts by GraphEdit to fail until
        // this application is restarted or until the graph is registered again.
        hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, 
                            pMoniker, pdwRegister);
        pMoniker->Release();
    }

    pROT->Release();
    return hr;
}

void CBlenderDlg::RemoveGraphFromRot(DWORD pdwRegister)
{
    IRunningObjectTable *pROT;

    if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) 
    {
        pROT->Revoke(pdwRegister);
        pROT->Release();
    }
}

#endif

void CBlenderDlg::Msg(TCHAR *szFormat, ...)
{
    TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs
    const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
    const int LASTCHAR = NUMCHARS - 1;

    // Format the input string
    va_list pArgs;
    va_start(pArgs, szFormat);

    // Use a bounded buffer size to prevent buffer overruns.  Limit count to
    // character size minus one to allow for a NULL terminating character.
    _vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);
    va_end(pArgs);

    // Ensure that the formatted string is NULL-terminated
    szBuffer[LASTCHAR] = TEXT('\0');

    // Display a message box with the formatted string
    MessageBox(szBuffer, TEXT("VMR Blender Sample"), MB_OK);
}

BOOL CBlenderDlg::GetClipFileName(LPTSTR szName)
{
    static OPENFILENAME ofn={0};
    static BOOL bSetInitialDir = FALSE;

    // Reset filename
    *szName = 0;

    // Fill in standard structure fields
    ofn.lStructSize       = sizeof(OPENFILENAME);
    ofn.hwndOwner         = GetSafeHwnd();
    ofn.lpstrFilter       = NULL;
    ofn.lpstrFilter       = FILE_FILTER_TEXT;
    ofn.lpstrCustomFilter = NULL;
    ofn.nFilterIndex      = 1;
    ofn.lpstrFile         = szName;
    ofn.nMaxFile          = MAX_PATH;
    ofn.lpstrTitle        = TEXT("Open Media File...\0");
    ofn.lpstrFileTitle    = NULL;
    ofn.lpstrDefExt       = TEXT("*\0");
    ofn.Flags             = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST;

    // Remember the path of the first selected file
    if (bSetInitialDir == FALSE)
    {
        ofn.lpstrInitialDir = DEFAULT_MEDIA_PATH;
        bSetInitialDir = TRUE;
    }
    else
        ofn.lpstrInitialDir = NULL;

    // Create the standard file open dialog and return its result
    return GetOpenFileName((LPOPENFILENAME)&ofn);
}

void CBlenderDlg::OnButtonStream1() 
{
    // Select a file
    if (GetClipFileName(m_szFile1))
    {
        // Enable the playback buttons
        InitButtons();

        // Reset the stream sliders and check buttons
        InitControls();

        // Display the selected filename and clear the second filename
        GetDlgItem(IDC_STATIC_STREAM1)->SetWindowText(m_szFile1);
        GetDlgItem(IDC_STATIC_STREAM2)->SetWindowText(TEXT("\0"));

        // Disable playback buttons until two files are properly loaded
        m_ButtonPlay.EnableWindow(FALSE);
        m_ButtonStop.EnableWindow(FALSE);
        m_ButtonPause.EnableWindow(FALSE);

        // Cleanup from the last playback, if it exists
        FreeDirectShow();

        // Enable the second stream select button
        GetDlgItem(IDC_BUTTON_STREAM2)->EnableWindow(TRUE);
    }
}

void CBlenderDlg::OnButtonStream2() 
{
    HRESULT hr;

    // Select a file
    if (GetClipFileName(m_szFile2))
    {
        // Display the selected file name
        GetDlgItem(IDC_STATIC_STREAM2)->SetWindowText(m_szFile2);

        // Initialize the global strParam structure with default values
        InitStreamParams();

        // Initialize DirectShow and configure the VMR for two streams.
        // Both media files will be rendered.
        hr = InitializeVideo();

        if (SUCCEEDED(hr))
        {
            EnableControls(TRUE);
            SetSliders();
            DisplayFileDuration();

            // Set video position, size, and alpha values
            UpdatePinPos(0);
            UpdatePinPos(1);
            UpdatePinAlpha(0);
            UpdatePinAlpha(1);
        }
    }
}

HRESULT CBlenderDlg::GetUnconnectedPin(
    IBaseFilter *pFilter,   // Pointer to the filter.
    PIN_DIRECTION PinDir,   // Direction of the pin to find.
    IPin **ppPin)           // Receives a pointer to the pin.
{
    IEnumPins *pEnum = 0;
    IPin *pPin = 0;

    if (!ppPin)
        return E_POINTER;
    *ppPin = 0;

    // Get a pin enumerator
    HRESULT hr = pFilter->EnumPins(&pEnum);
    if (FAILED(hr))
        return hr;

    // Look for the first unconnected pin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -