winmain.cpp
Cette rubrique contient du code pour le tutoriel Comment lire des fichiers multimédias avec Media Foundation.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "Player.h"
PCWSTR szTitle = L"BasicPlayback";
PCWSTR szWindowClass = L"MFBASICPLAYBACK";
HINSTANCE g_hInstance; // current instance
BOOL g_bRepaintClient = TRUE; // Repaint the application client area?
CPlayer *g_pPlayer = NULL; // Global player object.
// Note: After WM_CREATE is processed, g_pPlayer remains valid until the
// window is destroyed.
// Forward declarations of functions included in this code module:
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK OpenUrlDialogProc(HWND, UINT, WPARAM, LPARAM);
void NotifyError(HWND hwnd, const WCHAR *sErrorMessage, HRESULT hr);
void UpdateUI(HWND hwnd, PlayerState state);
HRESULT AllocGetWindowText(HWND hwnd, WCHAR **pszText, DWORD *pcchLen);
// Message handlers
LRESULT OnCreateWindow(HWND hwnd);
void OnFileOpen(HWND hwnd);
void OnOpenURL(HWND hwnd);
void OnPlayerEvent(HWND hwnd, WPARAM pUnkPtr);
void OnPaint(HWND hwnd);
void OnResize(WORD width, WORD height);
void OnKeyPress(WPARAM key);
// OpenUrlDialogInfo: Contains data passed to the "Open URL" dialog proc.
struct OpenUrlDialogInfo
{
WCHAR *pszURL;
DWORD cch;
};
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow)
{
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
// Perform application initialization.
if (!InitInstance(hInstance, nCmdShow))
{
NotifyError(NULL, L"Could not initialize the application.",
HRESULT_FROM_WIN32(GetLastError()));
return FALSE;
}
// Main message loop.
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Clean up.
if (g_pPlayer)
{
g_pPlayer->Shutdown();
SafeRelease(&g_pPlayer);
}
return 0;
}
// Create the application window.
BOOL InitInstance(HINSTANCE hInst, int nCmdShow)
{
HWND hwnd;
WNDCLASSEX wcex;
g_hInstance = hInst; // Store the instance handle.
// Register the window class.
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInst;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_MFPLAYBACK);
wcex.lpszClassName = szWindowClass;
if (RegisterClassEx(&wcex) == 0)
{
return FALSE;
}
// Create the application window.
hwnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL);
if (hwnd == 0)
{
return FALSE;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return TRUE;
}
// Message handler for the main window.
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
return OnCreateWindow(hwnd);
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_EXIT:
DestroyWindow(hwnd);
break;
case ID_FILE_OPENFILE:
OnFileOpen(hwnd);
break;
case ID_FILE_OPENURL:
OnOpenURL(hwnd);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
break;
case WM_PAINT:
OnPaint(hwnd);
break;
case WM_SIZE:
OnResize(LOWORD(lParam), HIWORD(lParam));
break;
case WM_ERASEBKGND:
// Suppress window erasing, to reduce flickering while the video is playing.
return 1;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CHAR:
OnKeyPress(wParam);
break;
case WM_APP_PLAYER_EVENT:
OnPlayerEvent(hwnd, wParam);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
// Open an audio/video file.
void OnFileOpen(HWND hwnd)
{
IFileOpenDialog *pFileOpen = NULL;
IShellItem *pItem = NULL;
PWSTR pszFilePath = NULL;
// Create the FileOpenDialog object.
HRESULT hr = CoCreateInstance(__uuidof(FileOpenDialog), NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileOpen));
if (FAILED(hr))
{
goto done;
}
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
// The user canceled the dialog. Do not treat as an error.
hr = S_OK;
goto done;
}
else if (FAILED(hr))
{
goto done;
}
// Get the file name from the dialog box.
hr = pFileOpen->GetResult(&pItem);
if (FAILED(hr))
{
goto done;
}
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
if (FAILED(hr))
{
goto done;
}
// Display the file name to the user.
hr = g_pPlayer->OpenURL(pszFilePath);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, OpenPending);
}
done:
if (FAILED(hr))
{
NotifyError(hwnd, L"Could not open the file.", hr);
UpdateUI(hwnd, Closed);
}
CoTaskMemFree(pszFilePath);
SafeRelease(&pItem);
SafeRelease(&pFileOpen);
}
// Open a media file from a URL.
void OnOpenURL(HWND hwnd)
{
HRESULT hr = S_OK;
// Pass in an OpenUrlDialogInfo structure to the dialog. The dialog
// fills in this structure with the URL. The dialog proc allocates
// the memory for the string.
OpenUrlDialogInfo url;
ZeroMemory(&url, sizeof(&url));
// Show the Open URL dialog.
if (IDOK == DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_OPENURL), hwnd,
OpenUrlDialogProc, (LPARAM)&url))
{
// Open the file with the playback object.
hr = g_pPlayer->OpenURL(url.pszURL);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, OpenPending);
}
else
{
NotifyError(hwnd, L"Could not open this URL.", hr);
UpdateUI(hwnd, Closed);
}
}
// The caller must free the URL string.
CoTaskMemFree(url.pszURL);
}
// Handler for WM_CREATE message.
LRESULT OnCreateWindow(HWND hwnd)
{
// Initialize the player object.
HRESULT hr = CPlayer::CreateInstance(hwnd, hwnd, &g_pPlayer);
if (SUCCEEDED(hr))
{
UpdateUI(hwnd, Closed);
return 0; // Success.
}
else
{
NotifyError(NULL, L"Could not initialize the player object.", hr);
return -1; // Destroy the window
}
}
// Handler for WM_PAINT messages.
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
if (g_pPlayer && g_pPlayer->HasVideo())
{
// Video is playing. Ask the player to repaint.
g_pPlayer->Repaint();
}
else
{
// The video is not playing, so we must paint the application window.
RECT rc;
GetClientRect(hwnd, &rc);
FillRect(hdc, &rc, (HBRUSH) COLOR_WINDOW);
}
EndPaint(hwnd, &ps);
}
// Handler for WM_SIZE messages.
void OnResize(WORD width, WORD height)
{
if (g_pPlayer)
{
g_pPlayer->ResizeVideo(width, height);
}
}
// Handler for WM_CHAR messages.
void OnKeyPress(WPARAM key)
{
switch (key)
{
// Space key toggles between running and paused
case VK_SPACE:
if (g_pPlayer->GetState() == Started)
{
g_pPlayer->Pause();
}
else if (g_pPlayer->GetState() == Paused)
{
g_pPlayer->Play();
}
break;
}
}
// Handler for Media Session events.
void OnPlayerEvent(HWND hwnd, WPARAM pUnkPtr)
{
HRESULT hr = g_pPlayer->HandleEvent(pUnkPtr);
if (FAILED(hr))
{
NotifyError(hwnd, L"An error occurred.", hr);
}
UpdateUI(hwnd, g_pPlayer->GetState());
}
// Update the application UI to reflect the current state.
void UpdateUI(HWND hwnd, PlayerState state)
{
BOOL bWaiting = FALSE;
BOOL bPlayback = FALSE;
assert(g_pPlayer != NULL);
switch (state)
{
case OpenPending:
bWaiting = TRUE;
break;
case Started:
bPlayback = TRUE;
break;
case Paused:
bPlayback = TRUE;
break;
}
HMENU hMenu = GetMenu(hwnd);
UINT uEnable = MF_BYCOMMAND | (bWaiting ? MF_GRAYED : MF_ENABLED);
EnableMenuItem(hMenu, ID_FILE_OPENFILE, uEnable);
EnableMenuItem(hMenu, ID_FILE_OPENURL, uEnable);
if (bPlayback && g_pPlayer->HasVideo())
{
g_bRepaintClient = FALSE;
}
else
{
g_bRepaintClient = TRUE;
}
}
// Show a message box with an error message.
void NotifyError(HWND hwnd, PCWSTR pszErrorMessage, HRESULT hrErr)
{
const size_t MESSAGE_LEN = 512;
WCHAR message[MESSAGE_LEN];
if (SUCCEEDED(StringCchPrintf(message, MESSAGE_LEN, L"%s (HRESULT = 0x%X)",
pszErrorMessage, hrErr)))
{
MessageBox(hwnd, message, NULL, MB_OK | MB_ICONERROR);
}
}
// Dialog proc for the "Open URL" dialog.
INT_PTR CALLBACK OpenUrlDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static OpenUrlDialogInfo *pUrl = NULL;
BOOL result = FALSE;
switch (message)
{
case WM_INITDIALOG:
// The caller sends a pointer to an OpenUrlDialogInfo structure as the
// lParam. This structure stores the URL.
pUrl = (OpenUrlDialogInfo*)lParam;
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (pUrl)
{
// Get the URL from the edit box in the dialog. This function
// allocates memory. The caller must call CoTaskMemAlloc.
if (SUCCEEDED(AllocGetWindowText(GetDlgItem(hDlg, IDC_EDIT_URL),
&pUrl->pszURL, &pUrl->cch)))
{
result = TRUE;
}
}
EndDialog(hDlg, result ? IDOK : IDABORT);
break;
case IDCANCEL:
EndDialog(hDlg, LOWORD(IDCANCEL));
break;
}
return (INT_PTR)FALSE;
}
return (INT_PTR)FALSE;
}
// Helper function to get text from a window.
//
// This function allocates a buffer and returns it in pszText. The caller must
// call CoTaskMemFree on the buffer.
//
// hwnd: Handle to the window.
// pszText: Receives a pointer to the string.
// pcchLen: Receives the length of the string, in characters, not including
// the terminating NULL character.
HRESULT AllocGetWindowText(HWND hwnd, WCHAR **pszText, DWORD *pcchLen)
{
if (pszText == NULL || pcchLen == NULL)
{
return E_POINTER;
}
*pszText = NULL;
int cch = GetWindowTextLength(hwnd);
if (cch < 0)
{
return E_UNEXPECTED;
}
PWSTR pszTmp = (PWSTR)CoTaskMemAlloc(sizeof(WCHAR) * (cch + 1));
// Includes room for terminating NULL character
if (!pszTmp)
{
return E_OUTOFMEMORY;
}
if (cch == 0)
{
pszTmp[0] = L'\0'; // No text.
}
else
{
int res = GetWindowText(hwnd, pszTmp, (cch + 1));
// Size includes terminating null character.
// GetWindowText returns 0 if (a) there is no text or (b) it failed.
// We checked for (a) already, so 0 means failure here.
if (res == 0)
{
CoTaskMemFree(pszTmp);
return __HRESULT_FROM_WIN32(GetLastError());
}
}
// If we got here, szTmp is valid, so return it to the caller.
*pszText = pszTmp;
// Return the length NOT including the '\0'.
*pcchLen = static_cast<DWORD>(cch);
return S_OK;
}
Rubriques connexes
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour