Using Your Own Stage Window

You can switch playback to a window created by your application. If you supply your own window for movie playback, your window function must update the window when it is invalidated (see “Updating the Invalid Rectangle,” later in this chapter, for more information).

Supplying the Stage-Window Handle

Use the MCI_WINDOW command to switch playback to a window created by your application. Set the hWnd field of the MCI_ANIM_WINDOW_PARMS structure to the window handle. Then, send the MCI_WINDOW command with the MCI_ANIM_WINDOW_HWND flag.

The MCI Movie Driver hides the default stage window and uses the application-created window as the stage window. Your application owns the window function for the playback window, so it can monitor any user actions directed toward the stage window.

Use the MCI_ANIM_WINDOW_DEFAULT constant instead of a window handle to switch to the default window. The following code fragment shows how to do this:

MCI_ANIM_WINDOW_PARMS mciWindow;

mciWindow.hWnd = MCI_ANIM_WINDOW_DEFAULT;
dwError = mciSendCommand(wDeviceID, MCI_WINDOW, MCI_ANIM_WINDOW_HWND,
                         (DWORD)(LPVOID)&mciWindow);

if(dwError)                     // Check return value
    showError(dwError);

If the default window does not exist when an application sends a window-related command to the MCI Movie Driver, the driver creates a new default window; the application never loses the default playback window.

Updating the Invalid Rectangle

The window function for the stage window must handle WM_PAINT messages generated when the stage window is invalidated. In response to the WM_PAINT message, the stage-window function sends the MCI_UPDATE command message to the MCI Movie Driver. The MCI Movie Driver then handles the screen updates. The MCI_ANIM_UPDATE_PARMS parameter block specifies the handle to the device context and the invalid rectangle.

The following code fragment shows how to use the MCI_UPDATE message:

MCI_ANIM_UPDATE_PARMS mciUpdate;
PAINTSTRUCT ps;
    .
    .
    .
case WM_PAINT:
    hDC = BeginPaint(hWnd, &ps);
    mciUpdate.rc  = ps.rcPaint;
    mciUpdate.hDC = ps.hdc;
    dwError = mciSendCommand(wDeviceID, MCI_UPDATE,
                   MCI_ANIM_RECT | MCI_ANIM_UPDATE_HDC,
                   (DWORD)(LPVOID)&mciUpdate);
    EndPaint(hWnd, &ps);
    if(dwError)                         // Check return value
        showError(dwError);
    break;

Creating a Full-Screen Playback Window

The following code fragment creates a full-screen stage window, sends the window handle to the MCI Movie Driver, and centers the playback area within the window: example

BOOL CreateStage(HWND hWnd)
{
    MCI_ANIM_WINDOW_PARMS mciWindow;
    MCI_ANIM_RECT_PARMS   mciRect;
    DWORD dwError;
    RECT rc;

    hWndFull = CreateWindow( szFullScreenName, NULL, WS_POPUP,
        0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
        hWnd, NULL, hInst, NULL);

    if(hWndFull == NULL)
        return FALSE;

    // Pass handle to MCI Movie Driver, and center playback area

    mciWindow.hWnd = hWndFull;
    dwError = mciSendCommand(wDeviceID, MCI_WINDOW,
                              MCI_ANIM_WINDOW_HWND | MCI_WAIT,
                              (DWORD)(LPVOID)&mciWindow);



    if(dwError)                         // If MCI_WINDOW failed, exit
    {
        showError(dwError);
        return FALSE;
    }
    dwError = mciSendCommand(wDeviceID, MCI_WHERE,
                              MCI_ANIM_WHERE_SOURCE | MCI_ANIM_RECT,
                              (DWORD)(LPVOID)&mciRect);

    if(dwError)
        showError(dwError);
    else
    {
        GetClientRect(hWndFull, (LPRECT)&rc);

        mciRect.rc.top =  max(0, ((rc.bottom - mciRect.rc.bottom) / 2));
        mciRect.rc.left = max(0, ((rc.right  - mciRect.rc.right)  / 2));

        dwError = mciSendCommand(wDeviceID, MCI_PUT,
                                MCI_ANIM_PUT_DESTINATION | MCI_ANIM_RECT,
                                (DWORD)(LPVOID)&mciRect);
        if(dwError)
                        showError(dwError);
    }

    // Rewind

    dwError = mciSendCommand(wDeviceID, MCI_SEEK, MCI_SEEK_TO_START,
                                 (DWORD)(LPVOID)&mciSeek);
    if(dwError)
        showError(dwError);
    ShowWindow(hWndFull, SW_SHOW);
    return TRUE;
}

An application can specify the MCI_NOTIFY flag with the MCI_PLAY command that started the full-screen playback. The MCI Movie Driver then sends an MM_MCINOTIFY message to the specified window function when playback is finished. This capability is useful when playing on a full-screen window, because you need to give the user some way to get to the menu after playback is complete. See “Using the Notification Message,” earlier in this chapter, for a description of how an application might handle the notification message when playing in a full-screen window.

Summary: Writing the Window Function

The window function for the full-screen stage window handles WM_PAINT messages; it also captures WM_KEYDOWN messages, returning playback to the default stage window when the user presses the ESC key. The following code fragment shows the window function (note the use of the MCI_UPDATE command message):

LONG FAR PASCAL StageWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
{
    PAINTSTRUCT ps;
    HDC hDC;
    MCI_ANIM_WINDOW_PARMS mciWindow;
    MCI_ANIM_UPDATE_PARMS mciUpdate;
    MCI_ANIM_RECT_PARMS   mciRect;

    switch(wMsg)
    {
        case WM_DESTROY:
            ShowWindow(hWnd, SW_HIDE);

            // Transfer playback to default stage window
            mciWindow.hWnd = MCI_ANIM_WINDOW_DEFAULT;
            mciWindow.nCmdShow = SW_SHOW;
                        dwError = mciSendCommand(wDeviceID, MCI_WINDOW,
                MCI_ANIM_WINDOW_HWND | MCI_ANIM_WINDOW_STATE,
                (DWORD)(LPVOID)&mciWindow);
            if(dwError)
                showError(dwError);
            break;

        case WM_KEYDOWN:
            if(wParam == VK_ESCAPE)
                DestroyWindow(hWnd);
            break;

        case WM_PAINT:
            hDC = BeginPaint(hWnd, &ps);
            mciUpdate.rc  = ps.rcPaint;
            mciUpdate.hDC = ps.hdc;
            dwError = mciSendCommand(wDeviceID, MCI_UPDATE,
                    MCI_ANIM_UPDATE_HDC | MCI_ANIM_RECT,
                    (DWORD)(LPVOID)&mciUpdate);
            EndPaint(hWnd, &ps);
            if(dwError)
                showError(dwError);
            break;

        default:
            return DefWindowProc(hWnd, wMsg, wParam, lParam);
    }
    return 0L;
 }