📄 bmpmix9.cpp
字号:
0,0, // size
LR_DEFAULTCOLOR | LR_DEFAULTSIZE );
if( hBitmap )
{
BITMAP bmpInfo;
if( ::GetObject( hBitmap, sizeof(bmpInfo), &bmpInfo ) )
{
lHeight = bmpInfo.bmHeight;
lWidth = bmpInfo.bmWidth;
ret = true;
}
}
DeleteObject( hBitmap );
return ret;
}
HRESULT SetInitialAlphaBitmap()
{
HRESULT hr = E_FAIL;
VMR9AlphaBitmap alphaBitmap;
// Initialize the alpha bitmap
FAIL_RET( SetUpAlphaBitmap( alphaBitmap, 0 ) );
// Apply the bitmap to the VMR
FAIL_RET( g_pMixerBitmap->SetAlphaBitmap( &alphaBitmap ) );
return hr;
}
HRESULT UpdateAlphaBitmap(int nIndex)
{
HRESULT hr = E_FAIL;
VMR9AlphaBitmap alphaBitmap;
// Update the bitmap by index
FAIL_RET( SetUpAlphaBitmap( alphaBitmap, nIndex ) );
// Apply the bitmap to the VMR
FAIL_RET( g_pMixerBitmap->SetAlphaBitmap( &alphaBitmap ) );
return hr;
}
HRESULT SetUpAlphaBitmap( VMR9AlphaBitmap& alphaBitmap, int nIndex )
{
if( g_pMixerBitmap == NULL || g_pSurfaces[nIndex] == NULL )
{
return E_FAIL;
}
ZeroMemory( &alphaBitmap, sizeof VMR9AlphaBitmap);
// Initialize VMR9AlphaBitmap structure
alphaBitmap.dwFlags = VMR9AlphaBitmap_EntireDDS | VMR9AlphaBitmap_SrcColorKey;
alphaBitmap.hdc = NULL;
alphaBitmap.pDDS = g_pSurfaces[nIndex];
alphaBitmap.clrSrcKey = RGB(255,255,255); // white background
// Position the bitmap within the VMR's composition space (0.0 - 1.0).
// Because the bitmap can move on mouse clicks, keep track of the
// current X and Y positions. The width/height of the alpha-bitmap are
// predetermined by constant sizes.
alphaBitmap.rDest.top = g_fCurrentY - BMP_SIZE_Y / 2;
alphaBitmap.rDest.left = g_fCurrentX - BMP_SIZE_X / 2;
alphaBitmap.rDest.bottom = g_fCurrentY + BMP_SIZE_Y / 2;
alphaBitmap.rDest.right = g_fCurrentX + BMP_SIZE_X / 2;
alphaBitmap.fAlpha = ALPHA_VALUE;
return S_OK;
}
HRESULT MoveAlphaBitmap(float fX, float fY)
{
HRESULT hr=S_OK;
VMR9AlphaBitmap alphaBitmap;
if( g_pMixerBitmap == NULL || g_pSurfaces[g_nCurrentImage] == NULL )
{
return E_FAIL;
}
ZeroMemory( &alphaBitmap, sizeof VMR9AlphaBitmap);
// Initialize VMR9AlphaBitmap structure
alphaBitmap.dwFlags = VMR9AlphaBitmap_EntireDDS | VMR9AlphaBitmap_SrcColorKey;
alphaBitmap.hdc = NULL;
alphaBitmap.pDDS = g_pSurfaces[g_nCurrentImage];
alphaBitmap.clrSrcKey = RGB(255,255,255);
// Position the bitmap within the VMR's composition space (0.0 - 1.0)
// centered around the mouse point
alphaBitmap.rDest.top = fY - BMP_SIZE_Y / 2;
alphaBitmap.rDest.left = fX - BMP_SIZE_X / 2;
alphaBitmap.rDest.bottom = fY + BMP_SIZE_Y / 2;
alphaBitmap.rDest.right = fX + BMP_SIZE_X / 2;
alphaBitmap.fAlpha = ALPHA_VALUE;
// Apply the bitmap to the VMR
FAIL_RET( g_pMixerBitmap->SetAlphaBitmap( &alphaBitmap ) );
// We successfully set the value, so remember the current coordinates
g_fCurrentX = fX;
g_fCurrentY = fY;
return S_OK;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(wcex));
// Set the members of the window class structure.
// Don't provide a background brush, because we process the WM_PAINT
// messages in OnPaint(). If a movie is active, we tell the VMR to
// repaint the window; otherwise, we repaint with COLOR_WINDOW+1.
// If a background brush is provided, you will see a white flicker
// whenever you resize the main application window, because Windows
// will repaint the window before the application also repaints.
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_BMPMIX9);
wcex.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_BMPMIX9);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszMenuName = (LPCTSTR)IDC_BMPMIX9;
wcex.lpszClassName = szWindowClass;
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, HWND& hWnd)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// Message handler for about box
LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HRESULT hr;
switch (message)
{
case WM_COMMAND:
{
int nId, nEvent;
nId = LOWORD(wParam);
nEvent = HIWORD(wParam);
// Parse the menu selections:
switch (nId)
{
case IDM_PLAY_FILE:
hr = StartGraph(g_hWnd);
if( FAILED(hr) )
{
MessageBox(NULL, TEXT("Failed to create the VMR9 graph!"),
TEXT("BitmapMix9 failure!"), MB_OK);
}
g_nCurrentImage = 0;
break;
case IDM_FILE_CLOSE:
OnFileClose( hWnd );
break;
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)AboutDlgProc);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
}
break;
}
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_MOUSEMOVE:
// If the left mouse button is down, treat this as a drag operation
if (wParam & MK_LBUTTON)
HandleMouseClick(lParam);
break;
case WM_LBUTTONDOWN:
HandleMouseClick(lParam);
break;
case WM_DISPLAYCHANGE:
if( g_pWC )
g_pWC->DisplayModeChanged();
break;
case WM_SIZE:
if( g_pWC )
{
RECT clientRect;
if( ::GetClientRect( g_hWnd, &clientRect ) )
{
g_pWC->SetVideoPosition(NULL, &clientRect );
}
}
break;
case WM_TIMER:
if( (UINT_PTR) wParam == g_nTimerID )
{
// Rotate through our list of bitmaps
g_nCurrentImage++;
g_nCurrentImage %= NUMBITMAPS;
hr = UpdateAlphaBitmap(g_nCurrentImage);
if( FAILED( hr ) )
return 0;
}
break;
case WM_DESTROY:
KillTimer(g_hWnd, g_nTimerID);
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void OnFileClose( HWND hWnd )
{
if( g_pMC != NULL )
{
OAFilterState state;
do {
g_pMC->Stop();
g_pMC->GetState(0, & state );
} while( state != State_Stopped ) ;
}
ClearD3D();
ClearDirectShow();
::InvalidateRect( hWnd, NULL, TRUE );
}
void OnPaint(HWND hwnd)
{
HRESULT hr;
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
hdc = BeginPaint(hwnd, &ps);
if(g_pWC)
{
// 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.
if (g_pWC)
hr = g_pWC->RepaintVideo(hwnd, hdc);
}
else // No video image. Just paint the whole client area.
{
FillRect(hdc, &rcClient, (HBRUSH)(COLOR_WINDOW + 1));
}
EndPaint(hwnd, &ps);
}
void HandleMouseClick(LPARAM lParam)
{
// Make sure that we're already playing the movie
if (!g_bRunning)
return;
// Get the window coordinates of the mouse pointer
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
// Get the window client area rectangle
RECT rcClient;
GetClientRect(g_hWnd, &rcClient);
// Convert the click position into composition space coordinates,
// which range from 0.0 to 1.0
float fX, fY;
fX = (float) ((float)xPos / (float)rcClient.right );
fY = (float) ((float)yPos / (float)rcClient.bottom );
// Bound coordinates to allowed space
if (fX > 1.0) fX = 1.0; if (fX < 0.0) fX = 0.0;
if (fY > 1.0) fY = 1.0; if (fY < 0.0) fY = 0.0;
// Because mouse movement messages can be very frequent,
// only update the bitmap if it has moved a sufficient distance.
if ((fabs(fX - g_fCurrentX) >= MOVE_TOLERANCE) ||
(fabs(fY - g_fCurrentY) >= MOVE_TOLERANCE))
{
MoveAlphaBitmap(fX, fY);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -