Microsoft DirectX 8.1 (C++)

Hosting the Video Control in an ATL-based Application

This topic applies to Windows XP Home Edition and Windows XP Professional only.

This article shows how to create a limited TV viewer application, using ATL and the Video Control. The application hosts the Video Control inside a composite control. (A composite control is a type of ActiveX object that contains other controls.) To create the application, you must perform the following steps:

  1. Create the framework with the ATL AppWizard.
  2. Add the composite control, using the ATL CComCompositeControl class.
  3. Add the Video Control to the composite control.
  4. Add code for showing the composite control.
  5. Add code for submitting a tune request.

The remainder of this article describes these steps in more detail.

Create the Framework

Create a new project using the ATL COM AppWizard. Select Executable (EXE) for the server type. Include the header file Msvidctl.h, and link to the Strmiids.lib library.

Add the Composite Control

Use the ATL Object Wizard to insert the composite control. For this example, the default attributes are fine. Give the control a name; for example, MyComposite.

Add the Video Control

Use the Dialog Editor to add the Video Control to the composite control, by doing the following:

  1. Right click the dialog box.
  2. Choose Insert ActiveX Control.
  3. Select MS TV Video Control. It should appear in the list if Msvidctl.dll is registered on your system.

Also, check Visible in the dialog properties. Otherwise, the control will not be visible.

Show the Composite Control

The ATL Object Wizard creates a generic WinMain function. Inside this function, add code before the message loop that creates and displays the composite control. The following code snippet shows the code that you need to add, in bold:

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, 
    HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
    /* ... */

    //Create the window and show the composite control.
    AtlAxWinInit();
    HWND hWnd = ::CreateWindow(TEXT("AtlAxWin"), 
        TEXT("MyTvApp.MyComposite"),
        NULL,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL,
        ::GetModuleHandle(NULL), NULL);

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    /* ... */
}

Also, add a message handler for the WM_CLOSE message. In it, destroy the window and post a quit message:

LRESULT MyComposite::OnClose(
    UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    DestroyWindow();
    PostQuitMessage(0);
    return 0;
}

Create a Tune Request

It is preferable to get the tune request from the Guide Store. However, you can construct a tune request from scratch if you know the particular network type that you want to support. To make this example self-contained, the example makes the application automatically tune to ATSC physical channel 46 on startup. It does this inside the WM_INITDIALOG message handler. Here are the necessary steps:

  1. Create a system tuning spaces collection.
  2. Enumerate the tuning spaces to find the ATSC tuning space.
  3. Use the ATSC tuning space to create a new tune request.
  4. Create an ATSC locator object.
  5. Set the physical channel property on the locator.
  6. Associate the locator with the tune request.
  7. Give the tune request to the Video Control.
  8. Run the Video Control.

The following example omits any error checking. In working code, you should always check HRESULT return codes.

LRESULT MyComposite::OnInitDialog(
    UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    HRESULT hr = S_OK;
    
    // Create the tuning space collection.
    CComPtr<ITuningSpaceContainer> pTuningSpaceContainer;
    hr = pTuningSpaceContainer.CoCreateInstance(CLSID_SystemTuningSpaces,
        NULL, CLSCTX_INPROC_SERVER);
    
    // Get a pointer to the video control object.
    CComPtr<IMSVidCtl> pMSVidCtl;
    hr = GetDlgControl(IDC_MSVIDCTL1, IID_IMSVidCtl, 
        reinterpret_cast<void **>(&pMSVidCtl));
    
    // Find the ATSC tuning space in the collection.
    CComPtr<IEnumTuningSpaces> pEnumTuningSpaces;
    CComBSTR bstrATSC(L"ATSC");
    CComPtr<ITuningSpace> pTuningSpace;

    hr = pTuningSpaceContainer->get_EnumTuningSpaces(&pEnumTuningSpaces);
    while (S_OK == pEnumTuningSpaces->Next(1, &pTuningSpace, NULL))
    {
        CComBSTR bstrTemp;
        hr = pTuningSpace->get_UniqueName(&bstrTemp);
        if (bstrTemp == bstrATSC)
        {
            break;  // Found it.
        }
        pTuningSpace = NULL;  // Release for the next loop.
    }
    
    if (pTuningSpace == NULL) // Did not find it.
    {
        MessageBox(TEXT("Could not find ATSC tuning space."), 
            TEXT("Error"), MB_OK);
        return hr;
    }
    
    // Create an ATSC Tune Request.
    CComPtr<IATSCTuningSpace> pATSCTuningSpace;
    pTuningSpace.QueryInterface(&pATSCTuningSpace);
    CComPtr<ITuneRequest> pTuneRequest;
    hr = pATSCTuningSpace->CreateTuneRequest(&pTuneRequest);
    
    // Create an ATSC Locator and set the physical channel.
    CComPtr<IATSCLocator> pATSCLocator;
    pATSCLocator.CoCreateInstance(CLSID_ATSCLocator, NULL, 
        CLSCTX_INPROC_SERVER);
    hr = pATSCLocator->put_PhysicalChannel(46);
    
    // Set the channel and minor channel properties on the tune request
    // to -1. The network provider will set these properties after it
    // tunes to the ATSC channel.
    CComPtr<IATSCChannelTuneRequest> pATSCTuneRequest;
    pTuneRequest.QueryInterface(&pATSCTuneRequest);
    hr = pATSCTuneRequest->put_Channel(-1);
    hr = pATSCTuneRequest->put_MinorChannel(-1);

    // Bind the locator to the tune request.
    hr = pATSCTuneRequest->put_Locator(pATSCLocator);
    
    // Give the tune request to the Video Control.
    CComVariant var(pATSCTuneRequest);
    hr = pMSVidCtl->View(&var);
    hr = pMSVidCtl->Run();
    
    return hr;
};

As this example shows, when the application builds the tune request, it must target specific network types. On the other hand, if it always gets the tune request from the Guide Store, it will function with any supported network type.