/***************************************************************************** * * (C) CORPYRIGHT MICROSOFT CORPORATION, 1999 - 2000 * * TITLE: videodlg.cpp * * VERSION: 1.0 * * AUTHOR: RickTu * * DATE: 10/14/99 * * DESCRIPTION: Implementation of DialogProc for video capture common dialog * *****************************************************************************/ #include #pragma hdrstop #include "wiacsh.h" #include "modlock.h" #include "wiadevdp.h" // // Help IDs // static const DWORD g_HelpIDs[] = { IDC_VIDDLG_BIG_TITLE, -1, IDC_VIDDLG_LITTLE_TITLE, -1, IDC_VIDDLG_PREVIEW, IDH_WIA_VIDEO, IDC_VIDDLG_THUMBNAILLIST, IDH_WIA_CAPTURED_IMAGES, IDC_VIDDLG_CAPTURE, IDH_WIA_CAPTURE, IDOK, IDH_WIA_VIDEO_GET_PICTURE, IDCANCEL, IDH_CANCEL, 0, 0 }; #define IDC_SIZEBOX 1113 // // If the callee doesn't return this value, we delete the message data ourselves. // #ifndef HANDLED_THREAD_MESSAGE #define HANDLED_THREAD_MESSAGE 2032 #endif // Thumbnail whitespace: the space in between images and their selection rectangles // CThese values were discovered by trail and error. For instance, if you reduce // c_nAdditionalMarginY to 20, you get really bizarre spacing problems in the list view // in vertical mode. These values could become invalid in future versions of the listview. static const int c_nAdditionalMarginX = 10; static const int c_nAdditionalMarginY = 6; static int c_nMinThumbnailWidth = 90; static int c_nMinThumbnailHeight = 90; static int c_nMaxThumbnailWidth = 120; static int c_nMaxThumbnailHeight = 120; // // Map of background thread messages // static CThreadMessageMap g_MsgMap[] = { { TQ_DESTROY, CVideoCaptureDialog::OnThreadDestroy}, { TQ_GETTHUMBNAIL, CVideoCaptureDialog::OnGetThumbnail}, { 0, NULL} }; class CGlobalInterfaceTableThreadMessage : public CNotifyThreadMessage { private: DWORD m_dwGlobalInterfaceTableCookie; private: // No implementation CGlobalInterfaceTableThreadMessage(void); CGlobalInterfaceTableThreadMessage &operator=( const CGlobalInterfaceTableThreadMessage & ); CGlobalInterfaceTableThreadMessage( const CGlobalInterfaceTableThreadMessage & ); public: CGlobalInterfaceTableThreadMessage( int nMessage, HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie ) : CNotifyThreadMessage( nMessage, hWndNotify ), m_dwGlobalInterfaceTableCookie(dwGlobalInterfaceTableCookie) { } DWORD GlobalInterfaceTableCookie(void) const { return(m_dwGlobalInterfaceTableCookie); } }; class CThumbnailThreadMessage : public CGlobalInterfaceTableThreadMessage { private: SIZE m_sizeThumb; private: // No implementation CThumbnailThreadMessage(void); CThumbnailThreadMessage &operator=( const CThumbnailThreadMessage & ); CThumbnailThreadMessage( const CThumbnailThreadMessage & ); public: CThumbnailThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, const SIZE &sizeThumb ) : CGlobalInterfaceTableThreadMessage( TQ_GETTHUMBNAIL, hWndNotify, dwGlobalInterfaceTableCookie ), m_sizeThumb(sizeThumb) { } const SIZE &ThumbSize(void) const { return(m_sizeThumb); } }; // // Avoids unnecessary state changes // static inline VOID MyEnableWindow( HWND hWnd, BOOL bEnable ) { if (bEnable && !IsWindowEnabled(hWnd)) { EnableWindow(hWnd,TRUE); } else if (!bEnable && IsWindowEnabled(hWnd)) { EnableWindow(hWnd,FALSE); } } /***************************************************************************** CVideoCaptureDialog constructor We don't have a destructor *****************************************************************************/ CVideoCaptureDialog::CVideoCaptureDialog( HWND hWnd ) : m_hWnd(hWnd), m_bFirstTime(true), m_hBigFont(NULL), m_nListViewWidth(0), m_hIconLarge(NULL), m_hIconSmall(NULL), m_hBackgroundThread(NULL), m_nDialogMode(0), m_hAccelTable(NULL), m_nParentFolderImageListIndex(0), m_pThreadMessageQueue(NULL) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::CVideoCaptureDialog"))); m_pThreadMessageQueue = new CThreadMessageQueue; if (m_pThreadMessageQueue) { // // Note that CBackgroundThread takes ownership of m_pThreadMessageQueue, and it doesn't have to be deleted in this thread // m_hBackgroundThread = CBackgroundThread::Create( m_pThreadMessageQueue, g_MsgMap, m_CancelEvent.Event(), g_hInstance ); } m_CurrentAspectRatio.cx = 4; m_CurrentAspectRatio.cy = 3; m_sizeThumbnails.cx = c_nMaxThumbnailWidth; m_sizeThumbnails.cy = c_nMaxThumbnailHeight; WIA_ASSERT(m_hBackgroundThread != NULL); } /***************************************************************************** CVideoCaptureDialog::OnInitDialog Handle WM_INITIDIALOG *****************************************************************************/ LRESULT CVideoCaptureDialog::OnInitDialog( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnInitDialog")); HRESULT hr; // // Make sure the background queue was successfully created // if (!m_pThreadMessageQueue) { WIA_ERROR((TEXT("VIDEODLG: unable to start background queue"))); EndDialog( m_hWnd, E_OUTOFMEMORY ); return(0); } // // Save incoming data // m_pDeviceDialogData = (PDEVICEDIALOGDATA)lParam; // // Make sure we have valid arguments // if (!m_pDeviceDialogData) { WIA_ERROR((TEXT("VIDEODLG: Invalid paramater: PDEVICEDIALOGDATA"))); EndDialog( m_hWnd, E_INVALIDARG ); return(0); } // // Initialialize our return stuff // if (m_pDeviceDialogData) { m_pDeviceDialogData->lItemCount = 0; m_pDeviceDialogData->ppWiaItems = NULL; } // // Make sure we have a valid device // if (!m_pDeviceDialogData->pIWiaItemRoot) { WIA_ERROR((TEXT("VIDEODLG: Invalid paramaters: pIWiaItem"))); EndDialog( m_hWnd, E_INVALIDARG ); return(0); } // // Get deviceID for this device // PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,m_strwDeviceId); // // Register for device disconnected, item creation and deletion events... // hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (LPVOID *)&m_pDevMgr ); WIA_CHECK_HR(hr,"CoCreateInstance( WiaDevMgr )"); if (SUCCEEDED(hr) && m_pDevMgr) { CVideoCallback *pVC = new CVideoCallback(); if (pVC) { hr = pVC->Initialize( m_hWnd ); WIA_CHECK_HR(hr,"pVC->Initialize()"); if (SUCCEEDED(hr)) { CComPtr pWiaEventCallback; hr = pVC->QueryInterface( IID_IWiaEventCallback, (void**)&pWiaEventCallback ); WIA_CHECK_HR(hr,"pVC->QI( IID_IWiaEventCallback )"); if (SUCCEEDED(hr) && pWiaEventCallback) { CSimpleBStr bstr( m_strwDeviceId ); hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK, bstr, &WIA_EVENT_DEVICE_DISCONNECTED, pWiaEventCallback, &m_pDisconnectedCallback ); WIA_CHECK_HR(hr,"RegisterEvent( DEVICE_DISCONNECTED )"); hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK, bstr, &WIA_EVENT_ITEM_DELETED, pWiaEventCallback, &m_pCreateCallback ); WIA_CHECK_HR(hr,"RegisterEvent( ITEM_DELETE )"); hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK, bstr, &WIA_EVENT_ITEM_CREATED, pWiaEventCallback, &m_pDeleteCallback ); WIA_CHECK_HR(hr,"RegisterEvent( ITEM_CREATED )"); } else { WIA_ERROR((TEXT("Either QI failed or pWiaEventCallback is NULL!"))); } } pVC->Release(); } } if (SUCCEEDED(hr) ) { // Create the WiaVideo object hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER, IID_IWiaVideo, (LPVOID *)&m_pWiaVideo); WIA_CHECK_HR(hr,"CoCreateInstance( WiaVideo )"); } // // Prevent multiple selection // if (m_pDeviceDialogData->dwFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE) { LONG_PTR lStyle = GetWindowLongPtr( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), GWL_STYLE ); SetWindowLongPtr( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), GWL_STYLE, lStyle | LVS_SINGLESEL ); m_nDialogMode = SINGLESEL_MODE; // // Hide the "Select All" button // ShowWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ), SW_HIDE ); // // Change text accordingly // CSimpleString( IDS_VIDDLG_TITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_VIDDLG_BIG_TITLE ) ); CSimpleString( IDS_VIDDLG_SUBTITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ) ); CSimpleString( IDS_VIDDLG_OK_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) ); } else { m_nDialogMode = MULTISEL_MODE; } // // Make the lovely font // m_hBigFont = WiaUiUtil::CreateFontWithPointSizeFromWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_BIG_TITLE), 14, false, false ); if (m_hBigFont) { SendDlgItemMessage( m_hWnd, IDC_VIDDLG_BIG_TITLE, WM_SETFONT, reinterpret_cast(m_hBigFont), MAKELPARAM(TRUE,0) ); } // // Save the minimum size of the dialog // RECT rcWindow; GetWindowRect( m_hWnd, &rcWindow ); m_sizeMinimumWindow.cx = rcWindow.right - rcWindow.left; m_sizeMinimumWindow.cy = rcWindow.bottom - rcWindow.top; // // Create the sizing control // HWND hWndSizingControl = CreateWindowEx( 0, TEXT("scrollbar"), TEXT(""), WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP|WS_CLIPSIBLINGS|SBS_SIZEBOXBOTTOMRIGHTALIGN|SBS_BOTTOMALIGN|WS_GROUP, CSimpleRect(m_hWnd).Width()-GetSystemMetrics(SM_CXVSCROLL), CSimpleRect(m_hWnd).Height()-GetSystemMetrics(SM_CYHSCROLL), GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL), m_hWnd, reinterpret_cast(IDC_SIZEBOX), g_hInstance, NULL ); if (!hWndSizingControl) { WIA_ERROR((TEXT("CreateWindowEx( sizing control ) failed!"))); } // // Reposition all the controls // ResizeAll(); // // Center the window over its parent // WiaUiUtil::CenterWindow( m_hWnd, GetParent(m_hWnd) ); // // Get the device icons and set the window icons // CSimpleStringWide strwDeviceId, strwClassId; LONG nDeviceType; if (PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_UI_CLSID,strwClassId) && PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,strwDeviceId) && PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_TYPE,nDeviceType)) { if (SUCCEEDED(WiaUiExtensionHelper::GetDeviceIcons( CSimpleBStr(strwClassId), nDeviceType, &m_hIconSmall, &m_hIconLarge ))) { if (m_hIconSmall) { SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, reinterpret_cast(m_hIconSmall) ); } if (m_hIconLarge) { SendMessage( m_hWnd, WM_SETICON, ICON_BIG, reinterpret_cast(m_hIconLarge) ); } } } SetForegroundWindow(m_hWnd); return(0); } /***************************************************************************** CVideoCaptureDialog::ResizeAll Resizes and repositions all the controls when the dialog size changes. *****************************************************************************/ VOID CVideoCaptureDialog::ResizeAll(VOID) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::ResizeAll"))); CSimpleRect rcClient(m_hWnd); CMoveWindow mw; CDialogUnits dialogUnits(m_hWnd); //WIA_TRACE((TEXT("rcClient is l(%d) t(%d) r(%d) b(%d)"),rcClient.left, rcClient.top, rcClient.right, rcClient.bottom)); //WIA_TRACE((TEXT("rcClient is w(%d) h(%d)"),rcClient.Width(),rcClient.Height())); //WIA_TRACE((TEXT("dialogUnits.StandardMargin is cx(%d) cy(%d)"),dialogUnits.StandardMargin().cx,dialogUnits.StandardMargin().cy)); //WIA_TRACE((TEXT("dialogUnits.StandardButtonMargin is cx(%d) cy(%d)"),dialogUnits.StandardButtonMargin().cx,dialogUnits.StandardButtonMargin().cy)); // // Resize the big title // mw.Size( GetDlgItem( m_hWnd, IDC_VIDDLG_BIG_TITLE ), rcClient.Width() - dialogUnits.StandardMargin().cx * 2, 0, CMoveWindow::NO_SIZEY ); // // Resize the subtitle // mw.Size( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ), rcClient.Width() - dialogUnits.StandardMargin().cx * 2, 0, CMoveWindow::NO_SIZEY ); CSimpleRect rcOK( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect ); CSimpleRect rcCancel( GetDlgItem( m_hWnd, IDCANCEL ), CSimpleRect::WindowRect ); //WIA_TRACE((TEXT("rcOK is l(%d) t(%d) r(%d) b(%d)"),rcOK.left, rcOK.top, rcOK.right, rcOK.bottom)); //WIA_TRACE((TEXT("rcOK is w(%d) h(%d)"),rcOK.Width(), rcOK.Height())); //WIA_TRACE((TEXT("rcCancel is l(%d) t(%d) r(%d) b(%d)"),rcCancel.left, rcCancel.top, rcCancel.right, rcCancel.bottom)); //WIA_TRACE((TEXT("rcCancel is w(%d) h(%d)"),rcCancel.Width(), rcCancel.Height())); // // Move the OK button // LONG x,y; x = rcClient.Width() - dialogUnits.StandardMargin().cx - dialogUnits.StandardButtonMargin().cx - rcCancel.Width() - rcOK.Width(); y = rcClient.Height() - dialogUnits.StandardMargin().cy - rcOK.Height(); //WIA_TRACE((TEXT("Moving IDOK to x(%x) y(%d)"),x,y)); mw.Move( GetDlgItem( m_hWnd, IDOK ), x, y, 0 ); INT nTopOfOK = y; INT nBottomOfSub = CSimpleRect( GetDlgItem(m_hWnd,IDC_VIDDLG_LITTLE_TITLE), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).bottom; // // Move the cancel button // x = rcClient.Width() - dialogUnits.StandardMargin().cx - rcCancel.Width(); y = rcClient.Height() - dialogUnits.StandardMargin().cy - rcCancel.Height(); //WIA_TRACE((TEXT("Moving IDCANCEL to x(%x) y(%d)"),x,y)); mw.Move( GetDlgItem( m_hWnd, IDCANCEL ), x, y, 0 ); // // Move the resizing handle // x = rcClient.Width() - GetSystemMetrics(SM_CXVSCROLL); y = rcClient.Height() - GetSystemMetrics(SM_CYHSCROLL); //WIA_TRACE((TEXT("Moving IDC_SIZEBOX to x(%x) y(%d)"),x,y)); mw.Move( GetDlgItem( m_hWnd, IDC_SIZEBOX ), x, y ); // // Resize the preview window & move the capture button // CSimpleRect rcSubTitle( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ), CSimpleRect::ClientRect ); CSimpleRect rcCapture( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), CSimpleRect::ClientRect ); CSimpleRect rcSelectAll( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ), CSimpleRect::ClientRect ); //WIA_TRACE((TEXT("rcSubTitle is l(%d) t(%d) r(%d) b(%d)"),rcSubTitle.left, rcSubTitle.top, rcSubTitle.right, rcSubTitle.bottom)); //WIA_TRACE((TEXT("rcSubTitle is w(%d) h(%d)"),rcSubTitle.Width(), rcSubTitle.Height())); //WIA_TRACE((TEXT("rcCapture is l(%d) t(%d) r(%d) b(%d)"),rcCapture.left, rcCapture.top, rcCapture.right, rcCapture.bottom)); //WIA_TRACE((TEXT("rcCapture is w(%d) h(%d)"),rcCapture.Width(), rcCapture.Height())); //WIA_TRACE((TEXT("rcSelectAll is l(%d) t(%d) r(%d) b(%d)"),rcSelectAll.left, rcSelectAll.top, rcSelectAll.right, rcSelectAll.bottom)); //WIA_TRACE((TEXT("rcSelectAll is w(%d) h(%d)"),rcSelectAll.Width(), rcSelectAll.Height())); //WIA_TRACE((TEXT("nTopOfOK is (%d)"),nTopOfOK)); //WIA_TRACE((TEXT("nBottomOfSub is (%d)"),nBottomOfSub)); CSimpleRect rcAvailableArea( dialogUnits.StandardMargin().cx, nBottomOfSub + dialogUnits.StandardMargin().cy, rcClient.right - dialogUnits.StandardMargin().cx, nTopOfOK - (dialogUnits.StandardButtonMargin().cy * 2) ); //WIA_TRACE((TEXT("rcAvailableArea is l(%d) t(%d) r(%d) b(%d)"),rcAvailableArea.left, rcAvailableArea.top, rcAvailableArea.right, rcAvailableArea.bottom)); //WIA_TRACE((TEXT("rcAvailableArea is w(%d) h(%d)"),rcAvailableArea.Width(), rcAvailableArea.Height())); INT full_width = rcAvailableArea.right - rcAvailableArea.left; INT preview_width = (full_width * 53) / 100; //WIA_TRACE((TEXT("full_width is (%d)"),full_width)); //WIA_TRACE((TEXT("preview_width is (%d)"),preview_width)); //WIA_TRACE((TEXT("SizeMoving IDC_VIDDLG_PREVIEW to x(%d) y(%d) w(%d) h(%d)"),rcAvailableArea.left,rcAvailableArea.top,preview_width,rcAvailableArea.Height() - rcCapture.Height() - dialogUnits.StandardButtonMargin().cy)); mw.SizeMove( GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ), rcAvailableArea.left, rcAvailableArea.top, preview_width, rcAvailableArea.Height() - rcCapture.Height() - dialogUnits.StandardButtonMargin().cy ); INT offset = (preview_width - rcCapture.Width()) / 2; //WIA_TRACE((TEXT("offset is (%d)"),offset)); //WIA_TRACE((TEXT("Moving IDC_VIDDLG_CAPTURE to x(%d) y(%d)"),rcAvailableArea.left + offset,rcAvailableArea.bottom - rcCapture.Height())); mw.Move( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), rcAvailableArea.left + offset, rcAvailableArea.bottom - rcCapture.Height(), 0 ); // // Resize the thumbnail list & move the selectall button // INT leftThumbEdge = rcAvailableArea.left + preview_width + dialogUnits.StandardMargin().cx; //WIA_TRACE((TEXT("leftThumbEdge is (%d)"),leftThumbEdge)); //WIA_TRACE((TEXT("SizeMoving IDC_VIDDLG_THUMBNAILLIST to x(%d) y(%d) w(%d) h(%d)"),leftThumbEdge,rcAvailableArea.top,rcAvailableArea.Width() - preview_width - dialogUnits.StandardMargin().cx,rcAvailableArea.Height() - rcSelectAll.Height() - dialogUnits.StandardButtonMargin().cy)); mw.SizeMove( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), leftThumbEdge, rcAvailableArea.top, rcAvailableArea.Width() - preview_width - dialogUnits.StandardMargin().cx, rcAvailableArea.Height() - rcSelectAll.Height() - dialogUnits.StandardButtonMargin().cy ); offset = ((rcAvailableArea.right - leftThumbEdge - rcSelectAll.Width()) / 2); //WIA_TRACE((TEXT("offset(new) is (%d)"),offset)); //WIA_TRACE((TEXT("Moving IDC_VIDDLG_SELECTALL to x(%d) y(%d)"),leftThumbEdge + offset,rcAvailableArea.bottom - rcSelectAll.Height())); mw.Move( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ), leftThumbEdge + offset, rcAvailableArea.bottom - rcSelectAll.Height(), 0 ); // // Explicitly apply the moves, because the toolbar frame doesn't get painted properly // mw.Apply(); // // Update the dialog's background to remove any weird stuff left behind // InvalidateRect( m_hWnd, NULL, FALSE ); UpdateWindow( m_hWnd ); } /***************************************************************************** CVideoCaptureDialog::OnSize Handle WM_SIZE messages *****************************************************************************/ LRESULT CVideoCaptureDialog::OnSize( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnSize"))); ResizeAll(); // // Tell the video preview window to resize in within it's // container window as best it can. // if (m_pWiaVideo) { m_pWiaVideo->ResizeVideo(FALSE); } return(0); } /***************************************************************************** CVideoCaptureDialog::OnShow Handle WM_SHOW message *****************************************************************************/ LRESULT CVideoCaptureDialog::OnShow( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnShow"))); if (m_bFirstTime) { PostMessage( m_hWnd, PWM_POSTINIT, 0, 0 ); m_bFirstTime = false; } return(0); } /***************************************************************************** CVideoCameraDialog::OnGetMinMaxInfo Handle WM_GETMINMAXINFO *****************************************************************************/ LRESULT CVideoCaptureDialog::OnGetMinMaxInfo( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnGetMinMaxInfo"))); WIA_TRACE((TEXT("m_sizeMinimumWindow = %d,%d"),m_sizeMinimumWindow.cx,m_sizeMinimumWindow.cy)); LPMINMAXINFO pMinMaxInfo = (LPMINMAXINFO)lParam; pMinMaxInfo->ptMinTrackSize.x = m_sizeMinimumWindow.cx; pMinMaxInfo->ptMinTrackSize.y = m_sizeMinimumWindow.cy; return(0); } /***************************************************************************** CVideoCameraDialog::OnDestroy Handle WM_DESTROY message and do cleanup *****************************************************************************/ LRESULT CVideoCaptureDialog::OnDestroy( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDestroy"))); // // Unregister for events // m_pCreateCallback = NULL; m_pDeleteCallback = NULL; m_pDisconnectedCallback = NULL; // // Tell the background thread to destroy itself // m_pThreadMessageQueue->Enqueue( new CThreadMessage(TQ_DESTROY),CThreadMessageQueue::PriorityUrgent ); // // Close the thread handle // CloseHandle( m_hBackgroundThread ); if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo) { m_pWiaVideo->DestroyVideo(); } // // Delete resources // if (m_hBigFont) { DeleteObject(m_hBigFont); m_hBigFont = NULL; } if (m_hImageList) { m_hImageList = NULL; } if (m_hAccelTable) { DestroyAcceleratorTable(m_hAccelTable); m_hAccelTable = NULL; } if (m_hIconLarge) { DestroyIcon(m_hIconLarge); m_hIconLarge = NULL; } if (m_hIconSmall) { DestroyIcon(m_hIconSmall); m_hIconSmall = NULL; } return(0); } /***************************************************************************** CVideoCaptureDialog::OnOK Handle when the user presses "Get Pictures" *****************************************************************************/ VOID CVideoCaptureDialog::OnOK( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnOK"))); HRESULT hr = S_OK; // // Start w/nothing to return // m_pDeviceDialogData->lItemCount = 0; m_pDeviceDialogData->ppWiaItems = NULL; // // Get the indicies of the items that are selected // CSimpleDynamicArray aIndices; GetSelectionIndices( aIndices ); // // Are there any items selected? // if (aIndices.Size()) { // // Calculate the size of the buffer needed // INT nArraySizeInBytes = sizeof(IWiaItem*) * aIndices.Size(); // // Alloc a buffer to hold the items // m_pDeviceDialogData->ppWiaItems = (IWiaItem**)CoTaskMemAlloc(nArraySizeInBytes); // // If we allocated a buffer, fill it up with the // items to return... // if (m_pDeviceDialogData->ppWiaItems) { INT i; ZeroMemory( m_pDeviceDialogData->ppWiaItems, nArraySizeInBytes ); for (i=0;iItem()) { m_pDeviceDialogData->ppWiaItems[i] = pItem->Item(); m_pDeviceDialogData->ppWiaItems[i]->AddRef(); } else { // // Somehow the list got corrupted // hr = E_UNEXPECTED; break; } } if (!SUCCEEDED(hr)) { // // Clean up if we had a failure // for (i=0;ippWiaItems[i]) { m_pDeviceDialogData->ppWiaItems[i]->Release(); } } CoTaskMemFree( m_pDeviceDialogData->ppWiaItems ); m_pDeviceDialogData->ppWiaItems = NULL; } else { m_pDeviceDialogData->lItemCount = aIndices.Size(); } } else { // // Unable to alloc buffer // WIA_ERROR((TEXT("Couldn't allocate a buffer"))); hr = E_OUTOFMEMORY; } } else { // // There aren't any items selected, so just return without // ending the dialog... // return; } EndDialog( m_hWnd, hr ); } /***************************************************************************** CVideoCaptureDialog::OnCancel Handle when the user presses cancel. *****************************************************************************/ VOID CVideoCaptureDialog::OnCancel( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnCancel"))); EndDialog( m_hWnd, S_FALSE ); } /***************************************************************************** CVideoCaptureDialog::OnSelectAll Handle when the user presses "Select All" button *****************************************************************************/ VOID CVideoCaptureDialog::OnSelectAll( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnSelectAll"))); LVITEM lvItem; lvItem.mask = LVIF_STATE; lvItem.iItem = 0; lvItem.state = LVIS_SELECTED; lvItem.stateMask = LVIS_SELECTED; SendMessage( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), LVM_SETITEMSTATE, -1, reinterpret_cast(&lvItem) ); } /***************************************************************************** CVideoCaptureDialog::AddItemToListView Adds a new IWiaItem to the list view... *****************************************************************************/ BOOL CVideoCaptureDialog::AddItemToListView( IWiaItem * pItem ) { WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::AddItemToListView"))); if (!pItem) { WIA_ERROR((TEXT("pItem is NULL!"))); return FALSE; } // // Add the new picture to our list // CCameraItem * pNewCameraItem = new CCameraItem( pItem ); if (pNewCameraItem) { WIA_TRACE((TEXT("Attempting to add new item to tree"))); m_CameraItemList.Add( NULL, pNewCameraItem ); } else { WIA_ERROR((TEXT("Couldn't create a new pNewCameraItem"))); } // // Create a thumbnail for the new item // HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList && pNewCameraItem) { HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL ); if (hImageList) { CVideoCaptureDialog::CreateThumbnails( pNewCameraItem, hImageList, FALSE ); } else { WIA_ERROR((TEXT("Couldn't get hImageList to get new thumbnail"))); } // // Update the listview with the new item // LVITEM lvItem; INT iItem = ListView_GetItemCount( hwndList ) + 1; ZeroMemory( &lvItem, sizeof(lvItem) ); lvItem.iItem = iItem; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = pNewCameraItem->ImageListIndex(); lvItem.lParam = (LPARAM)pNewCameraItem; int nIndex = ListView_InsertItem( hwndList, &lvItem ); // // Retrieve actual thumbnail // RequestThumbnails( pNewCameraItem ); // // Select the new item // SetSelectedListItem( nIndex ); // // Make sure the item is visible // ListView_EnsureVisible( hwndList, nIndex, FALSE ); } return TRUE; } /***************************************************************************** CVideoCaptureDialog::OnCapture Handle when the user presses the "Capture" button *****************************************************************************/ VOID CVideoCaptureDialog::OnCapture( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnCapture"))); // // Disable capture button until we're done with this iteration // MyEnableWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), FALSE ); // // Tell the video device to snap a picture // CComPtr pItem; if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo) { WIA_TRACE((TEXT("Telling WiaVideo to take a picture"))); BSTR bstrNewImageFileName = NULL; // // Take the picture // HRESULT hr = m_pWiaVideo->TakePicture(&bstrNewImageFileName); WIA_CHECK_HR(hr,"m_pWiaVideo->TakePicture"); if (hr == S_OK) { // // Succeeded in taking the picture, setting the LAST_PICTURE_TAKEN property // on the video driver to create a new item. // BOOL bSuccess = FALSE; PROPVARIANT pv; PropVariantInit(&pv); pv.vt = VT_BSTR; pv.bstrVal = bstrNewImageFileName; bSuccess = PropStorageHelpers::SetProperty(m_pDeviceDialogData->pIWiaItemRoot, WIA_DPV_LAST_PICTURE_TAKEN, pv); // // Note that this will free the bstrNewImageFileName returned to // us by WiaVideo // PropVariantClear(&pv); } } // // Re-Enable capture button now that we're done // MyEnableWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), TRUE ); // // Make sure the focus is still on our control // SetFocus( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ) ); } /***************************************************************************** CVideoCaptureDialog::OnDblClickImageList Translate a dbl-click on a thumbnail in the listview into a click on the "Get Pictures" button. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnDblClkImageList( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDblClkImageList"))); SendMessage( m_hWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 ); return 0; } /***************************************************************************** CVideoCaptureDialog::OnImageListItemChanged Sent whenever an item in the thumbnail list changes. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnImageListItemChanged( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnImageListItemChanged"))); HandleSelectionChange(); return 0; } /***************************************************************************** CVideoCaptureDialog::OnImageListKeyDown Forward the keyboard messages within the listview appropriately. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnImageListKeyDown( WPARAM, LPARAM lParam ) { LPNMLVKEYDOWN pnkd = reinterpret_cast(lParam); if (pnkd) { if (VK_LEFT == pnkd->wVKey && (GetKeyState(VK_MENU) & 0x8000)) { SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 ); } } return 0; } /***************************************************************************** CVideoCaptureDialog::OnNotify Handle WM_NOTIFY messages *****************************************************************************/ LRESULT CVideoCaptureDialog::OnNotify( WPARAM wParam, LPARAM lParam ) { SC_BEGIN_NOTIFY_MESSAGE_HANDLERS() { SC_HANDLE_NOTIFY_MESSAGE_CONTROL( NM_DBLCLK, IDC_VIDDLG_THUMBNAILLIST, OnDblClkImageList ); SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_ITEMCHANGED, IDC_VIDDLG_THUMBNAILLIST, OnImageListItemChanged ); SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_KEYDOWN, IDC_VIDDLG_THUMBNAILLIST, OnImageListKeyDown ); } SC_END_NOTIFY_MESSAGE_HANDLERS(); } /***************************************************************************** CVideoCaptureDialog::OnCommand Handle WM_COMMAND messages *****************************************************************************/ LRESULT CVideoCaptureDialog::OnCommand( WPARAM wParam, LPARAM lParam ) { SC_BEGIN_COMMAND_HANDLERS() { SC_HANDLE_COMMAND(IDOK, OnOK); SC_HANDLE_COMMAND(IDCANCEL, OnCancel); SC_HANDLE_COMMAND(IDC_VIDDLG_CAPTURE, OnCapture); SC_HANDLE_COMMAND(IDC_VIDDLG_SELECTALL, OnSelectAll); } SC_END_COMMAND_HANDLERS(); } /***************************************************************************** CVideoCaptureDialog::OnGetThumbnail Called by background thread to get the thumbnail for a given item. *****************************************************************************/ BOOL WINAPI CVideoCaptureDialog::OnGetThumbnail( CThreadMessage *pMsg ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnGetThumbnail")); HBITMAP hBmpThumbnail = NULL; CThumbnailThreadMessage *pThumbMsg = (CThumbnailThreadMessage *)(pMsg); if (pThumbMsg) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable); if (SUCCEEDED(hr) && pGlobalInterfaceTable) { CComPtr pIWiaItem; hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pThumbMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem); if (SUCCEEDED(hr) && pIWiaItem) { CComPtr pIWiaPropertyStorage; hr = pIWiaItem->QueryInterface( IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage ); if (SUCCEEDED(hr) && pIWiaPropertyStorage) { PROPVARIANT PropVar[3]; PROPSPEC PropSpec[3]; PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_IPC_THUMB_WIDTH; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_IPC_THUMB_HEIGHT; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_IPC_THUMBNAIL; hr = pIWiaPropertyStorage->ReadMultiple(ARRAYSIZE(PropSpec),PropSpec,PropVar ); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("Attempting to get the thumbnail for GIT entry: %08X, %08X, %08X, %08X"),pThumbMsg->GlobalInterfaceTableCookie(),PropVar[0].vt,PropVar[1].vt,PropVar[2].vt)); if ((PropVar[0].vt == VT_I4 || PropVar[0].vt == VT_UI4) && (PropVar[1].vt == VT_I4 || PropVar[1].vt == VT_UI4) && (PropVar[2].vt == (VT_UI1|VT_VECTOR))) { // // Calculate the actual amount of data to copy from the thumbnail bitmap. // We have to round up to the nearest DWORD boundary, so we align on Width * BYTES_PER_PIXEL // UINT nBitmapDataSize = WiaUiUtil::Align( PropVar[0].ulVal * 3, sizeof(DWORD) ) * PropVar[1].ulVal; if (nBitmapDataSize <= PropVar[2].caub.cElems) { BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = PropVar[0].ulVal; bmi.bmiHeader.biHeight = PropVar[1].ulVal; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; HDC hDC = GetDC(NULL); if (hDC) { PBYTE *pBits; HBITMAP hDibSection = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (PVOID*)&pBits, NULL, 0 ); if (hDibSection) { CopyMemory( pBits, PropVar[2].caub.pElems, nBitmapDataSize ); hr = ScaleImage( hDC, hDibSection, hBmpThumbnail, pThumbMsg->ThumbSize()); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("Sending this image to the notification window: %08X"),pThumbMsg->NotifyWindow())); } else { hBmpThumbnail = NULL; } DeleteObject(hDibSection); } ReleaseDC(NULL,hDC); } } } PropVariantClear(&PropVar[0]); PropVariantClear(&PropVar[1]); PropVariantClear(&PropVar[2]); } } } } } LRESULT lRes = SendMessage( pThumbMsg->NotifyWindow(), PWM_THUMBNAILSTATUS, (WPARAM)pThumbMsg->GlobalInterfaceTableCookie(), (LPARAM)hBmpThumbnail ); if (HANDLED_THREAD_MESSAGE != lRes && hBmpThumbnail) { DeleteObject( hBmpThumbnail ); } return TRUE; } /***************************************************************************** CVideoCaptureDialog::OnThreadDestroy *****************************************************************************/ BOOL WINAPI CVideoCaptureDialog::OnThreadDestroy( CThreadMessage * ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnThreadDestroy")); return FALSE; } /***************************************************************************** CVideoCaptureDialog::SetSelectedListItem *****************************************************************************/ BOOL CVideoCaptureDialog::SetSelectedListItem( int nIndex ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); // // Check for bad args // if (!hwndList) { return FALSE; } int iCount = ListView_GetItemCount(hwndList); for (int i=0;i *****************************************************************************/ VOID CVideoCaptureDialog::MarkItemDeletePending( INT nIndex, BOOL bSet ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList) { ListView_SetItemState( hwndList, nIndex, bSet ? LVIS_CUT : 0, LVIS_CUT ); } } /***************************************************************************** CVideoCaptureDialog::PopulateList Populates the listview with the current items. *****************************************************************************/ BOOL CVideoCaptureDialog::PopulateList( CCameraItem *pOldParent ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); int nSelItem = 0; if (hwndList) { ListView_DeleteAllItems( hwndList ); int nItem = 0; CCameraItem *pCurr; // // If this is a child directory... // if (m_pCurrentParentItem) { // // Start adding children // pCurr = m_pCurrentParentItem->Children(); // // Insert a dummy item that the user can use to // switch to the parent directory // LVITEM lvItem; ZeroMemory( &lvItem, sizeof(lvItem) ); lvItem.iItem = nItem++; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = m_nParentFolderImageListIndex; lvItem.lParam = 0; ListView_InsertItem( hwndList, &lvItem ); } else { // // if it's a parent directory... // pCurr = m_CameraItemList.Root(); } while (pCurr) { if (pOldParent && *pCurr == *pOldParent) { nSelItem = nItem; } if (pCurr->DeleteState() != CCameraItem::Delete_Deleted) { LVITEM lvItem; ZeroMemory( &lvItem, sizeof(lvItem) ); lvItem.iItem = nItem++; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = pCurr->ImageListIndex(); lvItem.lParam = (LPARAM)pCurr; int nIndex = ListView_InsertItem( hwndList, &lvItem ); if (nIndex >= 0 && pCurr->DeleteState() == CCameraItem::Delete_Pending) { MarkItemDeletePending(nIndex,true); } } pCurr = pCurr->Next(); } } // // If we've not calculated the width of the list in preview mode, attempt to do it // if (!m_nListViewWidth) { RECT rcItem; if (ListView_GetItemRect( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), 0, &rcItem, LVIR_ICON )) { m_nListViewWidth = (rcItem.right-rcItem.left) + rcItem.left * 2 + GetSystemMetrics(SM_CXHSCROLL) + c_nAdditionalMarginX; } } SetSelectedListItem(nSelItem); return TRUE; } /***************************************************************************** CVideoCaptureDialog::OnThumbnailStatus *****************************************************************************/ LRESULT CVideoCaptureDialog::OnThumbnailStatus( WPARAM wParam, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnThumbnailStatus")); WIA_TRACE((TEXT("Looking for the item with the ID %08X"),wParam)); CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam ); if (pCameraItem) { WIA_TRACE((TEXT("Found a CameraItem * (%08X)"),pCameraItem)); HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList) { WIA_TRACE((TEXT("Got the list control"))); HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL ); if (hImageList) { WIA_TRACE((TEXT("Got the image list"))); if ((HBITMAP)lParam) { if (ImageList_Replace( hImageList, pCameraItem->ImageListIndex(), (HBITMAP)lParam, NULL )) { WIA_TRACE((TEXT("Replaced the image in the list"))); int nItem = FindItemInList(pCameraItem); if (nItem >= 0) { LV_ITEM lvItem; ::ZeroMemory(&lvItem,sizeof(LV_ITEM)); lvItem.iItem = nItem; lvItem.mask = LVIF_IMAGE; lvItem.iImage = pCameraItem->ImageListIndex(); ListView_SetItem( hwndList, &lvItem ); ListView_Update( hwndList, nItem ); InvalidateRect( hwndList, NULL, FALSE ); } } } } } } // // Clean up the bitmap, regardless of any other failures, to avoid memory leaks // HBITMAP hBmpThumb = (HBITMAP)lParam; if (hBmpThumb) { DeleteObject(hBmpThumb); } return HANDLED_THREAD_MESSAGE; } /***************************************************************************** CVideoCaptureDialog::CreateThumbnails *****************************************************************************/ void CVideoCaptureDialog::CreateThumbnails( CCameraItem *pRoot, HIMAGELIST hImageList, bool bForce ) { CCameraItem *pCurr = pRoot; while (pCurr) { if (pCurr->ImageListIndex()<0 || bForce) { // // Get the item name // CSimpleStringWide strItemName; PropStorageHelpers::GetProperty( pCurr->Item(), WIA_IPA_ITEM_NAME, strItemName ); // // Create the title for the icon // CSimpleString strIconTitle; if (pCurr->IsFolder()) { strIconTitle = CSimpleStringConvert::NaturalString(strItemName); } else if (strItemName.Length()) { strIconTitle.Format( IDS_VIDDLG_DOWNLOADINGTHUMBNAIL, g_hInstance, CSimpleStringConvert::NaturalString(strItemName).String() ); } // // Create the thumbnail // HBITMAP hBmp = WiaUiUtil::CreateIconThumbnail( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, pCurr->IsFolder()?IDI_VIDDLG_FOLDER:IDI_VIDDLG_UNAVAILABLE, strIconTitle ); if (hBmp) { if (pCurr->ImageListIndex()<0) { pCurr->ImageListIndex(ImageList_Add( hImageList, hBmp, NULL )); } else { pCurr->ImageListIndex(ImageList_Replace( hImageList, pCurr->ImageListIndex(), hBmp, NULL )); } DeleteObject(hBmp); } } if (pCurr->Children()) { CreateThumbnails( pCurr->Children(), hImageList, bForce ); } pCurr = pCurr->Next(); } } /***************************************************************************** CVideoCaptureDialog::RequestThumbnails *****************************************************************************/ VOID CVideoCaptureDialog::RequestThumbnails( CCameraItem *pRoot ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::RequestThumbnails")); CCameraItem *pCurr = pRoot; while (pCurr) { if (!pCurr->IsFolder()) { m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pCurr->GlobalInterfaceTableCookie(), m_sizeThumbnails ) ); } if (pCurr->Children()) { RequestThumbnails( pCurr->Children() ); } pCurr = pCurr->Next(); } } /***************************************************************************** CVideoCaptureDialog::CreateThumbnails *****************************************************************************/ VOID CVideoCaptureDialog::CreateThumbnails( BOOL bForce ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList) { HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL ); if (hImageList) { // // Create the parent folder image and add it to the image list // HBITMAP hParentBitmap = WiaUiUtil::CreateIconThumbnail( hwndList, m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, IDI_VIDDLG_PARENTFOLDER, TEXT("(..)") ); if (hParentBitmap) { m_nParentFolderImageListIndex = ImageList_Add( hImageList, hParentBitmap, NULL ); DeleteObject(hParentBitmap); } // // Create all of the other images // CreateThumbnails( m_CameraItemList.Root(), hImageList, bForce != 0 ); } } } /***************************************************************************** CVideoCaptureDialog::FindMaximumThumbnailSize Looks through entire item list to get larget thumbnail. *****************************************************************************/ BOOL CVideoCaptureDialog::FindMaximumThumbnailSize( VOID ) { WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::FindMaximumThumbnailSize")); BOOL bResult = false; if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot) { LONG nWidth, nHeight; if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nWidth ) && PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nHeight )) { m_sizeThumbnails.cx = max(c_nMinThumbnailWidth,min(nWidth,c_nMaxThumbnailWidth)); m_sizeThumbnails.cy = max(c_nMinThumbnailHeight,min(nHeight,c_nMaxThumbnailHeight)); } else { WIA_TRACE((TEXT("FindMaximumThumbnailSize: Unable to retrieve thumbnail size for device"))); } } return(bResult && m_sizeThumbnails.cx && m_sizeThumbnails.cy); } /***************************************************************************** CVideoCaptureDialog::EnumerateItems Enumerate all the items at this level of the camera. *****************************************************************************/ HRESULT CVideoCaptureDialog::EnumerateItems( CCameraItem *pCurrentParent, IEnumWiaItem *pIEnumWiaItem ) { WIA_PUSHFUNCTION(TEXT("CCameraItemList::EnumerateItems")); HRESULT hr = E_FAIL; if (pIEnumWiaItem != NULL) { hr = pIEnumWiaItem->Reset(); while (hr == S_OK) { CComPtr pIWiaItem; hr = pIEnumWiaItem->Next(1, &pIWiaItem, NULL); if (hr == S_OK) { CCameraItem *pNewCameraItem = new CCameraItem( pIWiaItem ); if (pNewCameraItem && pNewCameraItem->Item()) { m_CameraItemList.Add( pCurrentParent, pNewCameraItem ); LONG ItemType; HRESULT hr2; hr2 = pNewCameraItem->Item()->GetItemType(&ItemType); if (SUCCEEDED(hr2)) { if (ItemType & WiaItemTypeImage) { WIA_TRACE((TEXT("Found an image"))); } else { WIA_TRACE((TEXT("Found something that is NOT an image"))); } CComPtr pIEnumChildItem; hr2 = pIWiaItem->EnumChildItems(&pIEnumChildItem); if (hr2 == S_OK) { EnumerateItems( pNewCameraItem, pIEnumChildItem ); } } } } } } return hr; } /***************************************************************************** CVideoCaptureDialog::EnumerateAllCameraItems Enumerate all the items in camera, including folders. *****************************************************************************/ HRESULT CVideoCaptureDialog::EnumerateAllCameraItems(void) { CComPtr pIEnumItem; HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->EnumChildItems(&pIEnumItem); if (hr == S_OK) { hr = EnumerateItems( NULL, pIEnumItem ); } return(hr); } /***************************************************************************** CVideoCaptureDialog::GetSelectionIndices Returns an array with the list indicies of the items that are selected in IDC_VIDDLG_THUMBNAILLIST *****************************************************************************/ INT CVideoCaptureDialog::GetSelectionIndices( CSimpleDynamicArray &aIndices ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (!hwndList) { return 0; } INT iCount = ListView_GetItemCount(hwndList); for (INT i=0; i pWiaProgressDialog; HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaProgressDialog, (void**)&pWiaProgressDialog ); if (SUCCEEDED(hr)) { // // Initialize the progress dialog // pWiaProgressDialog->Create( m_hWnd, WIA_PROGRESSDLG_ANIM_VIDEO_COMMUNICATE|WIA_PROGRESSDLG_NO_PROGRESS|WIA_PROGRESSDLG_NO_CANCEL|WIA_PROGRESSDLG_NO_TITLE ); pWiaProgressDialog->SetTitle( CSimpleStringConvert::WideString(CSimpleString(IDS_VIDDLG_PROGDLG_TITLE,g_hInstance))); pWiaProgressDialog->SetMessage( CSimpleStringConvert::WideString(CSimpleString(IDS_VIDDLG_PROGDLG_MESSAGE,g_hInstance))); // // Show the progress dialog // pWiaProgressDialog->Show(); if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo) { CSimpleString strImagesDirectory; if (hr == S_OK) { BOOL bSuccess = FALSE; // // Get the IMAGES_DIRECTORY property from the Wia Video Driver. // bSuccess = PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot, WIA_DPV_IMAGES_DIRECTORY, strImagesDirectory); if (!bSuccess) { hr = E_FAIL; } } 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 IDC_VIDSEL_PREVIEW dialog item // and automatically begin playback after creating the preview. // if (hr == S_OK) { hr = m_pWiaVideo->CreateVideoByWiaDevID(CSimpleBStr(m_strwDeviceId), GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ), FALSE, TRUE); } } } if (hr != S_OK) { // // Let the user know that the graph is most likely already // in use... // MessageBox( m_hWnd, CSimpleString(IDS_VIDDLG_BUSY_TEXT, g_hInstance), CSimpleString(IDS_VIDDLG_BUSY_TITLE, g_hInstance), MB_OK | MB_ICONWARNING | MB_SETFOREGROUND ); // // Disable the capture button since we have no graph // MyEnableWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_CAPTURE), FALSE ); } } // // Go get all the items.. // EnumerateAllCameraItems(); FindMaximumThumbnailSize(); // // Initialize Thumbnail Listview control // HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList) { ListView_SetExtendedListViewStyleEx( hwndList, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS ); m_hImageList = ImageList_Create( m_sizeThumbnails.cx, m_sizeThumbnails.cy, ILC_COLOR24|ILC_MIRROR, 1, 1 ); if (m_hImageList) { ListView_SetImageList( hwndList, m_hImageList, LVSIL_NORMAL ); ListView_SetIconSpacing( hwndList, m_sizeThumbnails.cx + c_nAdditionalMarginX, m_sizeThumbnails.cy + c_nAdditionalMarginY ); } } CreateThumbnails(); // // This causes the list to be populated // ChangeFolder(NULL); HandleSelectionChange(); RequestThumbnails( m_CameraItemList.Root() ); // // Close the progress dialog // pWiaProgressDialog->Destroy(); } return(0); } /***************************************************************************** CVideoCaptureDialog::FindItemInList *****************************************************************************/ INT CVideoCaptureDialog::FindItemInList( CCameraItem *pItem ) { if (pItem) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (hwndList) { for (int i=0;i *****************************************************************************/ CCameraItem * CVideoCaptureDialog::GetListItemNode( int nIndex ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ); if (!hwndList) { return NULL; } LV_ITEM lvItem; ::ZeroMemory(&lvItem,sizeof(LV_ITEM)); lvItem.mask = LVIF_PARAM; lvItem.iItem = nIndex; if (!ListView_GetItem( hwndList, &lvItem )) { return NULL ; } return((CCameraItem *)lvItem.lParam); } /***************************************************************************** CVideoCaptureDialog::ChangeFolder Change the current folder being viewed *****************************************************************************/ BOOL CVideoCaptureDialog::ChangeFolder( CCameraItem *pNode ) { CCameraItem *pOldParent = m_pCurrentParentItem; m_pCurrentParentItem = pNode; return PopulateList(pOldParent); } /***************************************************************************** CVideoCaptureDialog::OnChangeToParent *****************************************************************************/ LRESULT CVideoCaptureDialog::OnChangeToParent( WPARAM, LPARAM ) { if (m_pCurrentParentItem) { ChangeFolder(m_pCurrentParentItem->Parent()); } return(0); } /***************************************************************************** CVideoCaptureDialog::HandleSelectionChange *****************************************************************************/ VOID CVideoCaptureDialog::HandleSelectionChange( VOID ) { CWaitCursor wc; INT nSelCount = ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ) ); INT nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ) ); // // OK should be disabled for 0 items // MyEnableWindow( GetDlgItem(m_hWnd,IDOK), nSelCount != 0 ); // // Select all should be disabled for 0 items // MyEnableWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_SELECTALL), nItemCount != 0 ); } /***************************************************************************** CVideoCaptureDialog::OnTimer Handle WM_TIMER messages *****************************************************************************/ LRESULT CVideoCaptureDialog::OnTimer( WPARAM wParam, LPARAM ) { /* switch (wParam) { case IDT_UPDATEPREVIEW: { KillTimer( m_hWnd, IDT_UPDATEPREVIEW ); UpdatePreview(); } break; } */ return(0); } /***************************************************************************** CVideoCaptureDialog::OnNewItemEvent This gets called when get an event from the driver that a new item has been created. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnNewItemEvent( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnNewItemEvent"))); // // Make sure we have a valid item name // BSTR bstrFullItemName = reinterpret_cast(lParam); if (!bstrFullItemName) { WIA_TRACE((TEXT("bstrFullItemName was NULL"))); return 0; } // // Check to see if the item is already in our list // CCameraItem *pListItem = m_CameraItemList.Find(bstrFullItemName); if (!pListItem) { if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot) { WIA_TRACE((TEXT("Finding new item in device"))); // // Get an IWiaItem ptr to new item // CComPtr pItem; HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->FindItemByName(0,bstrFullItemName,&pItem); WIA_CHECK_HR(hr,"pWiaItemRoot->FindItemByName()"); if (SUCCEEDED(hr) && pItem) { // // Add the item to the list // AddItemToListView( pItem ); // // Make sure we update controls' states // HandleSelectionChange(); } else { WIA_ERROR((TEXT("FindItemByName returned NULL pItem"))); } } else { WIA_ERROR((TEXT("m_pDeviceDialogData or m_pDeviceDialogData->pIWiaItemRoot were NULL"))); } } else { WIA_TRACE((TEXT("We found the item is already in our list, doing nothing"))); } // // Free the item name // SysFreeString(bstrFullItemName); return HANDLED_THREAD_MESSAGE; } /***************************************************************************** CVideoCaptureDialog::OnDeleteItemEvent This gets called when we get an event from the driver that an item has been deleted. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnDeleteItemEvent( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDeleteItemEvent"))); CSimpleBStr bstrFullItem = reinterpret_cast(lParam); SysFreeString( reinterpret_cast(lParam) ); WIA_TRACE((TEXT("The deleted item is %s"),CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrFullItem)).String())); CCameraItem *pDeletedItem = m_CameraItemList.Find(bstrFullItem); if (pDeletedItem) { // // If we're deleting the current parent item, // select a new one. // if (pDeletedItem == m_pCurrentParentItem) { ChangeFolder(m_pCurrentParentItem->Parent()); } int nIndex = FindItemInList(pDeletedItem); if (nIndex >= 0) { // // Remove the item from the listview // ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ),nIndex); // // Make sure we leave something selected // if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ))) { int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST )); if (nItemCount) { if (nIndex >= nItemCount) { nIndex = nItemCount-1; } SetSelectedListItem(nIndex); } } // // Make sure we update controls' states // HandleSelectionChange(); } else { WIA_ERROR((TEXT("FindItemInList coulnd't find the item"))); } // // Mark the item as deleted. // pDeletedItem->DeleteState( CCameraItem::Delete_Deleted ); } else { WIA_ERROR((TEXT("The item could not be found in m_CameraItemList"))); } return HANDLED_THREAD_MESSAGE; } /***************************************************************************** CVideoCaptureDialog::OnDeviceDisconnect This gets called when we get an event from the driver that device has been disconnected. *****************************************************************************/ LRESULT CVideoCaptureDialog::OnDeviceDisconnect( WPARAM, LPARAM ) { WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDeviceDisconnect"))); // // Close the dialog with the approriate error // EndDialog( m_hWnd, WIA_ERROR_OFFLINE ); return 0; } /***************************************************************************** CVideoCaptureDialog::GetGraphWindowHandle Find the window handle of the video window *****************************************************************************/ HWND CVideoCaptureDialog::GetGraphWindowHandle(void) { HWND hWndGraphParent = GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ); if (hWndGraphParent) { return FindWindowEx( hWndGraphParent, NULL, TEXT("VideoRenderer"), NULL ); } return NULL; } /***************************************************************************** CCameraAcquireDialog::OnContextMenu Message handler for WM_HELP message *****************************************************************************/ LRESULT CVideoCaptureDialog::OnHelp( WPARAM wParam, LPARAM lParam ) { HELPINFO *pHelpInfo = reinterpret_cast(lParam); if (pHelpInfo && HELPINFO_WINDOW==pHelpInfo->iContextType && GetGraphWindowHandle()==pHelpInfo->hItemHandle) { pHelpInfo->hItemHandle = GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ); } return WiaHelp::HandleWmHelp( wParam, lParam, g_HelpIDs ); } /***************************************************************************** CCameraAcquireDialog::OnContextMenu Message handler for right-mouse-button click *****************************************************************************/ LRESULT CVideoCaptureDialog::OnContextMenu( WPARAM wParam, LPARAM lParam ) { if (GetGraphWindowHandle() == reinterpret_cast(wParam)) { wParam = reinterpret_cast(GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW )); } return WiaHelp::HandleWmContextMenu( wParam, lParam, g_HelpIDs ); } /***************************************************************************** CVideoCaptureDialog::DialogProc Dialog proc for video capture dialog *****************************************************************************/ INT_PTR PASCAL CVideoCaptureDialog::DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CVideoCaptureDialog) { SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog ); SC_HANDLE_DIALOG_MESSAGE( WM_SIZE, OnSize ); SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand ); SC_HANDLE_DIALOG_MESSAGE( WM_NOTIFY, OnNotify ); SC_HANDLE_DIALOG_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo ); SC_HANDLE_DIALOG_MESSAGE( WM_DESTROY, OnDestroy ); SC_HANDLE_DIALOG_MESSAGE( WM_SHOWWINDOW, OnShow ); SC_HANDLE_DIALOG_MESSAGE( WM_TIMER, OnTimer ); SC_HANDLE_DIALOG_MESSAGE( WM_HELP, OnHelp ); SC_HANDLE_DIALOG_MESSAGE( WM_CONTEXTMENU, OnContextMenu ); SC_HANDLE_DIALOG_MESSAGE( PWM_POSTINIT, OnPostInit ); SC_HANDLE_DIALOG_MESSAGE( PWM_CHANGETOPARENT, OnChangeToParent ); SC_HANDLE_DIALOG_MESSAGE( PWM_THUMBNAILSTATUS, OnThumbnailStatus ); SC_HANDLE_DIALOG_MESSAGE( VD_NEW_ITEM, OnNewItemEvent ); SC_HANDLE_DIALOG_MESSAGE( VD_DELETE_ITEM, OnDeleteItemEvent ); SC_HANDLE_DIALOG_MESSAGE( VD_DEVICE_DISCONNECTED, OnDeviceDisconnect ); } SC_END_DIALOG_MESSAGE_HANDLERS(); } /***************************************************************************** CVideoCallback::CVideoCallback Constructor for class *****************************************************************************/ CVideoCallback::CVideoCallback() : m_cRef(1), m_hWnd(NULL) { WIA_PUSHFUNCTION((TEXT("CVideoCallback::CVideoCallback()"))); } /***************************************************************************** CVideoCallback::Initialize Let us set which hwnd to notify when events come *****************************************************************************/ STDMETHODIMP CVideoCallback::Initialize( HWND hWnd ) { WIA_PUSHFUNCTION((TEXT("CVideoCallback::Initialize()"))); m_hWnd = hWnd; return S_OK; } /***************************************************************************** CVideoCallback::AddRef Standard COM *****************************************************************************/ STDMETHODIMP_(ULONG) CVideoCallback::AddRef( VOID ) { WIA_PUSHFUNCTION((TEXT("CVideoCallback::AddRef"))); return(InterlockedIncrement(&m_cRef)); } /***************************************************************************** CVideoCallback::Release Standard COM *****************************************************************************/ STDMETHODIMP_(ULONG) CVideoCallback::Release( VOID ) { WIA_PUSHFUNCTION(TEXT("CVideoCallback::Release")); LONG nRefCount = InterlockedDecrement(&m_cRef); if (!nRefCount) { delete this; } return(nRefCount); } /***************************************************************************** CVideoCallback::QueryInterface Standard COM *****************************************************************************/ STDMETHODIMP CVideoCallback::QueryInterface( REFIID riid, LPVOID *ppvObject ) { WIA_PUSHFUNCTION((TEXT("CVideoCallback::QueryInterface"))); HRESULT hr = S_OK; if (ppvObject) { if (IsEqualIID( riid, IID_IUnknown )) { WIA_TRACE((TEXT("Supported RIID asked for was IID_IUnknown"))); *ppvObject = static_cast(this); reinterpret_cast(*ppvObject)->AddRef(); } else if (IsEqualIID( riid, IID_IWiaEventCallback )) { WIA_TRACE((TEXT("Supported RIID asked for was IID_IWiaEventCallback"))); *ppvObject = static_cast(this); reinterpret_cast(*ppvObject)->AddRef(); } else { WIA_PRINTGUID((riid,TEXT("Unsupported interface!"))); *ppvObject = NULL; hr = E_NOINTERFACE; } } else { hr = E_INVALIDARG; } WIA_RETURN_HR(hr); } /***************************************************************************** CVideoCallback::ImageEventCallback WIA callback interface for events. *****************************************************************************/ STDMETHODIMP CVideoCallback::ImageEventCallback( const GUID *pEventGUID, BSTR bstrEventDescription, BSTR bstrDeviceID, BSTR bstrDeviceDescription, DWORD dwDeviceType, BSTR bstrFullItemName, ULONG *pulEventType, ULONG ulReserved) { WIA_PUSHFUNCTION((TEXT("CVideoCallback::ImageEventCallback"))); HRESULT hr = S_OK; if (pEventGUID) { if (IsEqualGUID( *pEventGUID, WIA_EVENT_ITEM_CREATED )) { WIA_TRACE((TEXT("Got WIA_EVENT_ITEM_CREATED"))); BSTR bstrToSend = SysAllocString( bstrFullItemName ); LRESULT lRes = SendMessage( m_hWnd, VD_NEW_ITEM, 0, reinterpret_cast(bstrToSend) ); if (HANDLED_THREAD_MESSAGE != lRes && bstrToSend) { SysFreeString( bstrToSend ); } } else if (IsEqualGUID( *pEventGUID, WIA_EVENT_ITEM_DELETED )) { WIA_TRACE((TEXT("Got WIA_EVENT_ITEM_DELETED"))); BSTR bstrToSend = SysAllocString( bstrFullItemName ); LRESULT lRes = SendMessage( m_hWnd, VD_DELETE_ITEM, 0, reinterpret_cast(bstrToSend) ); if (HANDLED_THREAD_MESSAGE != lRes && bstrToSend) { SysFreeString( bstrToSend ); } } else if (IsEqualGUID( *pEventGUID, WIA_EVENT_DEVICE_DISCONNECTED )) { PostMessage( m_hWnd, VD_DEVICE_DISCONNECTED, 0, 0 ); } else { WIA_ERROR((TEXT("Got an event other that what we registered for!"))); } } WIA_RETURN_HR(hr); }