📄 bmpmix9.cpp
字号:
//------------------------------------------------------------------------------
// File: BmpMix9.cpp
//
// Desc: DirectShow sample code - a bitmap-mixing VMR9 media file player
// using Direct3D9 surfaces
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
#include "bmpmix9.h"
#include "vmrutil.h"
// Constants
#define MAX_LOADSTRING 100
#define TIMER_INTERVAL 500 // Refresh bitmap every 500ms
#define ALPHA_VALUE 0.6f // Alpha value for bitmap (0.0 to 1.0)
#define BMP_SIZE_X 0.3f // Width of bitmap in comp. space
#define BMP_SIZE_Y 0.3f // Height of bitmap in comp. space
#define MOVE_TOLERANCE 0.05f // Min. distance for mouse move before refresh
#define BMP_INIT_X 0.6f
#define BMP_INIT_Y 0.6f
// Global Variables
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // title bar text
TCHAR szWindowClass[MAX_LOADSTRING];
UINT_PTR g_nTimerID = 0xFCDCACCC;
int g_nCurrentImage=0;
float g_fCurrentX=BMP_INIT_X, g_fCurrentY=BMP_INIT_Y;
BOOL g_bRunning=FALSE;
// Foward declarations of functions included in this code module
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int, HWND& );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
void OnPaint(HWND hwnd);
void OnFileClose( HWND hWnd );
void HandleMouseClick(LPARAM lParam);
// DirectShow and D3D routines
HRESULT StartGraph(HWND window);
HRESULT D3DStart( HWND hWnd );
BOOL GetImageDimensions(long& lHeight, long& lWidth);
HRESULT SetInitialAlphaBitmap();
HRESULT UpdateAlphaBitmap(int nIndex);
HRESULT SetUpAlphaBitmap( VMR9AlphaBitmap& alphaBitmap, int nIndex );
void ClearD3D(void);
void ClearDirectShow(void);
// DirectShow objects
HWND g_hWnd;
CComPtr<IGraphBuilder> g_pGB;
CComPtr<IBaseFilter> g_pVMR;
CComPtr<IVMRFilterConfig9> g_pFilterConfig;
CComPtr<IVMRWindowlessControl9> g_pWC;
CComPtr<IMediaControl> g_pMC;
CComPtr<IVMRMixerBitmap9> g_pMixerBitmap;
// D3D objects
CComPtr<IDirect3D9> g_pD3D;
CComPtr<IDirect3DDevice9> g_pD3DDevice;
const int NUMBITMAPS = 3;
CComPtr<IDirect3DSurface9> g_pSurfaces[NUMBITMAPS];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
int nReturn = -1;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Verify that the VMR9 is present on this system
if(!VerifyVMR9())
{
CoUninitialize();
return FALSE;
}
__try
{
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_BMPMIX9, szWindowClass, MAX_LOADSTRING);
if (!MyRegisterClass(hInstance))
{
MessageBox(NULL, TEXT("Failed to register main window class!"),
TEXT("BmpMix9"), MB_ICONERROR | MB_OK);
__leave;
}
// Perform application initialization
if (!InitInstance (hInstance, nCmdShow, g_hWnd))
{
MessageBox(NULL, TEXT("Failed to initialize main window!"),
TEXT("BmpMix9"), MB_ICONERROR | MB_OK);
__leave;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_BMPMIX9);
// Main message loop
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
nReturn = (int) msg.wParam;
}
__finally
{
// Delete resources
// Release the CComPtr interfaces before uninitializing COM
ClearD3D();
ClearDirectShow();
CoUninitialize();
}
return nReturn;
}
_bstr_t GetMoviePath()
{
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
TCHAR szBuffer[MAX_PATH];
szBuffer[0] = NULL;
// Initialize the open file dialog structure
static const TCHAR szFilter[]
= TEXT("Video Files (.ASF, .AVI, .MPG, .MPEG, .VOB, .QT, .WMV)\0*.ASF;*.AVI;*.MPG;*.MPEG;*.VOB;*.QT;*.WMV\0") \
TEXT("All Files (*.*)\0*.*\0\0");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = g_hWnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.nFilterIndex = 1;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.lpstrFile = szBuffer;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = TEXT("Select a video file to play...");
ofn.Flags = OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = TEXT("AVI");
ofn.lCustData = 0L;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (GetOpenFileName (&ofn)) // user specified a file
return _bstr_t( szBuffer );
else
return "";
}
void ClearD3D(void)
{
// Initialize global data
for( int i = 0; i < NUMBITMAPS; ++i )
g_pSurfaces[i] = NULL;
// Zero CComPtrs to release interfaces and free memory
g_pD3DDevice = NULL;
g_pD3D = NULL;
}
void ClearDirectShow(void)
{
// Zero CComPtrs to release interfaces and free memory
g_pMixerBitmap = NULL;
g_pFilterConfig = NULL;
g_pMC = NULL;
g_pWC = NULL;
g_pVMR = NULL;
g_pGB = NULL;
g_fCurrentX = BMP_INIT_X;
g_fCurrentY = BMP_INIT_Y;
}
HRESULT StartGraph(HWND hwnd)
{
HRESULT hr;
// Prompt the user for a media file name
_bstr_t path = GetMoviePath();
if( ! path.length() )
{
return E_FAIL;
}
// Stop any currently running timer
KillTimer(g_hWnd, g_nTimerID);
UpdateWindow(g_hWnd);
// Initialize global data
ClearDirectShow();
// Create a filter graph
FAIL_RET( g_pGB.CoCreateInstance(CLSID_FilterGraph) )
// Create a VMR9 rendering filter and add it to the empty graph
FAIL_RET( g_pVMR.CoCreateInstance(CLSID_VideoMixingRenderer9,
NULL, CLSCTX_INPROC_SERVER) )
FAIL_RET( g_pGB->AddFilter(g_pVMR, L"Video Mixing Renderer 9") )
// Get the filter configuration interface and set VMR to Windowless rendering
FAIL_RET( g_pVMR->QueryInterface(IID_IVMRFilterConfig9,
reinterpret_cast<void**>(&g_pFilterConfig)) )
FAIL_RET( g_pFilterConfig->SetRenderingMode( VMR9Mode_Windowless ) )
// Bound the video clipping region to our application window
FAIL_RET( g_pVMR->QueryInterface(IID_IVMRWindowlessControl9,
reinterpret_cast<void**>(&g_pWC)) )
FAIL_RET( g_pWC->SetVideoClippingWindow( g_hWnd ) )
// Position the video within our application window
RECT clientRect;
if( ::GetClientRect(g_hWnd, &clientRect ) )
{
FAIL_RET( g_pWC->SetVideoPosition( NULL, &clientRect ) )
}
// Get the remaining necessary COM interfaces
FAIL_RET( g_pGB->QueryInterface(IID_IMediaControl,
reinterpret_cast<void**>(&g_pMC)) )
FAIL_RET( g_pVMR->QueryInterface(IID_IVMRMixerBitmap9,
reinterpret_cast<void**>(&g_pMixerBitmap)) )
// Initialize Direct3D 9
FAIL_RET( D3DStart( hwnd ) )
// Render and run the user-selected media file.
FAIL_RET( RenderFileToVMR9(g_pGB, path, g_pVMR));
// Associate an alpha-blended bitmap with the VMR
FAIL_RET( SetInitialAlphaBitmap( ) );
FAIL_RET( g_pMC->Run() )
// Start the timer for updating the alpha-blended bitmap
SetTimer( g_hWnd, g_nTimerID, TIMER_INTERVAL, NULL );
g_bRunning = TRUE;
return hr;
}
HRESULT D3DStart(HWND hWnd)
{
HRESULT hr;
ClearD3D();
// Initialize D3D
g_pD3D.Release(); // just in case this is called twice
g_pD3D.Attach(Direct3DCreate9( D3D_SDK_VERSION ) );
if( g_pD3D == NULL )
return E_FAIL;
D3DDISPLAYMODE d3ddm;
FAIL_RET( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.hDeviceWindow = g_hWnd;
FAIL_RET( g_pD3D->CreateDevice(
D3DADAPTER_DEFAULT, // always the primary display adapter
D3DDEVTYPE_HAL,
NULL,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pD3DDevice) )
// Read the dimensions of our alpha-blended bitmap
long lWidth, lHeight;
if( ! GetImageDimensions( lHeight, lWidth ) )
return E_FAIL;
// Create an offscreen D3D surface for each bitmap (in the set of 3)
for( int i = 0; i < NUMBITMAPS; ++i )
{
FAIL_RET( g_pD3DDevice->CreateOffscreenPlainSurface(
lWidth, lHeight,
D3DFMT_X8R8G8B8,
D3DPOOL_SYSTEMMEM,
&g_pSurfaces[i], NULL ) );
}
// Load the bitmaps into memory
FAIL_RET( D3DXLoadSurfaceFromResource (
g_pSurfaces[0],
NULL, // palette
NULL, // entire surface - created to be the proper height
GetModuleHandle(NULL), // current module
MAKEINTRESOURCE(IDB_BITMAP1),
NULL, // entire image
D3DX_DEFAULT,
0, // disable color key
NULL // source info
));
FAIL_RET( D3DXLoadSurfaceFromResource (
g_pSurfaces[1],
NULL,
NULL,
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDB_BITMAP2),
NULL, // entire image
D3DX_DEFAULT,
0,
NULL
));
FAIL_RET( D3DXLoadSurfaceFromResource (
g_pSurfaces[2],
NULL,
NULL,
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDB_BITMAP3),
NULL, // entire image
D3DX_DEFAULT,
0,
NULL
));
return hr;
}
BOOL GetImageDimensions(long& lHeight, long& lWidth)
{
BOOL ret = false;
HANDLE hBitmap = LoadImage(::GetModuleHandle(NULL),
MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -