Microsoft DirectX 8.1 (C++) |
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:
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:
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:
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.