Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2605 lines
77 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) CORPYRIGHT MICROSOFT CORPORATION, 1999 - 2000
  4. *
  5. * TITLE: videodlg.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: RickTu
  10. *
  11. * DATE: 10/14/99
  12. *
  13. * DESCRIPTION: Implementation of DialogProc for video capture common dialog
  14. *
  15. *****************************************************************************/
  16. #include <precomp.h>
  17. #pragma hdrstop
  18. #include "wiacsh.h"
  19. #include "modlock.h"
  20. #include "wiadevdp.h"
  21. //
  22. // Help IDs
  23. //
  24. static const DWORD g_HelpIDs[] =
  25. {
  26. IDC_VIDDLG_BIG_TITLE, -1,
  27. IDC_VIDDLG_LITTLE_TITLE, -1,
  28. IDC_VIDDLG_PREVIEW, IDH_WIA_VIDEO,
  29. IDC_VIDDLG_THUMBNAILLIST, IDH_WIA_CAPTURED_IMAGES,
  30. IDC_VIDDLG_CAPTURE, IDH_WIA_CAPTURE,
  31. IDOK, IDH_WIA_VIDEO_GET_PICTURE,
  32. IDCANCEL, IDH_CANCEL,
  33. 0, 0
  34. };
  35. #define IDC_SIZEBOX 1113
  36. //
  37. // If the callee doesn't return this value, we delete the message data ourselves.
  38. //
  39. #ifndef HANDLED_THREAD_MESSAGE
  40. #define HANDLED_THREAD_MESSAGE 2032
  41. #endif
  42. // Thumbnail whitespace: the space in between images and their selection rectangles
  43. // CThese values were discovered by trail and error. For instance, if you reduce
  44. // c_nAdditionalMarginY to 20, you get really bizarre spacing problems in the list view
  45. // in vertical mode. These values could become invalid in future versions of the listview.
  46. static const int c_nAdditionalMarginX = 10;
  47. static const int c_nAdditionalMarginY = 6;
  48. static int c_nMinThumbnailWidth = 90;
  49. static int c_nMinThumbnailHeight = 90;
  50. static int c_nMaxThumbnailWidth = 120;
  51. static int c_nMaxThumbnailHeight = 120;
  52. //
  53. // Map of background thread messages
  54. //
  55. static CThreadMessageMap g_MsgMap[] =
  56. {
  57. { TQ_DESTROY, CVideoCaptureDialog::OnThreadDestroy},
  58. { TQ_GETTHUMBNAIL, CVideoCaptureDialog::OnGetThumbnail},
  59. { 0, NULL}
  60. };
  61. class CGlobalInterfaceTableThreadMessage : public CNotifyThreadMessage
  62. {
  63. private:
  64. DWORD m_dwGlobalInterfaceTableCookie;
  65. private:
  66. // No implementation
  67. CGlobalInterfaceTableThreadMessage(void);
  68. CGlobalInterfaceTableThreadMessage &operator=( const CGlobalInterfaceTableThreadMessage & );
  69. CGlobalInterfaceTableThreadMessage( const CGlobalInterfaceTableThreadMessage & );
  70. public:
  71. CGlobalInterfaceTableThreadMessage( int nMessage, HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie )
  72. : CNotifyThreadMessage( nMessage, hWndNotify ),
  73. m_dwGlobalInterfaceTableCookie(dwGlobalInterfaceTableCookie)
  74. {
  75. }
  76. DWORD GlobalInterfaceTableCookie(void) const
  77. {
  78. return(m_dwGlobalInterfaceTableCookie);
  79. }
  80. };
  81. class CThumbnailThreadMessage : public CGlobalInterfaceTableThreadMessage
  82. {
  83. private:
  84. SIZE m_sizeThumb;
  85. private:
  86. // No implementation
  87. CThumbnailThreadMessage(void);
  88. CThumbnailThreadMessage &operator=( const CThumbnailThreadMessage & );
  89. CThumbnailThreadMessage( const CThumbnailThreadMessage & );
  90. public:
  91. CThumbnailThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, const SIZE &sizeThumb )
  92. : CGlobalInterfaceTableThreadMessage( TQ_GETTHUMBNAIL, hWndNotify, dwGlobalInterfaceTableCookie ),
  93. m_sizeThumb(sizeThumb)
  94. {
  95. }
  96. const SIZE &ThumbSize(void) const
  97. {
  98. return(m_sizeThumb);
  99. }
  100. };
  101. //
  102. // Avoids unnecessary state changes
  103. //
  104. static inline VOID MyEnableWindow( HWND hWnd, BOOL bEnable )
  105. {
  106. if (bEnable && !IsWindowEnabled(hWnd))
  107. {
  108. EnableWindow(hWnd,TRUE);
  109. }
  110. else if (!bEnable && IsWindowEnabled(hWnd))
  111. {
  112. EnableWindow(hWnd,FALSE);
  113. }
  114. }
  115. /*****************************************************************************
  116. CVideoCaptureDialog constructor
  117. We don't have a destructor
  118. *****************************************************************************/
  119. CVideoCaptureDialog::CVideoCaptureDialog( HWND hWnd )
  120. : m_hWnd(hWnd),
  121. m_bFirstTime(true),
  122. m_hBigFont(NULL),
  123. m_nListViewWidth(0),
  124. m_hIconLarge(NULL),
  125. m_hIconSmall(NULL),
  126. m_hBackgroundThread(NULL),
  127. m_nDialogMode(0),
  128. m_hAccelTable(NULL),
  129. m_nParentFolderImageListIndex(0),
  130. m_pThreadMessageQueue(NULL)
  131. {
  132. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::CVideoCaptureDialog")));
  133. m_pThreadMessageQueue = new CThreadMessageQueue;
  134. if (m_pThreadMessageQueue)
  135. {
  136. //
  137. // Note that CBackgroundThread takes ownership of m_pThreadMessageQueue, and it doesn't have to be deleted in this thread
  138. //
  139. m_hBackgroundThread = CBackgroundThread::Create( m_pThreadMessageQueue, g_MsgMap, m_CancelEvent.Event(), g_hInstance );
  140. }
  141. m_CurrentAspectRatio.cx = 4;
  142. m_CurrentAspectRatio.cy = 3;
  143. m_sizeThumbnails.cx = c_nMaxThumbnailWidth;
  144. m_sizeThumbnails.cy = c_nMaxThumbnailHeight;
  145. WIA_ASSERT(m_hBackgroundThread != NULL);
  146. }
  147. /*****************************************************************************
  148. CVideoCaptureDialog::OnInitDialog
  149. Handle WM_INITIDIALOG
  150. *****************************************************************************/
  151. LRESULT CVideoCaptureDialog::OnInitDialog( WPARAM, LPARAM lParam )
  152. {
  153. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnInitDialog"));
  154. HRESULT hr;
  155. //
  156. // Make sure the background queue was successfully created
  157. //
  158. if (!m_pThreadMessageQueue)
  159. {
  160. WIA_ERROR((TEXT("VIDEODLG: unable to start background queue")));
  161. EndDialog( m_hWnd, E_OUTOFMEMORY );
  162. return(0);
  163. }
  164. //
  165. // Save incoming data
  166. //
  167. m_pDeviceDialogData = (PDEVICEDIALOGDATA)lParam;
  168. //
  169. // Make sure we have valid arguments
  170. //
  171. if (!m_pDeviceDialogData)
  172. {
  173. WIA_ERROR((TEXT("VIDEODLG: Invalid paramater: PDEVICEDIALOGDATA")));
  174. EndDialog( m_hWnd, E_INVALIDARG );
  175. return(0);
  176. }
  177. //
  178. // Initialialize our return stuff
  179. //
  180. if (m_pDeviceDialogData)
  181. {
  182. m_pDeviceDialogData->lItemCount = 0;
  183. m_pDeviceDialogData->ppWiaItems = NULL;
  184. }
  185. //
  186. // Make sure we have a valid device
  187. //
  188. if (!m_pDeviceDialogData->pIWiaItemRoot)
  189. {
  190. WIA_ERROR((TEXT("VIDEODLG: Invalid paramaters: pIWiaItem")));
  191. EndDialog( m_hWnd, E_INVALIDARG );
  192. return(0);
  193. }
  194. //
  195. // Get deviceID for this device
  196. //
  197. PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,m_strwDeviceId);
  198. //
  199. // Register for device disconnected, item creation and deletion events...
  200. //
  201. hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (LPVOID *)&m_pDevMgr );
  202. WIA_CHECK_HR(hr,"CoCreateInstance( WiaDevMgr )");
  203. if (SUCCEEDED(hr) && m_pDevMgr)
  204. {
  205. CVideoCallback *pVC = new CVideoCallback();
  206. if (pVC)
  207. {
  208. hr = pVC->Initialize( m_hWnd );
  209. WIA_CHECK_HR(hr,"pVC->Initialize()");
  210. if (SUCCEEDED(hr))
  211. {
  212. CComPtr<IWiaEventCallback> pWiaEventCallback;
  213. hr = pVC->QueryInterface( IID_IWiaEventCallback,
  214. (void**)&pWiaEventCallback
  215. );
  216. WIA_CHECK_HR(hr,"pVC->QI( IID_IWiaEventCallback )");
  217. if (SUCCEEDED(hr) && pWiaEventCallback)
  218. {
  219. CSimpleBStr bstr( m_strwDeviceId );
  220. hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK,
  221. bstr,
  222. &WIA_EVENT_DEVICE_DISCONNECTED,
  223. pWiaEventCallback,
  224. &m_pDisconnectedCallback
  225. );
  226. WIA_CHECK_HR(hr,"RegisterEvent( DEVICE_DISCONNECTED )");
  227. hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK,
  228. bstr,
  229. &WIA_EVENT_ITEM_DELETED,
  230. pWiaEventCallback,
  231. &m_pCreateCallback
  232. );
  233. WIA_CHECK_HR(hr,"RegisterEvent( ITEM_DELETE )");
  234. hr = m_pDevMgr->RegisterEventCallbackInterface( WIA_REGISTER_EVENT_CALLBACK,
  235. bstr,
  236. &WIA_EVENT_ITEM_CREATED,
  237. pWiaEventCallback,
  238. &m_pDeleteCallback
  239. );
  240. WIA_CHECK_HR(hr,"RegisterEvent( ITEM_CREATED )");
  241. }
  242. else
  243. {
  244. WIA_ERROR((TEXT("Either QI failed or pWiaEventCallback is NULL!")));
  245. }
  246. }
  247. pVC->Release();
  248. }
  249. }
  250. if (SUCCEEDED(hr) )
  251. {
  252. // Create the WiaVideo object
  253. hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER,
  254. IID_IWiaVideo, (LPVOID *)&m_pWiaVideo);
  255. WIA_CHECK_HR(hr,"CoCreateInstance( WiaVideo )");
  256. }
  257. //
  258. // Prevent multiple selection
  259. //
  260. if (m_pDeviceDialogData->dwFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE)
  261. {
  262. LONG_PTR lStyle = GetWindowLongPtr( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), GWL_STYLE );
  263. SetWindowLongPtr( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), GWL_STYLE, lStyle | LVS_SINGLESEL );
  264. m_nDialogMode = SINGLESEL_MODE;
  265. //
  266. // Hide the "Select All" button
  267. //
  268. ShowWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ), SW_HIDE );
  269. //
  270. // Change text accordingly
  271. //
  272. CSimpleString( IDS_VIDDLG_TITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_VIDDLG_BIG_TITLE ) );
  273. CSimpleString( IDS_VIDDLG_SUBTITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ) );
  274. CSimpleString( IDS_VIDDLG_OK_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) );
  275. }
  276. else
  277. {
  278. m_nDialogMode = MULTISEL_MODE;
  279. }
  280. //
  281. // Make the lovely font
  282. //
  283. m_hBigFont = WiaUiUtil::CreateFontWithPointSizeFromWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_BIG_TITLE), 14, false, false );
  284. if (m_hBigFont)
  285. {
  286. SendDlgItemMessage( m_hWnd,
  287. IDC_VIDDLG_BIG_TITLE,
  288. WM_SETFONT,
  289. reinterpret_cast<WPARAM>(m_hBigFont),
  290. MAKELPARAM(TRUE,0)
  291. );
  292. }
  293. //
  294. // Save the minimum size of the dialog
  295. //
  296. RECT rcWindow;
  297. GetWindowRect( m_hWnd, &rcWindow );
  298. m_sizeMinimumWindow.cx = rcWindow.right - rcWindow.left;
  299. m_sizeMinimumWindow.cy = rcWindow.bottom - rcWindow.top;
  300. //
  301. // Create the sizing control
  302. //
  303. HWND hWndSizingControl = CreateWindowEx( 0, TEXT("scrollbar"), TEXT(""),
  304. WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP|WS_CLIPSIBLINGS|SBS_SIZEBOXBOTTOMRIGHTALIGN|SBS_BOTTOMALIGN|WS_GROUP,
  305. CSimpleRect(m_hWnd).Width()-GetSystemMetrics(SM_CXVSCROLL),
  306. CSimpleRect(m_hWnd).Height()-GetSystemMetrics(SM_CYHSCROLL),
  307. GetSystemMetrics(SM_CXVSCROLL),
  308. GetSystemMetrics(SM_CYHSCROLL),
  309. m_hWnd, reinterpret_cast<HMENU>(IDC_SIZEBOX),
  310. g_hInstance, NULL );
  311. if (!hWndSizingControl)
  312. {
  313. WIA_ERROR((TEXT("CreateWindowEx( sizing control ) failed!")));
  314. }
  315. //
  316. // Reposition all the controls
  317. //
  318. ResizeAll();
  319. //
  320. // Center the window over its parent
  321. //
  322. WiaUiUtil::CenterWindow( m_hWnd, GetParent(m_hWnd) );
  323. //
  324. // Get the device icons and set the window icons
  325. //
  326. CSimpleStringWide strwDeviceId, strwClassId;
  327. LONG nDeviceType;
  328. if (PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_UI_CLSID,strwClassId) &&
  329. PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,strwDeviceId) &&
  330. PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_TYPE,nDeviceType))
  331. {
  332. if (SUCCEEDED(WiaUiExtensionHelper::GetDeviceIcons( CSimpleBStr(strwClassId), nDeviceType, &m_hIconSmall, &m_hIconLarge )))
  333. {
  334. if (m_hIconSmall)
  335. {
  336. SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(m_hIconSmall) );
  337. }
  338. if (m_hIconLarge)
  339. {
  340. SendMessage( m_hWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(m_hIconLarge) );
  341. }
  342. }
  343. }
  344. SetForegroundWindow(m_hWnd);
  345. return(0);
  346. }
  347. /*****************************************************************************
  348. CVideoCaptureDialog::ResizeAll
  349. Resizes and repositions all the controls when the dialog size
  350. changes.
  351. *****************************************************************************/
  352. VOID CVideoCaptureDialog::ResizeAll(VOID)
  353. {
  354. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::ResizeAll")));
  355. CSimpleRect rcClient(m_hWnd);
  356. CMoveWindow mw;
  357. CDialogUnits dialogUnits(m_hWnd);
  358. //WIA_TRACE((TEXT("rcClient is l(%d) t(%d) r(%d) b(%d)"),rcClient.left, rcClient.top, rcClient.right, rcClient.bottom));
  359. //WIA_TRACE((TEXT("rcClient is w(%d) h(%d)"),rcClient.Width(),rcClient.Height()));
  360. //WIA_TRACE((TEXT("dialogUnits.StandardMargin is cx(%d) cy(%d)"),dialogUnits.StandardMargin().cx,dialogUnits.StandardMargin().cy));
  361. //WIA_TRACE((TEXT("dialogUnits.StandardButtonMargin is cx(%d) cy(%d)"),dialogUnits.StandardButtonMargin().cx,dialogUnits.StandardButtonMargin().cy));
  362. //
  363. // Resize the big title
  364. //
  365. mw.Size( GetDlgItem( m_hWnd, IDC_VIDDLG_BIG_TITLE ),
  366. rcClient.Width() - dialogUnits.StandardMargin().cx * 2,
  367. 0,
  368. CMoveWindow::NO_SIZEY );
  369. //
  370. // Resize the subtitle
  371. //
  372. mw.Size( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ),
  373. rcClient.Width() - dialogUnits.StandardMargin().cx * 2,
  374. 0,
  375. CMoveWindow::NO_SIZEY );
  376. CSimpleRect rcOK( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect );
  377. CSimpleRect rcCancel( GetDlgItem( m_hWnd, IDCANCEL ), CSimpleRect::WindowRect );
  378. //WIA_TRACE((TEXT("rcOK is l(%d) t(%d) r(%d) b(%d)"),rcOK.left, rcOK.top, rcOK.right, rcOK.bottom));
  379. //WIA_TRACE((TEXT("rcOK is w(%d) h(%d)"),rcOK.Width(), rcOK.Height()));
  380. //WIA_TRACE((TEXT("rcCancel is l(%d) t(%d) r(%d) b(%d)"),rcCancel.left, rcCancel.top, rcCancel.right, rcCancel.bottom));
  381. //WIA_TRACE((TEXT("rcCancel is w(%d) h(%d)"),rcCancel.Width(), rcCancel.Height()));
  382. //
  383. // Move the OK button
  384. //
  385. LONG x,y;
  386. x = rcClient.Width() - dialogUnits.StandardMargin().cx - dialogUnits.StandardButtonMargin().cx - rcCancel.Width() - rcOK.Width();
  387. y = rcClient.Height() - dialogUnits.StandardMargin().cy - rcOK.Height();
  388. //WIA_TRACE((TEXT("Moving IDOK to x(%x) y(%d)"),x,y));
  389. mw.Move( GetDlgItem( m_hWnd, IDOK ), x, y, 0 );
  390. INT nTopOfOK = y;
  391. INT nBottomOfSub = CSimpleRect( GetDlgItem(m_hWnd,IDC_VIDDLG_LITTLE_TITLE), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).bottom;
  392. //
  393. // Move the cancel button
  394. //
  395. x = rcClient.Width() - dialogUnits.StandardMargin().cx - rcCancel.Width();
  396. y = rcClient.Height() - dialogUnits.StandardMargin().cy - rcCancel.Height();
  397. //WIA_TRACE((TEXT("Moving IDCANCEL to x(%x) y(%d)"),x,y));
  398. mw.Move( GetDlgItem( m_hWnd, IDCANCEL ), x, y, 0 );
  399. //
  400. // Move the resizing handle
  401. //
  402. x = rcClient.Width() - GetSystemMetrics(SM_CXVSCROLL);
  403. y = rcClient.Height() - GetSystemMetrics(SM_CYHSCROLL);
  404. //WIA_TRACE((TEXT("Moving IDC_SIZEBOX to x(%x) y(%d)"),x,y));
  405. mw.Move( GetDlgItem( m_hWnd, IDC_SIZEBOX ), x, y );
  406. //
  407. // Resize the preview window & move the capture button
  408. //
  409. CSimpleRect rcSubTitle( GetDlgItem( m_hWnd, IDC_VIDDLG_LITTLE_TITLE ), CSimpleRect::ClientRect );
  410. CSimpleRect rcCapture( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), CSimpleRect::ClientRect );
  411. CSimpleRect rcSelectAll( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ), CSimpleRect::ClientRect );
  412. //WIA_TRACE((TEXT("rcSubTitle is l(%d) t(%d) r(%d) b(%d)"),rcSubTitle.left, rcSubTitle.top, rcSubTitle.right, rcSubTitle.bottom));
  413. //WIA_TRACE((TEXT("rcSubTitle is w(%d) h(%d)"),rcSubTitle.Width(), rcSubTitle.Height()));
  414. //WIA_TRACE((TEXT("rcCapture is l(%d) t(%d) r(%d) b(%d)"),rcCapture.left, rcCapture.top, rcCapture.right, rcCapture.bottom));
  415. //WIA_TRACE((TEXT("rcCapture is w(%d) h(%d)"),rcCapture.Width(), rcCapture.Height()));
  416. //WIA_TRACE((TEXT("rcSelectAll is l(%d) t(%d) r(%d) b(%d)"),rcSelectAll.left, rcSelectAll.top, rcSelectAll.right, rcSelectAll.bottom));
  417. //WIA_TRACE((TEXT("rcSelectAll is w(%d) h(%d)"),rcSelectAll.Width(), rcSelectAll.Height()));
  418. //WIA_TRACE((TEXT("nTopOfOK is (%d)"),nTopOfOK));
  419. //WIA_TRACE((TEXT("nBottomOfSub is (%d)"),nBottomOfSub));
  420. CSimpleRect rcAvailableArea(
  421. dialogUnits.StandardMargin().cx,
  422. nBottomOfSub + dialogUnits.StandardMargin().cy,
  423. rcClient.right - dialogUnits.StandardMargin().cx,
  424. nTopOfOK - (dialogUnits.StandardButtonMargin().cy * 2)
  425. );
  426. //WIA_TRACE((TEXT("rcAvailableArea is l(%d) t(%d) r(%d) b(%d)"),rcAvailableArea.left, rcAvailableArea.top, rcAvailableArea.right, rcAvailableArea.bottom));
  427. //WIA_TRACE((TEXT("rcAvailableArea is w(%d) h(%d)"),rcAvailableArea.Width(), rcAvailableArea.Height()));
  428. INT full_width = rcAvailableArea.right - rcAvailableArea.left;
  429. INT preview_width = (full_width * 53) / 100;
  430. //WIA_TRACE((TEXT("full_width is (%d)"),full_width));
  431. //WIA_TRACE((TEXT("preview_width is (%d)"),preview_width));
  432. //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));
  433. mw.SizeMove( GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ),
  434. rcAvailableArea.left,
  435. rcAvailableArea.top,
  436. preview_width,
  437. rcAvailableArea.Height() - rcCapture.Height() - dialogUnits.StandardButtonMargin().cy
  438. );
  439. INT offset = (preview_width - rcCapture.Width()) / 2;
  440. //WIA_TRACE((TEXT("offset is (%d)"),offset));
  441. //WIA_TRACE((TEXT("Moving IDC_VIDDLG_CAPTURE to x(%d) y(%d)"),rcAvailableArea.left + offset,rcAvailableArea.bottom - rcCapture.Height()));
  442. mw.Move( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ),
  443. rcAvailableArea.left + offset,
  444. rcAvailableArea.bottom - rcCapture.Height(),
  445. 0 );
  446. //
  447. // Resize the thumbnail list & move the selectall button
  448. //
  449. INT leftThumbEdge = rcAvailableArea.left + preview_width + dialogUnits.StandardMargin().cx;
  450. //WIA_TRACE((TEXT("leftThumbEdge is (%d)"),leftThumbEdge));
  451. //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));
  452. mw.SizeMove( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ),
  453. leftThumbEdge,
  454. rcAvailableArea.top,
  455. rcAvailableArea.Width() - preview_width - dialogUnits.StandardMargin().cx,
  456. rcAvailableArea.Height() - rcSelectAll.Height() - dialogUnits.StandardButtonMargin().cy
  457. );
  458. offset = ((rcAvailableArea.right - leftThumbEdge - rcSelectAll.Width()) / 2);
  459. //WIA_TRACE((TEXT("offset(new) is (%d)"),offset));
  460. //WIA_TRACE((TEXT("Moving IDC_VIDDLG_SELECTALL to x(%d) y(%d)"),leftThumbEdge + offset,rcAvailableArea.bottom - rcSelectAll.Height()));
  461. mw.Move( GetDlgItem( m_hWnd, IDC_VIDDLG_SELECTALL ),
  462. leftThumbEdge + offset,
  463. rcAvailableArea.bottom - rcSelectAll.Height(),
  464. 0 );
  465. //
  466. // Explicitly apply the moves, because the toolbar frame doesn't get painted properly
  467. //
  468. mw.Apply();
  469. //
  470. // Update the dialog's background to remove any weird stuff left behind
  471. //
  472. InvalidateRect( m_hWnd, NULL, FALSE );
  473. UpdateWindow( m_hWnd );
  474. }
  475. /*****************************************************************************
  476. CVideoCaptureDialog::OnSize
  477. Handle WM_SIZE messages
  478. *****************************************************************************/
  479. LRESULT CVideoCaptureDialog::OnSize( WPARAM, LPARAM )
  480. {
  481. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnSize")));
  482. ResizeAll();
  483. //
  484. // Tell the video preview window to resize in within it's
  485. // container window as best it can.
  486. //
  487. if (m_pWiaVideo)
  488. {
  489. m_pWiaVideo->ResizeVideo(FALSE);
  490. }
  491. return(0);
  492. }
  493. /*****************************************************************************
  494. CVideoCaptureDialog::OnShow
  495. Handle WM_SHOW message
  496. *****************************************************************************/
  497. LRESULT CVideoCaptureDialog::OnShow( WPARAM, LPARAM )
  498. {
  499. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnShow")));
  500. if (m_bFirstTime)
  501. {
  502. PostMessage( m_hWnd, PWM_POSTINIT, 0, 0 );
  503. m_bFirstTime = false;
  504. }
  505. return(0);
  506. }
  507. /*****************************************************************************
  508. CVideoCameraDialog::OnGetMinMaxInfo
  509. Handle WM_GETMINMAXINFO
  510. *****************************************************************************/
  511. LRESULT CVideoCaptureDialog::OnGetMinMaxInfo( WPARAM, LPARAM lParam )
  512. {
  513. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnGetMinMaxInfo")));
  514. WIA_TRACE((TEXT("m_sizeMinimumWindow = %d,%d"),m_sizeMinimumWindow.cx,m_sizeMinimumWindow.cy));
  515. LPMINMAXINFO pMinMaxInfo = (LPMINMAXINFO)lParam;
  516. pMinMaxInfo->ptMinTrackSize.x = m_sizeMinimumWindow.cx;
  517. pMinMaxInfo->ptMinTrackSize.y = m_sizeMinimumWindow.cy;
  518. return(0);
  519. }
  520. /*****************************************************************************
  521. CVideoCameraDialog::OnDestroy
  522. Handle WM_DESTROY message and do cleanup
  523. *****************************************************************************/
  524. LRESULT CVideoCaptureDialog::OnDestroy( WPARAM, LPARAM )
  525. {
  526. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDestroy")));
  527. //
  528. // Unregister for events
  529. //
  530. m_pCreateCallback = NULL;
  531. m_pDeleteCallback = NULL;
  532. m_pDisconnectedCallback = NULL;
  533. //
  534. // Tell the background thread to destroy itself
  535. //
  536. m_pThreadMessageQueue->Enqueue( new CThreadMessage(TQ_DESTROY),CThreadMessageQueue::PriorityUrgent );
  537. //
  538. // Close the thread handle
  539. //
  540. CloseHandle( m_hBackgroundThread );
  541. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo)
  542. {
  543. m_pWiaVideo->DestroyVideo();
  544. }
  545. //
  546. // Delete resources
  547. //
  548. if (m_hBigFont)
  549. {
  550. DeleteObject(m_hBigFont);
  551. m_hBigFont = NULL;
  552. }
  553. if (m_hImageList)
  554. {
  555. m_hImageList = NULL;
  556. }
  557. if (m_hAccelTable)
  558. {
  559. DestroyAcceleratorTable(m_hAccelTable);
  560. m_hAccelTable = NULL;
  561. }
  562. if (m_hIconLarge)
  563. {
  564. DestroyIcon(m_hIconLarge);
  565. m_hIconLarge = NULL;
  566. }
  567. if (m_hIconSmall)
  568. {
  569. DestroyIcon(m_hIconSmall);
  570. m_hIconSmall = NULL;
  571. }
  572. return(0);
  573. }
  574. /*****************************************************************************
  575. CVideoCaptureDialog::OnOK
  576. Handle when the user presses "Get Pictures"
  577. *****************************************************************************/
  578. VOID CVideoCaptureDialog::OnOK( WPARAM, LPARAM )
  579. {
  580. WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnOK")));
  581. HRESULT hr = S_OK;
  582. //
  583. // Start w/nothing to return
  584. //
  585. m_pDeviceDialogData->lItemCount = 0;
  586. m_pDeviceDialogData->ppWiaItems = NULL;
  587. //
  588. // Get the indicies of the items that are selected
  589. //
  590. CSimpleDynamicArray<int> aIndices;
  591. GetSelectionIndices( aIndices );
  592. //
  593. // Are there any items selected?
  594. //
  595. if (aIndices.Size())
  596. {
  597. //
  598. // Calculate the size of the buffer needed
  599. //
  600. INT nArraySizeInBytes = sizeof(IWiaItem*) * aIndices.Size();
  601. //
  602. // Alloc a buffer to hold the items
  603. //
  604. m_pDeviceDialogData->ppWiaItems = (IWiaItem**)CoTaskMemAlloc(nArraySizeInBytes);
  605. //
  606. // If we allocated a buffer, fill it up with the
  607. // items to return...
  608. //
  609. if (m_pDeviceDialogData->ppWiaItems)
  610. {
  611. INT i;
  612. ZeroMemory( m_pDeviceDialogData->ppWiaItems, nArraySizeInBytes );
  613. for (i=0;i<aIndices.Size();i++)
  614. {
  615. CCameraItem *pItem = GetListItemNode(aIndices[i]);
  616. if (pItem && pItem->Item())
  617. {
  618. m_pDeviceDialogData->ppWiaItems[i] = pItem->Item();
  619. m_pDeviceDialogData->ppWiaItems[i]->AddRef();
  620. }
  621. else
  622. {
  623. //
  624. // Somehow the list got corrupted
  625. //
  626. hr = E_UNEXPECTED;
  627. break;
  628. }
  629. }
  630. if (!SUCCEEDED(hr))
  631. {
  632. //
  633. // Clean up if we had a failure
  634. //
  635. for (i=0;i<aIndices.Size();i++)
  636. {
  637. if (m_pDeviceDialogData->ppWiaItems[i])
  638. {
  639. m_pDeviceDialogData->ppWiaItems[i]->Release();
  640. }
  641. }
  642. CoTaskMemFree( m_pDeviceDialogData->ppWiaItems );
  643. m_pDeviceDialogData->ppWiaItems = NULL;
  644. }
  645. else
  646. {
  647. m_pDeviceDialogData->lItemCount = aIndices.Size();
  648. }
  649. }
  650. else
  651. {
  652. //
  653. // Unable to alloc buffer
  654. //
  655. WIA_ERROR((TEXT("Couldn't allocate a buffer")));
  656. hr = E_OUTOFMEMORY;
  657. }
  658. }
  659. else
  660. {
  661. //
  662. // There aren't any items selected, so just return without
  663. // ending the dialog...
  664. //
  665. return;
  666. }
  667. EndDialog( m_hWnd, hr );
  668. }
  669. /*****************************************************************************
  670. CVideoCaptureDialog::OnCancel
  671. Handle when the user presses cancel.
  672. *****************************************************************************/
  673. VOID CVideoCaptureDialog::OnCancel( WPARAM, LPARAM )
  674. {
  675. WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnCancel")));
  676. EndDialog( m_hWnd, S_FALSE );
  677. }
  678. /*****************************************************************************
  679. CVideoCaptureDialog::OnSelectAll
  680. Handle when the user presses "Select All" button
  681. *****************************************************************************/
  682. VOID CVideoCaptureDialog::OnSelectAll( WPARAM, LPARAM )
  683. {
  684. WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnSelectAll")));
  685. LVITEM lvItem;
  686. lvItem.mask = LVIF_STATE;
  687. lvItem.iItem = 0;
  688. lvItem.state = LVIS_SELECTED;
  689. lvItem.stateMask = LVIS_SELECTED;
  690. SendMessage( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), LVM_SETITEMSTATE, -1, reinterpret_cast<LPARAM>(&lvItem) );
  691. }
  692. /*****************************************************************************
  693. CVideoCaptureDialog::AddItemToListView
  694. Adds a new IWiaItem to the list view...
  695. *****************************************************************************/
  696. BOOL CVideoCaptureDialog::AddItemToListView( IWiaItem * pItem )
  697. {
  698. WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::AddItemToListView")));
  699. if (!pItem)
  700. {
  701. WIA_ERROR((TEXT("pItem is NULL!")));
  702. return FALSE;
  703. }
  704. //
  705. // Add the new picture to our list
  706. //
  707. CCameraItem * pNewCameraItem = new CCameraItem( pItem );
  708. if (pNewCameraItem)
  709. {
  710. WIA_TRACE((TEXT("Attempting to add new item to tree")));
  711. m_CameraItemList.Add( NULL, pNewCameraItem );
  712. }
  713. else
  714. {
  715. WIA_ERROR((TEXT("Couldn't create a new pNewCameraItem")));
  716. }
  717. //
  718. // Create a thumbnail for the new item
  719. //
  720. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  721. if (hwndList && pNewCameraItem)
  722. {
  723. HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL );
  724. if (hImageList)
  725. {
  726. CVideoCaptureDialog::CreateThumbnails( pNewCameraItem,
  727. hImageList,
  728. FALSE
  729. );
  730. }
  731. else
  732. {
  733. WIA_ERROR((TEXT("Couldn't get hImageList to get new thumbnail")));
  734. }
  735. //
  736. // Update the listview with the new item
  737. //
  738. LVITEM lvItem;
  739. INT iItem = ListView_GetItemCount( hwndList ) + 1;
  740. ZeroMemory( &lvItem, sizeof(lvItem) );
  741. lvItem.iItem = iItem;
  742. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  743. lvItem.iImage = pNewCameraItem->ImageListIndex();
  744. lvItem.lParam = (LPARAM)pNewCameraItem;
  745. int nIndex = ListView_InsertItem( hwndList, &lvItem );
  746. //
  747. // Retrieve actual thumbnail
  748. //
  749. RequestThumbnails( pNewCameraItem );
  750. //
  751. // Select the new item
  752. //
  753. SetSelectedListItem( nIndex );
  754. //
  755. // Make sure the item is visible
  756. //
  757. ListView_EnsureVisible( hwndList, nIndex, FALSE );
  758. }
  759. return TRUE;
  760. }
  761. /*****************************************************************************
  762. CVideoCaptureDialog::OnCapture
  763. Handle when the user presses the "Capture" button
  764. *****************************************************************************/
  765. VOID CVideoCaptureDialog::OnCapture( WPARAM, LPARAM )
  766. {
  767. WIA_PUSHFUNCTION((TEXT("CVideoCameraDialog::OnCapture")));
  768. //
  769. // Disable capture button until we're done with this iteration
  770. //
  771. MyEnableWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), FALSE );
  772. //
  773. // Tell the video device to snap a picture
  774. //
  775. CComPtr<IWiaItem> pItem;
  776. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo)
  777. {
  778. WIA_TRACE((TEXT("Telling WiaVideo to take a picture")));
  779. BSTR bstrNewImageFileName = NULL;
  780. //
  781. // Take the picture
  782. //
  783. HRESULT hr = m_pWiaVideo->TakePicture(&bstrNewImageFileName);
  784. WIA_CHECK_HR(hr,"m_pWiaVideo->TakePicture");
  785. if (hr == S_OK)
  786. {
  787. //
  788. // Succeeded in taking the picture, setting the LAST_PICTURE_TAKEN property
  789. // on the video driver to create a new item.
  790. //
  791. BOOL bSuccess = FALSE;
  792. PROPVARIANT pv;
  793. PropVariantInit(&pv);
  794. pv.vt = VT_BSTR;
  795. pv.bstrVal = bstrNewImageFileName;
  796. bSuccess = PropStorageHelpers::SetProperty(m_pDeviceDialogData->pIWiaItemRoot,
  797. WIA_DPV_LAST_PICTURE_TAKEN,
  798. pv);
  799. //
  800. // Note that this will free the bstrNewImageFileName returned to
  801. // us by WiaVideo
  802. //
  803. PropVariantClear(&pv);
  804. }
  805. }
  806. //
  807. // Re-Enable capture button now that we're done
  808. //
  809. MyEnableWindow( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ), TRUE );
  810. //
  811. // Make sure the focus is still on our control
  812. //
  813. SetFocus( GetDlgItem( m_hWnd, IDC_VIDDLG_CAPTURE ) );
  814. }
  815. /*****************************************************************************
  816. CVideoCaptureDialog::OnDblClickImageList
  817. Translate a dbl-click on a thumbnail in the listview into a click
  818. on the "Get Pictures" button.
  819. *****************************************************************************/
  820. LRESULT CVideoCaptureDialog::OnDblClkImageList( WPARAM, LPARAM )
  821. {
  822. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDblClkImageList")));
  823. SendMessage( m_hWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 );
  824. return 0;
  825. }
  826. /*****************************************************************************
  827. CVideoCaptureDialog::OnImageListItemChanged
  828. Sent whenever an item in the thumbnail list changes.
  829. *****************************************************************************/
  830. LRESULT CVideoCaptureDialog::OnImageListItemChanged( WPARAM, LPARAM )
  831. {
  832. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnImageListItemChanged")));
  833. HandleSelectionChange();
  834. return 0;
  835. }
  836. /*****************************************************************************
  837. CVideoCaptureDialog::OnImageListKeyDown
  838. Forward the keyboard messages within the listview appropriately.
  839. *****************************************************************************/
  840. LRESULT CVideoCaptureDialog::OnImageListKeyDown( WPARAM, LPARAM lParam )
  841. {
  842. LPNMLVKEYDOWN pnkd = reinterpret_cast<LPNMLVKEYDOWN>(lParam);
  843. if (pnkd)
  844. {
  845. if (VK_LEFT == pnkd->wVKey && (GetKeyState(VK_MENU) & 0x8000))
  846. {
  847. SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 );
  848. }
  849. }
  850. return 0;
  851. }
  852. /*****************************************************************************
  853. CVideoCaptureDialog::OnNotify
  854. Handle WM_NOTIFY messages
  855. *****************************************************************************/
  856. LRESULT CVideoCaptureDialog::OnNotify( WPARAM wParam, LPARAM lParam )
  857. {
  858. SC_BEGIN_NOTIFY_MESSAGE_HANDLERS()
  859. {
  860. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( NM_DBLCLK, IDC_VIDDLG_THUMBNAILLIST, OnDblClkImageList );
  861. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_ITEMCHANGED, IDC_VIDDLG_THUMBNAILLIST, OnImageListItemChanged );
  862. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_KEYDOWN, IDC_VIDDLG_THUMBNAILLIST, OnImageListKeyDown );
  863. }
  864. SC_END_NOTIFY_MESSAGE_HANDLERS();
  865. }
  866. /*****************************************************************************
  867. CVideoCaptureDialog::OnCommand
  868. Handle WM_COMMAND messages
  869. *****************************************************************************/
  870. LRESULT CVideoCaptureDialog::OnCommand( WPARAM wParam, LPARAM lParam )
  871. {
  872. SC_BEGIN_COMMAND_HANDLERS()
  873. {
  874. SC_HANDLE_COMMAND(IDOK, OnOK);
  875. SC_HANDLE_COMMAND(IDCANCEL, OnCancel);
  876. SC_HANDLE_COMMAND(IDC_VIDDLG_CAPTURE, OnCapture);
  877. SC_HANDLE_COMMAND(IDC_VIDDLG_SELECTALL, OnSelectAll);
  878. }
  879. SC_END_COMMAND_HANDLERS();
  880. }
  881. /*****************************************************************************
  882. CVideoCaptureDialog::OnGetThumbnail
  883. Called by background thread to get the thumbnail for a given item.
  884. *****************************************************************************/
  885. BOOL WINAPI CVideoCaptureDialog::OnGetThumbnail( CThreadMessage *pMsg )
  886. {
  887. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnGetThumbnail"));
  888. HBITMAP hBmpThumbnail = NULL;
  889. CThumbnailThreadMessage *pThumbMsg = (CThumbnailThreadMessage *)(pMsg);
  890. if (pThumbMsg)
  891. {
  892. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  893. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable,
  894. NULL,
  895. CLSCTX_INPROC_SERVER,
  896. IID_IGlobalInterfaceTable,
  897. (void **)&pGlobalInterfaceTable);
  898. if (SUCCEEDED(hr) && pGlobalInterfaceTable)
  899. {
  900. CComPtr<IWiaItem> pIWiaItem;
  901. hr = pGlobalInterfaceTable->GetInterfaceFromGlobal(
  902. pThumbMsg->GlobalInterfaceTableCookie(),
  903. IID_IWiaItem,
  904. (void**)&pIWiaItem);
  905. if (SUCCEEDED(hr) && pIWiaItem)
  906. {
  907. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  908. hr = pIWiaItem->QueryInterface( IID_IWiaPropertyStorage,
  909. (void**)&pIWiaPropertyStorage
  910. );
  911. if (SUCCEEDED(hr) && pIWiaPropertyStorage)
  912. {
  913. PROPVARIANT PropVar[3];
  914. PROPSPEC PropSpec[3];
  915. PropSpec[0].ulKind = PRSPEC_PROPID;
  916. PropSpec[0].propid = WIA_IPC_THUMB_WIDTH;
  917. PropSpec[1].ulKind = PRSPEC_PROPID;
  918. PropSpec[1].propid = WIA_IPC_THUMB_HEIGHT;
  919. PropSpec[2].ulKind = PRSPEC_PROPID;
  920. PropSpec[2].propid = WIA_IPC_THUMBNAIL;
  921. hr = pIWiaPropertyStorage->ReadMultiple(ARRAYSIZE(PropSpec),PropSpec,PropVar );
  922. if (SUCCEEDED(hr))
  923. {
  924. 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));
  925. if ((PropVar[0].vt == VT_I4 || PropVar[0].vt == VT_UI4) &&
  926. (PropVar[1].vt == VT_I4 || PropVar[1].vt == VT_UI4) &&
  927. (PropVar[2].vt == (VT_UI1|VT_VECTOR)))
  928. {
  929. BITMAPINFO bmi;
  930. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  931. bmi.bmiHeader.biWidth = PropVar[0].ulVal;
  932. bmi.bmiHeader.biHeight = PropVar[1].ulVal;
  933. bmi.bmiHeader.biPlanes = 1;
  934. bmi.bmiHeader.biBitCount = 24;
  935. bmi.bmiHeader.biCompression = BI_RGB;
  936. bmi.bmiHeader.biSizeImage = 0;
  937. bmi.bmiHeader.biXPelsPerMeter = 0;
  938. bmi.bmiHeader.biYPelsPerMeter = 0;
  939. bmi.bmiHeader.biClrUsed = 0;
  940. bmi.bmiHeader.biClrImportant = 0;
  941. HDC hDC = GetDC(NULL);
  942. if (hDC)
  943. {
  944. PBYTE *pBits;
  945. HBITMAP hDibSection = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (PVOID*)&pBits, NULL, 0 );
  946. if (hDibSection)
  947. {
  948. CopyMemory( pBits, PropVar[2].caub.pElems, PropVar[2].caub.cElems );
  949. hr = ScaleImage( hDC, hDibSection, hBmpThumbnail, pThumbMsg->ThumbSize());
  950. if (SUCCEEDED(hr))
  951. {
  952. WIA_TRACE((TEXT("Sending this image to the notification window: %08X"),pThumbMsg->NotifyWindow()));
  953. }
  954. else
  955. {
  956. hBmpThumbnail = NULL;
  957. }
  958. DeleteObject(hDibSection);
  959. }
  960. ReleaseDC(NULL,hDC);
  961. }
  962. }
  963. PropVariantClear(&PropVar[0]);
  964. PropVariantClear(&PropVar[1]);
  965. PropVariantClear(&PropVar[2]);
  966. }
  967. }
  968. }
  969. }
  970. }
  971. LRESULT lRes = SendMessage( pThumbMsg->NotifyWindow(), PWM_THUMBNAILSTATUS, (WPARAM)pThumbMsg->GlobalInterfaceTableCookie(), (LPARAM)hBmpThumbnail );
  972. if (HANDLED_THREAD_MESSAGE != lRes && hBmpThumbnail)
  973. {
  974. DeleteObject( hBmpThumbnail );
  975. }
  976. return TRUE;
  977. }
  978. /*****************************************************************************
  979. CVideoCaptureDialog::OnThreadDestroy
  980. <Notes>
  981. *****************************************************************************/
  982. BOOL WINAPI CVideoCaptureDialog::OnThreadDestroy( CThreadMessage * )
  983. {
  984. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnThreadDestroy"));
  985. return FALSE;
  986. }
  987. /*****************************************************************************
  988. CVideoCaptureDialog::SetSelectedListItem
  989. <Notes>
  990. *****************************************************************************/
  991. BOOL
  992. CVideoCaptureDialog::SetSelectedListItem( int nIndex )
  993. {
  994. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  995. //
  996. // Check for bad args
  997. //
  998. if (!hwndList)
  999. {
  1000. return FALSE;
  1001. }
  1002. int iCount = ListView_GetItemCount(hwndList);
  1003. for (int i=0;i<iCount;i++)
  1004. {
  1005. ListView_SetItemState(hwndList,i,0,LVIS_SELECTED|LVIS_FOCUSED);
  1006. }
  1007. ListView_SetItemState(hwndList,nIndex,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
  1008. return TRUE;
  1009. }
  1010. /*****************************************************************************
  1011. CVideoCaptureDialog::MarkItemDeletePending
  1012. <Notes>
  1013. *****************************************************************************/
  1014. VOID
  1015. CVideoCaptureDialog::MarkItemDeletePending( INT nIndex, BOOL bSet )
  1016. {
  1017. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1018. if (hwndList)
  1019. {
  1020. ListView_SetItemState( hwndList, nIndex, bSet ? LVIS_CUT : 0, LVIS_CUT );
  1021. }
  1022. }
  1023. /*****************************************************************************
  1024. CVideoCaptureDialog::PopulateList
  1025. Populates the listview with the current items.
  1026. *****************************************************************************/
  1027. BOOL
  1028. CVideoCaptureDialog::PopulateList( CCameraItem *pOldParent )
  1029. {
  1030. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1031. int nSelItem = 0;
  1032. if (hwndList)
  1033. {
  1034. ListView_DeleteAllItems( hwndList );
  1035. int nItem = 0;
  1036. CCameraItem *pCurr;
  1037. //
  1038. // If this is a child directory...
  1039. //
  1040. if (m_pCurrentParentItem)
  1041. {
  1042. //
  1043. // Start adding children
  1044. //
  1045. pCurr = m_pCurrentParentItem->Children();
  1046. //
  1047. // Insert a dummy item that the user can use to
  1048. // switch to the parent directory
  1049. //
  1050. LVITEM lvItem;
  1051. ZeroMemory( &lvItem, sizeof(lvItem) );
  1052. lvItem.iItem = nItem++;
  1053. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  1054. lvItem.iImage = m_nParentFolderImageListIndex;
  1055. lvItem.lParam = 0;
  1056. ListView_InsertItem( hwndList, &lvItem );
  1057. }
  1058. else
  1059. {
  1060. //
  1061. // if it's a parent directory...
  1062. //
  1063. pCurr = m_CameraItemList.Root();
  1064. }
  1065. while (pCurr)
  1066. {
  1067. if (pOldParent && *pCurr == *pOldParent)
  1068. {
  1069. nSelItem = nItem;
  1070. }
  1071. if (pCurr->DeleteState() != CCameraItem::Delete_Deleted)
  1072. {
  1073. LVITEM lvItem;
  1074. ZeroMemory( &lvItem, sizeof(lvItem) );
  1075. lvItem.iItem = nItem++;
  1076. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  1077. lvItem.iImage = pCurr->ImageListIndex();
  1078. lvItem.lParam = (LPARAM)pCurr;
  1079. int nIndex = ListView_InsertItem( hwndList, &lvItem );
  1080. if (nIndex >= 0 && pCurr->DeleteState() == CCameraItem::Delete_Pending)
  1081. {
  1082. MarkItemDeletePending(nIndex,true);
  1083. }
  1084. }
  1085. pCurr = pCurr->Next();
  1086. }
  1087. }
  1088. //
  1089. // If we've not calculated the width of the list in preview mode, attempt to do it
  1090. //
  1091. if (!m_nListViewWidth)
  1092. {
  1093. RECT rcItem;
  1094. if (ListView_GetItemRect( GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ), 0, &rcItem, LVIR_ICON ))
  1095. {
  1096. m_nListViewWidth = (rcItem.right-rcItem.left) + rcItem.left * 2 + GetSystemMetrics(SM_CXHSCROLL) + c_nAdditionalMarginX;
  1097. }
  1098. }
  1099. SetSelectedListItem(nSelItem);
  1100. return TRUE;
  1101. }
  1102. /*****************************************************************************
  1103. CVideoCaptureDialog::OnThumbnailStatus
  1104. <Notes>
  1105. *****************************************************************************/
  1106. LRESULT
  1107. CVideoCaptureDialog::OnThumbnailStatus( WPARAM wParam, LPARAM lParam )
  1108. {
  1109. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::OnThumbnailStatus"));
  1110. WIA_TRACE((TEXT("Looking for the item with the ID %08X"),wParam));
  1111. CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam );
  1112. if (pCameraItem)
  1113. {
  1114. WIA_TRACE((TEXT("Found a CameraItem * (%08X)"),pCameraItem));
  1115. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1116. if (hwndList)
  1117. {
  1118. WIA_TRACE((TEXT("Got the list control")));
  1119. HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL );
  1120. if (hImageList)
  1121. {
  1122. WIA_TRACE((TEXT("Got the image list")));
  1123. if ((HBITMAP)lParam)
  1124. {
  1125. if (ImageList_Replace( hImageList, pCameraItem->ImageListIndex(), (HBITMAP)lParam, NULL ))
  1126. {
  1127. WIA_TRACE((TEXT("Replaced the image in the list")));
  1128. int nItem = FindItemInList(pCameraItem);
  1129. if (nItem >= 0)
  1130. {
  1131. LV_ITEM lvItem;
  1132. ::ZeroMemory(&lvItem,sizeof(LV_ITEM));
  1133. lvItem.iItem = nItem;
  1134. lvItem.mask = LVIF_IMAGE;
  1135. lvItem.iImage = pCameraItem->ImageListIndex();
  1136. ListView_SetItem( hwndList, &lvItem );
  1137. ListView_Update( hwndList, nItem );
  1138. InvalidateRect( hwndList, NULL, FALSE );
  1139. }
  1140. }
  1141. }
  1142. }
  1143. }
  1144. }
  1145. //
  1146. // Clean up the bitmap, regardless of any other failures, to avoid memory leaks
  1147. //
  1148. HBITMAP hBmpThumb = (HBITMAP)lParam;
  1149. if (hBmpThumb)
  1150. {
  1151. DeleteObject(hBmpThumb);
  1152. }
  1153. return HANDLED_THREAD_MESSAGE;
  1154. }
  1155. /*****************************************************************************
  1156. CVideoCaptureDialog::CreateThumbnails
  1157. <Notes>
  1158. *****************************************************************************/
  1159. void CVideoCaptureDialog::CreateThumbnails( CCameraItem *pRoot, HIMAGELIST hImageList, bool bForce )
  1160. {
  1161. CCameraItem *pCurr = pRoot;
  1162. while (pCurr)
  1163. {
  1164. if (pCurr->ImageListIndex()<0 || bForce)
  1165. {
  1166. //
  1167. // Get the item name
  1168. //
  1169. CSimpleStringWide strItemName;
  1170. PropStorageHelpers::GetProperty( pCurr->Item(), WIA_IPA_ITEM_NAME, strItemName );
  1171. //
  1172. // Create the title for the icon
  1173. //
  1174. CSimpleString strIconTitle;
  1175. if (pCurr->IsFolder())
  1176. {
  1177. strIconTitle = CSimpleStringConvert::NaturalString(strItemName);
  1178. }
  1179. else if (strItemName.Length())
  1180. {
  1181. strIconTitle.Format( IDS_VIDDLG_DOWNLOADINGTHUMBNAIL, g_hInstance, CSimpleStringConvert::NaturalString(strItemName).String() );
  1182. }
  1183. //
  1184. // Create the thumbnail
  1185. //
  1186. 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 );
  1187. if (hBmp)
  1188. {
  1189. if (pCurr->ImageListIndex()<0)
  1190. {
  1191. pCurr->ImageListIndex(ImageList_Add( hImageList, hBmp, NULL ));
  1192. }
  1193. else
  1194. {
  1195. pCurr->ImageListIndex(ImageList_Replace( hImageList, pCurr->ImageListIndex(), hBmp, NULL ));
  1196. }
  1197. DeleteObject(hBmp);
  1198. }
  1199. }
  1200. if (pCurr->Children())
  1201. {
  1202. CreateThumbnails( pCurr->Children(), hImageList, bForce );
  1203. }
  1204. pCurr = pCurr->Next();
  1205. }
  1206. }
  1207. /*****************************************************************************
  1208. CVideoCaptureDialog::RequestThumbnails
  1209. <Notes>
  1210. *****************************************************************************/
  1211. VOID
  1212. CVideoCaptureDialog::RequestThumbnails( CCameraItem *pRoot )
  1213. {
  1214. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::RequestThumbnails"));
  1215. CCameraItem *pCurr = pRoot;
  1216. while (pCurr)
  1217. {
  1218. if (!pCurr->IsFolder())
  1219. {
  1220. m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pCurr->GlobalInterfaceTableCookie(), m_sizeThumbnails ) );
  1221. }
  1222. if (pCurr->Children())
  1223. {
  1224. RequestThumbnails( pCurr->Children() );
  1225. }
  1226. pCurr = pCurr->Next();
  1227. }
  1228. }
  1229. /*****************************************************************************
  1230. CVideoCaptureDialog::CreateThumbnails
  1231. <Notes>
  1232. *****************************************************************************/
  1233. VOID
  1234. CVideoCaptureDialog::CreateThumbnails( BOOL bForce )
  1235. {
  1236. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1237. if (hwndList)
  1238. {
  1239. HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL );
  1240. if (hImageList)
  1241. {
  1242. //
  1243. // Create the parent folder image and add it to the image list
  1244. //
  1245. HBITMAP hParentBitmap = WiaUiUtil::CreateIconThumbnail(
  1246. hwndList,
  1247. m_sizeThumbnails.cx,
  1248. m_sizeThumbnails.cy,
  1249. g_hInstance,
  1250. IDI_VIDDLG_PARENTFOLDER,
  1251. TEXT("(..)") );
  1252. if (hParentBitmap)
  1253. {
  1254. m_nParentFolderImageListIndex = ImageList_Add( hImageList, hParentBitmap, NULL );
  1255. DeleteObject(hParentBitmap);
  1256. }
  1257. //
  1258. // Create all of the other images
  1259. //
  1260. CreateThumbnails( m_CameraItemList.Root(), hImageList, bForce != 0 );
  1261. }
  1262. }
  1263. }
  1264. /*****************************************************************************
  1265. CVideoCaptureDialog::FindMaximumThumbnailSize
  1266. Looks through entire item list to get larget thumbnail.
  1267. *****************************************************************************/
  1268. BOOL
  1269. CVideoCaptureDialog::FindMaximumThumbnailSize( VOID )
  1270. {
  1271. WIA_PUSHFUNCTION(TEXT("CVideoCaptureDialog::FindMaximumThumbnailSize"));
  1272. BOOL bResult = false;
  1273. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot)
  1274. {
  1275. LONG nWidth, nHeight;
  1276. if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nWidth ) &&
  1277. PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nHeight ))
  1278. {
  1279. m_sizeThumbnails.cx = max(c_nMinThumbnailWidth,min(nWidth,c_nMaxThumbnailWidth));
  1280. m_sizeThumbnails.cy = max(c_nMinThumbnailHeight,min(nHeight,c_nMaxThumbnailHeight));
  1281. }
  1282. else
  1283. {
  1284. WIA_TRACE((TEXT("FindMaximumThumbnailSize: Unable to retrieve thumbnail size for device")));
  1285. }
  1286. }
  1287. return(bResult && m_sizeThumbnails.cx && m_sizeThumbnails.cy);
  1288. }
  1289. /*****************************************************************************
  1290. CVideoCaptureDialog::EnumerateItems
  1291. Enumerate all the items at this level of the camera.
  1292. *****************************************************************************/
  1293. HRESULT
  1294. CVideoCaptureDialog::EnumerateItems( CCameraItem *pCurrentParent, IEnumWiaItem *pIEnumWiaItem )
  1295. {
  1296. WIA_PUSHFUNCTION(TEXT("CCameraItemList::EnumerateItems"));
  1297. HRESULT hr = E_FAIL;
  1298. if (pIEnumWiaItem != NULL)
  1299. {
  1300. hr = pIEnumWiaItem->Reset();
  1301. while (hr == S_OK)
  1302. {
  1303. CComPtr<IWiaItem> pIWiaItem;
  1304. hr = pIEnumWiaItem->Next(1, &pIWiaItem, NULL);
  1305. if (hr == S_OK)
  1306. {
  1307. CCameraItem *pNewCameraItem = new CCameraItem( pIWiaItem );
  1308. if (pNewCameraItem && pNewCameraItem->Item())
  1309. {
  1310. m_CameraItemList.Add( pCurrentParent, pNewCameraItem );
  1311. LONG ItemType;
  1312. HRESULT hr2;
  1313. hr2 = pNewCameraItem->Item()->GetItemType(&ItemType);
  1314. if (SUCCEEDED(hr2))
  1315. {
  1316. if (ItemType & WiaItemTypeImage)
  1317. {
  1318. WIA_TRACE((TEXT("Found an image")));
  1319. }
  1320. else
  1321. {
  1322. WIA_TRACE((TEXT("Found something that is NOT an image")));
  1323. }
  1324. CComPtr <IEnumWiaItem> pIEnumChildItem;
  1325. hr2 = pIWiaItem->EnumChildItems(&pIEnumChildItem);
  1326. if (hr2 == S_OK)
  1327. {
  1328. EnumerateItems( pNewCameraItem, pIEnumChildItem );
  1329. }
  1330. }
  1331. }
  1332. }
  1333. }
  1334. }
  1335. return hr;
  1336. }
  1337. /*****************************************************************************
  1338. CVideoCaptureDialog::EnumerateAllCameraItems
  1339. Enumerate all the items in camera, including folders.
  1340. *****************************************************************************/
  1341. HRESULT CVideoCaptureDialog::EnumerateAllCameraItems(void)
  1342. {
  1343. CComPtr<IEnumWiaItem> pIEnumItem;
  1344. HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->EnumChildItems(&pIEnumItem);
  1345. if (hr == S_OK)
  1346. {
  1347. hr = EnumerateItems( NULL, pIEnumItem );
  1348. }
  1349. return(hr);
  1350. }
  1351. /*****************************************************************************
  1352. CVideoCaptureDialog::GetSelectionIndices
  1353. Returns an array with the list indicies of the items that are
  1354. selected in IDC_VIDDLG_THUMBNAILLIST
  1355. *****************************************************************************/
  1356. INT
  1357. CVideoCaptureDialog::GetSelectionIndices( CSimpleDynamicArray<int> &aIndices )
  1358. {
  1359. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1360. if (!hwndList)
  1361. {
  1362. return 0;
  1363. }
  1364. INT iCount = ListView_GetItemCount(hwndList);
  1365. for (INT i=0; i<iCount; i++)
  1366. {
  1367. if (ListView_GetItemState(hwndList,i,LVIS_SELECTED) & LVIS_SELECTED)
  1368. {
  1369. aIndices.Append(i);
  1370. }
  1371. }
  1372. return aIndices.Size();
  1373. }
  1374. /*****************************************************************************
  1375. CVideoCaptureDialog::OnPostInit
  1376. Handle the post WM_INIT processing that needs to take place.
  1377. *****************************************************************************/
  1378. LRESULT CVideoCaptureDialog::OnPostInit( WPARAM, LPARAM )
  1379. {
  1380. //
  1381. // Create the progress dialog
  1382. //
  1383. CComPtr<IWiaProgressDialog> pWiaProgressDialog;
  1384. HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaProgressDialog, (void**)&pWiaProgressDialog );
  1385. if (SUCCEEDED(hr))
  1386. {
  1387. //
  1388. // Initialize the progress dialog
  1389. //
  1390. pWiaProgressDialog->Create( m_hWnd, WIA_PROGRESSDLG_ANIM_VIDEO_COMMUNICATE|WIA_PROGRESSDLG_NO_PROGRESS|WIA_PROGRESSDLG_NO_CANCEL|WIA_PROGRESSDLG_NO_TITLE );
  1391. pWiaProgressDialog->SetTitle( CSimpleStringConvert::WideString(CSimpleString(IDS_VIDDLG_PROGDLG_TITLE,g_hInstance)));
  1392. pWiaProgressDialog->SetMessage( CSimpleStringConvert::WideString(CSimpleString(IDS_VIDDLG_PROGDLG_MESSAGE,g_hInstance)));
  1393. //
  1394. // Show the progress dialog
  1395. //
  1396. pWiaProgressDialog->Show();
  1397. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot && m_pWiaVideo)
  1398. {
  1399. CSimpleString strImagesDirectory;
  1400. if (hr == S_OK)
  1401. {
  1402. BOOL bSuccess = FALSE;
  1403. //
  1404. // Get the IMAGES_DIRECTORY property from the Wia Video Driver.
  1405. //
  1406. bSuccess = PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,
  1407. WIA_DPV_IMAGES_DIRECTORY,
  1408. strImagesDirectory);
  1409. if (!bSuccess)
  1410. {
  1411. hr = E_FAIL;
  1412. }
  1413. }
  1414. if (hr == S_OK)
  1415. {
  1416. WIAVIDEO_STATE VideoState = WIAVIDEO_NO_VIDEO;
  1417. //
  1418. // Get the current state of the WiaVideo object. If we just created it
  1419. // then the state will be NO_VIDEO, otherwise, it could already be previewing video,
  1420. // in which case we shouldn't do anything.
  1421. //
  1422. hr = m_pWiaVideo->GetCurrentState(&VideoState);
  1423. if (VideoState == WIAVIDEO_NO_VIDEO)
  1424. {
  1425. //
  1426. // Set the directory we want to save our images to. We got the image directory
  1427. // from the Wia Video Driver IMAGES_DIRECTORY property
  1428. //
  1429. if (hr == S_OK)
  1430. {
  1431. hr = m_pWiaVideo->put_ImagesDirectory(CSimpleBStr(strImagesDirectory));
  1432. }
  1433. //
  1434. // Create the video preview as a child of the IDC_VIDSEL_PREVIEW dialog item
  1435. // and automatically begin playback after creating the preview.
  1436. //
  1437. if (hr == S_OK)
  1438. {
  1439. hr = m_pWiaVideo->CreateVideoByWiaDevID(CSimpleBStr(m_strwDeviceId),
  1440. GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ),
  1441. FALSE,
  1442. TRUE);
  1443. }
  1444. }
  1445. }
  1446. if (hr != S_OK)
  1447. {
  1448. //
  1449. // Let the user know that the graph is most likely already
  1450. // in use...
  1451. //
  1452. MessageBox( m_hWnd,
  1453. CSimpleString(IDS_VIDDLG_BUSY_TEXT, g_hInstance),
  1454. CSimpleString(IDS_VIDDLG_BUSY_TITLE, g_hInstance),
  1455. MB_OK | MB_ICONWARNING | MB_SETFOREGROUND
  1456. );
  1457. //
  1458. // Disable the capture button since we have no graph
  1459. //
  1460. MyEnableWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_CAPTURE), FALSE );
  1461. }
  1462. }
  1463. //
  1464. // Go get all the items..
  1465. //
  1466. EnumerateAllCameraItems();
  1467. FindMaximumThumbnailSize();
  1468. //
  1469. // Initialize Thumbnail Listview control
  1470. //
  1471. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1472. if (hwndList)
  1473. {
  1474. ListView_SetExtendedListViewStyleEx( hwndList,
  1475. LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS,
  1476. LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS
  1477. );
  1478. m_hImageList = ImageList_Create( m_sizeThumbnails.cx,
  1479. m_sizeThumbnails.cy,
  1480. ILC_COLOR24|ILC_MIRROR, 1, 1
  1481. );
  1482. if (m_hImageList)
  1483. {
  1484. ListView_SetImageList( hwndList,
  1485. m_hImageList,
  1486. LVSIL_NORMAL
  1487. );
  1488. ListView_SetIconSpacing( hwndList,
  1489. m_sizeThumbnails.cx + c_nAdditionalMarginX,
  1490. m_sizeThumbnails.cy + c_nAdditionalMarginY
  1491. );
  1492. }
  1493. }
  1494. CreateThumbnails();
  1495. //
  1496. // This causes the list to be populated
  1497. //
  1498. ChangeFolder(NULL);
  1499. HandleSelectionChange();
  1500. RequestThumbnails( m_CameraItemList.Root() );
  1501. //
  1502. // Close the progress dialog
  1503. //
  1504. pWiaProgressDialog->Destroy();
  1505. }
  1506. return(0);
  1507. }
  1508. /*****************************************************************************
  1509. CVideoCaptureDialog::FindItemInList
  1510. <Notes>
  1511. *****************************************************************************/
  1512. INT CVideoCaptureDialog::FindItemInList( CCameraItem *pItem )
  1513. {
  1514. if (pItem)
  1515. {
  1516. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1517. if (hwndList)
  1518. {
  1519. for (int i=0;i<ListView_GetItemCount(hwndList);i++)
  1520. {
  1521. if (pItem == GetListItemNode(i))
  1522. {
  1523. return i;
  1524. }
  1525. }
  1526. }
  1527. }
  1528. return -1;
  1529. }
  1530. /*****************************************************************************
  1531. CVideoCaptureDialog::GetListItemNode
  1532. <Notes>
  1533. *****************************************************************************/
  1534. CCameraItem *
  1535. CVideoCaptureDialog::GetListItemNode( int nIndex )
  1536. {
  1537. HWND hwndList = GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST );
  1538. if (!hwndList)
  1539. {
  1540. return NULL;
  1541. }
  1542. LV_ITEM lvItem;
  1543. ::ZeroMemory(&lvItem,sizeof(LV_ITEM));
  1544. lvItem.mask = LVIF_PARAM;
  1545. lvItem.iItem = nIndex;
  1546. if (!ListView_GetItem( hwndList, &lvItem ))
  1547. {
  1548. return NULL ;
  1549. }
  1550. return((CCameraItem *)lvItem.lParam);
  1551. }
  1552. /*****************************************************************************
  1553. CVideoCaptureDialog::ChangeFolder
  1554. Change the current folder being viewed
  1555. *****************************************************************************/
  1556. BOOL
  1557. CVideoCaptureDialog::ChangeFolder( CCameraItem *pNode )
  1558. {
  1559. CCameraItem *pOldParent = m_pCurrentParentItem;
  1560. m_pCurrentParentItem = pNode;
  1561. return PopulateList(pOldParent);
  1562. }
  1563. /*****************************************************************************
  1564. CVideoCaptureDialog::OnChangeToParent
  1565. <Notes>
  1566. *****************************************************************************/
  1567. LRESULT
  1568. CVideoCaptureDialog::OnChangeToParent( WPARAM, LPARAM )
  1569. {
  1570. if (m_pCurrentParentItem)
  1571. {
  1572. ChangeFolder(m_pCurrentParentItem->Parent());
  1573. }
  1574. return(0);
  1575. }
  1576. /*****************************************************************************
  1577. CVideoCaptureDialog::HandleSelectionChange
  1578. <Notes>
  1579. *****************************************************************************/
  1580. VOID
  1581. CVideoCaptureDialog::HandleSelectionChange( VOID )
  1582. {
  1583. CWaitCursor wc;
  1584. INT nSelCount = ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ) );
  1585. INT nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ) );
  1586. //
  1587. // OK should be disabled for 0 items
  1588. //
  1589. MyEnableWindow( GetDlgItem(m_hWnd,IDOK), nSelCount != 0 );
  1590. //
  1591. // Select all should be disabled for 0 items
  1592. //
  1593. MyEnableWindow( GetDlgItem(m_hWnd,IDC_VIDDLG_SELECTALL), nItemCount != 0 );
  1594. }
  1595. /*****************************************************************************
  1596. CVideoCaptureDialog::OnTimer
  1597. Handle WM_TIMER messages
  1598. *****************************************************************************/
  1599. LRESULT
  1600. CVideoCaptureDialog::OnTimer( WPARAM wParam, LPARAM )
  1601. {
  1602. /*
  1603. switch (wParam)
  1604. {
  1605. case IDT_UPDATEPREVIEW:
  1606. {
  1607. KillTimer( m_hWnd, IDT_UPDATEPREVIEW );
  1608. UpdatePreview();
  1609. }
  1610. break;
  1611. }
  1612. */
  1613. return(0);
  1614. }
  1615. /*****************************************************************************
  1616. CVideoCaptureDialog::OnNewItemEvent
  1617. This gets called when get an event from the driver that a new item has
  1618. been created.
  1619. *****************************************************************************/
  1620. LRESULT
  1621. CVideoCaptureDialog::OnNewItemEvent( WPARAM, LPARAM lParam )
  1622. {
  1623. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnNewItemEvent")));
  1624. //
  1625. // Make sure we have a valid item name
  1626. //
  1627. BSTR bstrFullItemName = reinterpret_cast<BSTR>(lParam);
  1628. if (!bstrFullItemName)
  1629. {
  1630. WIA_TRACE((TEXT("bstrFullItemName was NULL")));
  1631. return 0;
  1632. }
  1633. //
  1634. // Check to see if the item is already in our list
  1635. //
  1636. CCameraItem *pListItem = m_CameraItemList.Find(bstrFullItemName);
  1637. if (!pListItem)
  1638. {
  1639. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot)
  1640. {
  1641. WIA_TRACE((TEXT("Finding new item in device")));
  1642. //
  1643. // Get an IWiaItem ptr to new item
  1644. //
  1645. CComPtr<IWiaItem> pItem;
  1646. HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->FindItemByName(0,bstrFullItemName,&pItem);
  1647. WIA_CHECK_HR(hr,"pWiaItemRoot->FindItemByName()");
  1648. if (SUCCEEDED(hr) && pItem)
  1649. {
  1650. //
  1651. // Add the item to the list
  1652. //
  1653. AddItemToListView( pItem );
  1654. //
  1655. // Make sure we update controls' states
  1656. //
  1657. HandleSelectionChange();
  1658. }
  1659. else
  1660. {
  1661. WIA_ERROR((TEXT("FindItemByName returned NULL pItem")));
  1662. }
  1663. }
  1664. else
  1665. {
  1666. WIA_ERROR((TEXT("m_pDeviceDialogData or m_pDeviceDialogData->pIWiaItemRoot were NULL")));
  1667. }
  1668. }
  1669. else
  1670. {
  1671. WIA_TRACE((TEXT("We found the item is already in our list, doing nothing")));
  1672. }
  1673. //
  1674. // Free the item name
  1675. //
  1676. SysFreeString(bstrFullItemName);
  1677. return HANDLED_THREAD_MESSAGE;
  1678. }
  1679. /*****************************************************************************
  1680. CVideoCaptureDialog::OnDeleteItemEvent
  1681. This gets called when we get an event from the driver that an item has
  1682. been deleted.
  1683. *****************************************************************************/
  1684. LRESULT
  1685. CVideoCaptureDialog::OnDeleteItemEvent( WPARAM, LPARAM lParam )
  1686. {
  1687. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDeleteItemEvent")));
  1688. CSimpleBStr bstrFullItem = reinterpret_cast<BSTR>(lParam);
  1689. SysFreeString( reinterpret_cast<BSTR>(lParam) );
  1690. WIA_TRACE((TEXT("The deleted item is %s"),CSimpleStringConvert::NaturalString(CSimpleStringWide(bstrFullItem)).String()));
  1691. CCameraItem *pDeletedItem = m_CameraItemList.Find(bstrFullItem);
  1692. if (pDeletedItem)
  1693. {
  1694. //
  1695. // If we're deleting the current parent item,
  1696. // select a new one.
  1697. //
  1698. if (pDeletedItem == m_pCurrentParentItem)
  1699. {
  1700. ChangeFolder(m_pCurrentParentItem->Parent());
  1701. }
  1702. int nIndex = FindItemInList(pDeletedItem);
  1703. if (nIndex >= 0)
  1704. {
  1705. //
  1706. // Remove the item from the listview
  1707. //
  1708. ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ),nIndex);
  1709. //
  1710. // Make sure we leave something selected
  1711. //
  1712. if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST )))
  1713. {
  1714. int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_VIDDLG_THUMBNAILLIST ));
  1715. if (nItemCount)
  1716. {
  1717. if (nIndex >= nItemCount)
  1718. {
  1719. nIndex = nItemCount-1;
  1720. }
  1721. SetSelectedListItem(nIndex);
  1722. }
  1723. }
  1724. //
  1725. // Make sure we update controls' states
  1726. //
  1727. HandleSelectionChange();
  1728. }
  1729. else
  1730. {
  1731. WIA_ERROR((TEXT("FindItemInList coulnd't find the item")));
  1732. }
  1733. //
  1734. // Mark the item as deleted.
  1735. //
  1736. pDeletedItem->DeleteState( CCameraItem::Delete_Deleted );
  1737. }
  1738. else
  1739. {
  1740. WIA_ERROR((TEXT("The item could not be found in m_CameraItemList")));
  1741. }
  1742. return HANDLED_THREAD_MESSAGE;
  1743. }
  1744. /*****************************************************************************
  1745. CVideoCaptureDialog::OnDeviceDisconnect
  1746. This gets called when we get an event from the driver that device has
  1747. been disconnected.
  1748. *****************************************************************************/
  1749. LRESULT
  1750. CVideoCaptureDialog::OnDeviceDisconnect( WPARAM, LPARAM )
  1751. {
  1752. WIA_PUSHFUNCTION((TEXT("CVideoCaptureDialog::OnDeviceDisconnect")));
  1753. //
  1754. // Close the dialog with the approriate error
  1755. //
  1756. EndDialog( m_hWnd, WIA_ERROR_OFFLINE );
  1757. return 0;
  1758. }
  1759. /*****************************************************************************
  1760. CVideoCaptureDialog::GetGraphWindowHandle
  1761. Find the window handle of the video window
  1762. *****************************************************************************/
  1763. HWND
  1764. CVideoCaptureDialog::GetGraphWindowHandle(void)
  1765. {
  1766. HWND hWndGraphParent = GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW );
  1767. if (hWndGraphParent)
  1768. {
  1769. return FindWindowEx( hWndGraphParent, NULL, TEXT("VideoRenderer"), NULL );
  1770. }
  1771. return NULL;
  1772. }
  1773. /*****************************************************************************
  1774. CCameraAcquireDialog::OnContextMenu
  1775. Message handler for WM_HELP message
  1776. *****************************************************************************/
  1777. LRESULT
  1778. CVideoCaptureDialog::OnHelp( WPARAM wParam, LPARAM lParam )
  1779. {
  1780. HELPINFO *pHelpInfo = reinterpret_cast<HELPINFO*>(lParam);
  1781. if (pHelpInfo && HELPINFO_WINDOW==pHelpInfo->iContextType && GetGraphWindowHandle()==pHelpInfo->hItemHandle)
  1782. {
  1783. pHelpInfo->hItemHandle = GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW );
  1784. }
  1785. return WiaHelp::HandleWmHelp( wParam, lParam, g_HelpIDs );
  1786. }
  1787. /*****************************************************************************
  1788. CCameraAcquireDialog::OnContextMenu
  1789. Message handler for right-mouse-button click
  1790. *****************************************************************************/
  1791. LRESULT
  1792. CVideoCaptureDialog::OnContextMenu( WPARAM wParam, LPARAM lParam )
  1793. {
  1794. if (GetGraphWindowHandle() == reinterpret_cast<HWND>(wParam))
  1795. {
  1796. wParam = reinterpret_cast<WPARAM>(GetDlgItem( m_hWnd, IDC_VIDDLG_PREVIEW ));
  1797. }
  1798. return WiaHelp::HandleWmContextMenu( wParam, lParam, g_HelpIDs );
  1799. }
  1800. /*****************************************************************************
  1801. CVideoCaptureDialog::DialogProc
  1802. Dialog proc for video capture dialog
  1803. *****************************************************************************/
  1804. INT_PTR PASCAL CVideoCaptureDialog::DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1805. {
  1806. SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CVideoCaptureDialog)
  1807. {
  1808. SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog );
  1809. SC_HANDLE_DIALOG_MESSAGE( WM_SIZE, OnSize );
  1810. SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand );
  1811. SC_HANDLE_DIALOG_MESSAGE( WM_NOTIFY, OnNotify );
  1812. SC_HANDLE_DIALOG_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo );
  1813. SC_HANDLE_DIALOG_MESSAGE( WM_DESTROY, OnDestroy );
  1814. SC_HANDLE_DIALOG_MESSAGE( WM_SHOWWINDOW, OnShow );
  1815. SC_HANDLE_DIALOG_MESSAGE( WM_TIMER, OnTimer );
  1816. SC_HANDLE_DIALOG_MESSAGE( WM_HELP, OnHelp );
  1817. SC_HANDLE_DIALOG_MESSAGE( WM_CONTEXTMENU, OnContextMenu );
  1818. SC_HANDLE_DIALOG_MESSAGE( PWM_POSTINIT, OnPostInit );
  1819. SC_HANDLE_DIALOG_MESSAGE( PWM_CHANGETOPARENT, OnChangeToParent );
  1820. SC_HANDLE_DIALOG_MESSAGE( PWM_THUMBNAILSTATUS, OnThumbnailStatus );
  1821. SC_HANDLE_DIALOG_MESSAGE( VD_NEW_ITEM, OnNewItemEvent );
  1822. SC_HANDLE_DIALOG_MESSAGE( VD_DELETE_ITEM, OnDeleteItemEvent );
  1823. SC_HANDLE_DIALOG_MESSAGE( VD_DEVICE_DISCONNECTED, OnDeviceDisconnect );
  1824. }
  1825. SC_END_DIALOG_MESSAGE_HANDLERS();
  1826. }
  1827. /*****************************************************************************
  1828. CVideoCallback::CVideoCallback
  1829. Constructor for class
  1830. *****************************************************************************/
  1831. CVideoCallback::CVideoCallback()
  1832. : m_cRef(1),
  1833. m_hWnd(NULL)
  1834. {
  1835. WIA_PUSHFUNCTION((TEXT("CVideoCallback::CVideoCallback()")));
  1836. }
  1837. /*****************************************************************************
  1838. CVideoCallback::Initialize
  1839. Let us set which hwnd to notify when events come
  1840. *****************************************************************************/
  1841. STDMETHODIMP
  1842. CVideoCallback::Initialize( HWND hWnd )
  1843. {
  1844. WIA_PUSHFUNCTION((TEXT("CVideoCallback::Initialize()")));
  1845. m_hWnd = hWnd;
  1846. return S_OK;
  1847. }
  1848. /*****************************************************************************
  1849. CVideoCallback::AddRef
  1850. Standard COM
  1851. *****************************************************************************/
  1852. STDMETHODIMP_(ULONG)
  1853. CVideoCallback::AddRef( VOID )
  1854. {
  1855. WIA_PUSHFUNCTION((TEXT("CVideoCallback::AddRef")));
  1856. return(InterlockedIncrement(&m_cRef));
  1857. }
  1858. /*****************************************************************************
  1859. CVideoCallback::Release
  1860. Standard COM
  1861. *****************************************************************************/
  1862. STDMETHODIMP_(ULONG)
  1863. CVideoCallback::Release( VOID )
  1864. {
  1865. WIA_PUSHFUNCTION(TEXT("CVideoCallback::Release"));
  1866. LONG nRefCount = InterlockedDecrement(&m_cRef);
  1867. if (!nRefCount)
  1868. {
  1869. delete this;
  1870. }
  1871. return(nRefCount);
  1872. }
  1873. /*****************************************************************************
  1874. CVideoCallback::QueryInterface
  1875. Standard COM
  1876. *****************************************************************************/
  1877. STDMETHODIMP
  1878. CVideoCallback::QueryInterface( REFIID riid, LPVOID *ppvObject )
  1879. {
  1880. WIA_PUSHFUNCTION((TEXT("CVideoCallback::QueryInterface")));
  1881. HRESULT hr = S_OK;
  1882. if (ppvObject)
  1883. {
  1884. if (IsEqualIID( riid, IID_IUnknown ))
  1885. {
  1886. WIA_TRACE((TEXT("Supported RIID asked for was IID_IUnknown")));
  1887. *ppvObject = static_cast<IUnknown*>(this);
  1888. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1889. }
  1890. else if (IsEqualIID( riid, IID_IWiaEventCallback ))
  1891. {
  1892. WIA_TRACE((TEXT("Supported RIID asked for was IID_IWiaEventCallback")));
  1893. *ppvObject = static_cast<IWiaEventCallback*>(this);
  1894. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1895. }
  1896. else
  1897. {
  1898. WIA_PRINTGUID((riid,TEXT("Unsupported interface!")));
  1899. *ppvObject = NULL;
  1900. hr = E_NOINTERFACE;
  1901. }
  1902. }
  1903. else
  1904. {
  1905. hr = E_INVALIDARG;
  1906. }
  1907. WIA_RETURN_HR(hr);
  1908. }
  1909. /*****************************************************************************
  1910. CVideoCallback::ImageEventCallback
  1911. WIA callback interface for events.
  1912. *****************************************************************************/
  1913. STDMETHODIMP
  1914. CVideoCallback::ImageEventCallback( const GUID *pEventGUID,
  1915. BSTR bstrEventDescription,
  1916. BSTR bstrDeviceID,
  1917. BSTR bstrDeviceDescription,
  1918. DWORD dwDeviceType,
  1919. BSTR bstrFullItemName,
  1920. ULONG *pulEventType,
  1921. ULONG ulReserved)
  1922. {
  1923. WIA_PUSHFUNCTION((TEXT("CVideoCallback::ImageEventCallback")));
  1924. HRESULT hr = S_OK;
  1925. if (pEventGUID)
  1926. {
  1927. if (IsEqualGUID( *pEventGUID, WIA_EVENT_ITEM_CREATED ))
  1928. {
  1929. WIA_TRACE((TEXT("Got WIA_EVENT_ITEM_CREATED")));
  1930. BSTR bstrToSend = SysAllocString( bstrFullItemName );
  1931. LRESULT lRes = SendMessage( m_hWnd, VD_NEW_ITEM, 0, reinterpret_cast<LPARAM>(bstrToSend) );
  1932. if (HANDLED_THREAD_MESSAGE != lRes && bstrToSend)
  1933. {
  1934. SysFreeString( bstrToSend );
  1935. }
  1936. }
  1937. else if (IsEqualGUID( *pEventGUID, WIA_EVENT_ITEM_DELETED ))
  1938. {
  1939. WIA_TRACE((TEXT("Got WIA_EVENT_ITEM_DELETED")));
  1940. BSTR bstrToSend = SysAllocString( bstrFullItemName );
  1941. LRESULT lRes = SendMessage( m_hWnd, VD_DELETE_ITEM, 0, reinterpret_cast<LPARAM>(bstrToSend) );
  1942. if (HANDLED_THREAD_MESSAGE != lRes && bstrToSend)
  1943. {
  1944. SysFreeString( bstrToSend );
  1945. }
  1946. }
  1947. else if (IsEqualGUID( *pEventGUID, WIA_EVENT_DEVICE_DISCONNECTED ))
  1948. {
  1949. PostMessage( m_hWnd, VD_DEVICE_DISCONNECTED, 0, 0 );
  1950. }
  1951. else
  1952. {
  1953. WIA_ERROR((TEXT("Got an event other that what we registered for!")));
  1954. }
  1955. }
  1956. WIA_RETURN_HR(hr);
  1957. }