windows-nt/Source/XPSP1/NT/printscan/ui/webview/camocx/preview.cpp
2020-09-26 16:20:57 +08:00

415 lines
10 KiB
C++

/*****************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORPORATION, 1999 - 2001
*
* TITLE: preview.cpp
*
* VERSION: 1.0
*
* AUTHOR: RickTu
*
* DATE: 10/30/99
*
* DESCRIPTION: Implements preview class for directshow devices in WIA
*
*****************************************************************************/
#include "precomp.h"
#pragma hdrstop
VOID CALLBACK PreviewTimerProc( HWND hDlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
{
switch (idEvent)
{
case TIMER_CLOSE_DIALOG:
WIA_TRACE((TEXT("PreviewTimerProc -- got TIMER_CLOSE_DIALOG")));
EndDialog( hDlg, -2 );
break;
}
}
/*****************************************************************************
PreviewDialogProc
Dialog proc for preview dialog.
*****************************************************************************/
INT_PTR CALLBACK PreviewDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch (uMsg)
{
case WM_INITDIALOG:
{
WIA_TRACE((TEXT("PreviewDialogProc -- WM_INITDIALOG")));
SetTimer( hDlg, TIMER_CLOSE_DIALOG, 30000, PreviewTimerProc );
PREVIEW_INFO_STRUCT * ppis = reinterpret_cast<PREVIEW_INFO_STRUCT *>(lParam);
if (ppis)
{
ppis->hDlg = hDlg;
if (ppis->hEvent)
{
SetEvent( ppis->hEvent );
}
}
}
return TRUE;
case PM_GOAWAY:
WIA_TRACE((TEXT("PreviewDialogProc -- PM_GOAWAY")));
EndDialog( hDlg, 0 );
return TRUE;
}
return FALSE;
}
/*****************************************************************************
PreviewThreadProc
We spin a thread to put up the status dialog
*****************************************************************************/
DWORD WINAPI PreviewThreadProc( LPVOID lpv )
{
INT_PTR iRes;
WIA_TRACE((TEXT("PreviewThreadProc enter")));
iRes = DialogBoxParam( _Module.m_hInst,
MAKEINTRESOURCE(IDD_INIT_DEVICE),
NULL,
PreviewDialogProc,
reinterpret_cast<LPARAM>(lpv)
);
WIA_TRACE((TEXT("IDD_INIT_DEVICE dialog returned %d"),iRes));
#ifdef DEBUG
if (iRes==-1)
{
WIA_ERROR((TEXT("DialogBoxParam failed w/GLE = %d"),GetLastError()));
}
#endif
if (iRes < 0)
{
PREVIEW_INFO_STRUCT * ppis = reinterpret_cast<PREVIEW_INFO_STRUCT *>(lpv);
if (ppis && ppis->hEvent)
{
SetEvent( ppis->hEvent );
}
}
WIA_TRACE((TEXT("PreviewThreadProc exit")));
return 0;
}
/*****************************************************************************
CVideoPreview::Device
Hand us a device pointer for the camera (or DS device) we're connected to.
*****************************************************************************/
STDMETHODIMP
CVideoPreview::Device(IUnknown * pDevice)
{
HRESULT hr = S_OK;
WIA_PUSHFUNCTION((TEXT("CVideoPreview::Device")));
// Create the WiaVideo object
hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER,
IID_IWiaVideo, (LPVOID *)&m_pWiaVideo);
WIA_CHECK_HR(hr,"CoCreateInstance( WiaVideo )");
m_pDevice = pDevice;
// if we've already been created, redo everything
if (m_bCreated)
{
BOOL bDummy;
OnCreate(WM_CREATE, 0, 0, bDummy);
}
return hr;
}
/*****************************************************************************
CVideoPreview::InPlaceDeactivate
Trap in place deactivate so we can unhook the dshow preview window from
ours before both are destroyed.
*****************************************************************************/
STDMETHODIMP
CVideoPreview::InPlaceDeactivate()
{
HRESULT hr = E_FAIL;
WIA_PUSHFUNCTION((TEXT("CVideoPreview::InPlaceDeactivate")));
//
// Make sure we have a pointer to the device...
//
if (m_pWiaVideo.p)
{
//
// Tell the device to close the graph
//
m_pWiaVideo->DestroyVideo();
m_pWiaVideo = NULL;
}
else
{
WIA_ERROR((TEXT("m_pWiaVideo is NULL")));
}
//
// Always return S_OK so that InPlaceDeactivate happens.
//
return S_OK;
}
/*****************************************************************************
CVideoPreview::OnSize
Called when our window is resized. We want to let the streaming
preview know we've been resized so it can reposition itself accordingly.
*****************************************************************************/
LRESULT
CVideoPreview::OnSize(UINT , WPARAM , LPARAM lParam, BOOL& )
{
WIA_PUSHFUNCTION((TEXT("CVideoPreview::OnSize")));
if (m_pWiaVideo)
{
m_pWiaVideo->ResizeVideo(FALSE);
}
else
{
WIA_ERROR((TEXT("m_pWiaVideo is NULL!")));
}
return 0;
}
LRESULT
CVideoPreview::OnCreate(UINT uMsg, WPARAM wp, LPARAM lp, BOOL &bHandled)
{
HRESULT hr = S_OK;
WIA_PUSHFUNCTION(TEXT("CVideoPreview::OnCreate"));
WIA_ASSERT(::IsWindow(m_hWnd));
if (m_pDevice.p && m_pWiaVideo.p)
{
HANDLE hThread = NULL;
DWORD dwId = 0;
PREVIEW_INFO_STRUCT pis;
//
// Creating the graph can be quite time consuming, so put up
// a dialog if it takes more than a couple of seconds. We start
// a thread so that the UI doesn't hang, and that thread
// puts up UI saying the device may take a while to initialize.
//
pis.hDlg = NULL;
pis.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
hThread = CreateThread( NULL, 0, PreviewThreadProc, reinterpret_cast<LPVOID>(&pis), 0, &dwId );
//
// Tell the device to build the DShow graph
//
BOOL bSuccess = TRUE;
HWND hwndFore = ::GetForegroundWindow();
HWND hwndFocus = ::GetFocus();
CSimpleString strDeviceID;
CSimpleString strImagesDirectory;
CComQIPtr<IWiaItem, &IID_IWiaItem> pRootDevice(m_pDevice);
if (pRootDevice == NULL)
{
hr = E_FAIL;
bSuccess = FALSE;
}
//
// Get the WIA Device ID
//
if (bSuccess)
{
bSuccess = PropStorageHelpers::GetProperty(pRootDevice,
WIA_DIP_DEV_ID,
strDeviceID);
}
//
// Get the directory the images will be stored in.
//
if (bSuccess)
{
bSuccess = PropStorageHelpers::GetProperty(pRootDevice,
WIA_DPV_IMAGES_DIRECTORY,
strImagesDirectory);
}
//
// Create the Video if it isn't already created.
if (bSuccess)
{
if (hr == S_OK)
{
WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
//
// Get the current state of the WiaVideo object. If we
// just created it then the state will be NO_VIDEO,
// otherwise, it could already be previewing video,
// in which case we shouldn't do anything.
//
hr = m_pWiaVideo->GetCurrentState(&VideoState);
if (VideoState == WIAVIDEO_NO_VIDEO)
{
//
// Set the directory we want to save our images to.
// We got the image directory from the Wia Video Driver
// IMAGES_DIRECTORY property
//
if (hr == S_OK)
{
hr = m_pWiaVideo->put_ImagesDirectory(CSimpleBStr(strImagesDirectory));
}
//
// Create the video preview as a child of the hwnd
// and automatically begin playback after creating the preview.
//
if (hr == S_OK)
{
hr = m_pWiaVideo->CreateVideoByWiaDevID(CSimpleBStr(strDeviceID),
m_hWnd,
FALSE,
TRUE);
}
}
}
}
if (!bSuccess)
{
hr = E_FAIL;
}
if (FAILED(hr))
{
//
// Let the user know that the graph is most likely already
// in use...
//
::MessageBox( NULL,
CSimpleString(IDS_VIDEO_BUSY_TEXT, _Module.m_hInst),
CSimpleString(IDS_VIDEO_BUSY_TITLE, _Module.m_hInst ),
MB_OK | MB_ICONWARNING | MB_TOPMOST | MB_SETFOREGROUND
);
}
//
// Restore foreground window & focus, as it seems the
// active movie window does not preserve these things...
//
if (hwndFore)
{
::SetForegroundWindow( hwndFore );
}
if (hwndFocus)
{
::SetFocus(hwndFocus);
}
//
// Tell the dialog to go away
//
if (hThread)
{
if (pis.hEvent)
{
//
// Wait for 45 seconds
//
WaitForSingleObject( pis.hEvent, 45 * 1000 );
if (pis.hDlg)
{
::PostMessage( pis.hDlg, PM_GOAWAY, 0, 0 );
}
CloseHandle( pis.hEvent );
pis.hEvent = NULL;
}
CloseHandle( hThread );
hThread = NULL;
}
}
bHandled = TRUE;
m_bCreated = TRUE;
return 0;
}
LRESULT
CVideoPreview::OnEraseBkgnd(UINT uMsg, WPARAM wp, LPARAM lp, BOOL &bHandled)
{
HDC hdc = (HDC)wp;
RECT rc;
GetClientRect(&rc);
SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
bHandled = TRUE;
return TRUE;
}