Leaked source code of windows server 2003
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.

2646 lines
93 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include <windows.h>
  4. #include <wia.h>
  5. #include <wiadef.h>
  6. #include <commctrl.h>
  7. #include <comctrlp.h>
  8. #include <propidl.h>
  9. #include "simstr.h"
  10. #include "camdlg.h"
  11. #include "camdlg.rh"
  12. #include "simcrack.h"
  13. #include "pviewids.h"
  14. #include "dlgunits.h"
  15. #include "miscutil.h"
  16. #include "waitcurs.h"
  17. #include "movewnd.h"
  18. #include "simrect.h"
  19. #include "simbstr.h"
  20. #include "uiexthlp.h"
  21. #include "gwiaevnt.h"
  22. #include "wiacsh.h"
  23. #include "wiadevdp.h"
  24. //
  25. // Thread queue messages
  26. //
  27. #define TQ_DESTROY (WM_USER+1)
  28. #define TQ_GETTHUMBNAIL (WM_USER+2)
  29. #define TQ_GETPREVIEW (WM_USER+3)
  30. #define TQ_DELETEITEM (WM_USER+4)
  31. //
  32. // Control ids
  33. //
  34. #define IDC_TOOLBAR 1112
  35. #define IDC_SIZEBOX 1113
  36. //
  37. // The UI thread will notify us that it took ownership of the data.
  38. // otherwise, it will be deleted in the worker thread
  39. //
  40. #define HANDLED_THREAD_MESSAGE 1000
  41. //
  42. // Help IDs
  43. //
  44. static const DWORD g_HelpIDs[] =
  45. {
  46. IDC_CAMDLG_BIG_TITLE, -1,
  47. IDC_CAMDLG_SUBTITLE, -1,
  48. IDC_TOOLBAR_FRAME, IDH_WIA_BUTTONS,
  49. IDC_TOOLBAR, IDH_WIA_BUTTONS,
  50. IDOK, IDH_WIA_GET_PICS,
  51. IDC_THUMBNAILLIST, IDH_WIA_PIC_LIST,
  52. IDC_YOU_CAN_ALSO, IDH_WIA_VIEW_PIC_INFO,
  53. IDC_CAMDLG_PROPERTIES, IDH_WIA_VIEW_PIC_INFO,
  54. IDC_PREVIEW, IDH_WIA_PREVIEW_DETAIL,
  55. IDC_INNER_PREVIEW_WINDOW, IDH_WIA_PREVIEW_DETAIL,
  56. IDCANCEL, IDH_CANCEL,
  57. 0, 0
  58. };
  59. //
  60. // Update timer
  61. //
  62. #define IDT_UPDATEPREVIEW 1000
  63. #define UPDATE_PREVIEW_DELAY 500
  64. //
  65. // Number of milliseconds between percent display updates
  66. //
  67. #define PERCENT_UPDATE_GRANULARITY 1000
  68. //
  69. // Private messages
  70. //
  71. #define PWM_POSTINIT (WM_USER+1)
  72. #define PWM_CHANGETOPARENT (WM_USER+2)
  73. #define PWM_THUMBNAILSTATUS (WM_USER+3)
  74. #define PWM_PREVIEWSTATUS (WM_USER+4)
  75. #define PWM_PREVIEWPERCENT (WM_USER+5)
  76. #define PWM_ITEMDELETED (WM_USER+6)
  77. #define PWM_WIAEVENT (WM_USER+7)
  78. //
  79. // Thumbnail whitespace: the space in between images and their selection rectangles
  80. // These values were discovered by trail and error. For instance, if you reduce
  81. // c_nAdditionalMarginY to 20, you get really bizarre spacing problems in the list view
  82. // in vertical mode. These values could become invalid in future versions of the listview.
  83. //
  84. static const int c_nAdditionalMarginX = 10;
  85. static const int c_nAdditionalMarginY = 6;
  86. static int c_nMinThumbnailWidth = 90;
  87. static int c_nMinThumbnailHeight = 90;
  88. static int c_nMaxThumbnailWidth = 120;
  89. static int c_nMaxThumbnailHeight = 120;
  90. //
  91. // Button bar button bitmap sizes
  92. //
  93. static const int c_nButtonBitmapSizeX = 16;
  94. static const int c_nButtonBitmapSizeY = 16;
  95. //
  96. // Button bar button sizes
  97. //
  98. static const int c_nButtonSizeX = 300; // Ridiculously large size to compensate for BTNS_AUTOSIZE bug.
  99. static const int c_nButtonSizeY = 16;
  100. //
  101. // Default preview mode list width
  102. //
  103. static const int c_nDefaultListViewWidth = 120;
  104. //
  105. // These defines let me compile with pre-nt5 headers
  106. //
  107. #ifndef BTNS_SEP
  108. #define BTNS_SEP TBSTYLE_SEP
  109. #endif
  110. #ifndef BTNS_BUTTON
  111. #define BTNS_BUTTON TBSTYLE_BUTTON
  112. #endif
  113. #ifndef ListView_SetExtendedListViewStyleEx
  114. #define ListView_SetExtendedListViewStyleEx( h, m, s )
  115. #endif
  116. class CGlobalInterfaceTableThreadMessage : public CNotifyThreadMessage
  117. {
  118. private:
  119. DWORD m_dwGlobalInterfaceTableCookie;
  120. private:
  121. //
  122. // No implementation
  123. //
  124. CGlobalInterfaceTableThreadMessage(void);
  125. CGlobalInterfaceTableThreadMessage &operator=( const CGlobalInterfaceTableThreadMessage & );
  126. CGlobalInterfaceTableThreadMessage( const CGlobalInterfaceTableThreadMessage & );
  127. public:
  128. CGlobalInterfaceTableThreadMessage( int nMessage, HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie )
  129. : CNotifyThreadMessage( nMessage, hWndNotify ),
  130. m_dwGlobalInterfaceTableCookie(dwGlobalInterfaceTableCookie)
  131. {
  132. }
  133. DWORD GlobalInterfaceTableCookie(void) const
  134. {
  135. return(m_dwGlobalInterfaceTableCookie);
  136. }
  137. };
  138. class CThumbnailThreadMessage : public CGlobalInterfaceTableThreadMessage
  139. {
  140. private:
  141. SIZE m_sizeThumb;
  142. private:
  143. //
  144. // No implementation
  145. //
  146. CThumbnailThreadMessage(void);
  147. CThumbnailThreadMessage &operator=( const CThumbnailThreadMessage & );
  148. CThumbnailThreadMessage( const CThumbnailThreadMessage & );
  149. public:
  150. CThumbnailThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, const SIZE &sizeThumb )
  151. : CGlobalInterfaceTableThreadMessage( TQ_GETTHUMBNAIL, hWndNotify, dwGlobalInterfaceTableCookie ),
  152. m_sizeThumb(sizeThumb)
  153. {
  154. }
  155. const SIZE &ThumbSize(void) const
  156. {
  157. return(m_sizeThumb);
  158. }
  159. };
  160. class CDeleteThreadMessage : public CGlobalInterfaceTableThreadMessage
  161. {
  162. private:
  163. //
  164. // No implementation
  165. //
  166. CDeleteThreadMessage(void);
  167. CDeleteThreadMessage &operator=( const CDeleteThreadMessage & );
  168. CDeleteThreadMessage( const CDeleteThreadMessage & );
  169. public:
  170. CDeleteThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie )
  171. : CGlobalInterfaceTableThreadMessage( TQ_DELETEITEM, hWndNotify, dwGlobalInterfaceTableCookie )
  172. {
  173. }
  174. };
  175. class CPreviewThreadMessage : public CGlobalInterfaceTableThreadMessage
  176. {
  177. private:
  178. CSimpleEvent m_CancelEvent;
  179. private:
  180. //
  181. // No implementation
  182. //
  183. CPreviewThreadMessage(void);
  184. CPreviewThreadMessage &operator=( const CPreviewThreadMessage & );
  185. CPreviewThreadMessage( const CPreviewThreadMessage & );
  186. public:
  187. CPreviewThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent )
  188. : CGlobalInterfaceTableThreadMessage( TQ_GETPREVIEW, hWndNotify, dwGlobalInterfaceTableCookie ),
  189. m_CancelEvent(hCancelEvent)
  190. {
  191. }
  192. CSimpleEvent &CancelEvent(void)
  193. {
  194. return(m_CancelEvent);
  195. }
  196. };
  197. BOOL WINAPI CCameraAcquireDialog::OnThreadDestroy( CThreadMessage * )
  198. {
  199. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThreadDestroy"));
  200. return(FALSE);
  201. }
  202. BOOL WINAPI CCameraAcquireDialog::OnThreadDeleteItem( CThreadMessage *pMsg )
  203. {
  204. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThreadDeleteItem"));
  205. CDeleteThreadMessage *pDeleteMsg = (CDeleteThreadMessage *)(pMsg);
  206. if (pDeleteMsg)
  207. {
  208. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  209. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable);
  210. if (SUCCEEDED(hr))
  211. {
  212. CComPtr<IWiaItem> pIWiaItem;
  213. hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pDeleteMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem );
  214. if (SUCCEEDED(hr))
  215. {
  216. hr = WiaUiUtil::DeleteItemAndChildren(pIWiaItem);
  217. WIA_TRACE((TEXT("********************* pIWiaItem->DeleteItem returned %08X"), hr ));
  218. PostMessage( pDeleteMsg->NotifyWindow(), PWM_ITEMDELETED, pDeleteMsg->GlobalInterfaceTableCookie(), SUCCEEDED(hr) );
  219. }
  220. }
  221. }
  222. return(TRUE);
  223. }
  224. class CWiaDataCallback : public IWiaDataCallback
  225. {
  226. private:
  227. ULONG m_cRef;
  228. HWND m_hWndNotify;
  229. DWORD m_dwGlobalInterfaceTableCookie;
  230. CSimpleEvent m_CancelEvent;
  231. DWORD m_dwPreviousTickCount;
  232. int m_nPercentGranularity;
  233. public:
  234. CWiaDataCallback();
  235. ~CWiaDataCallback();
  236. HRESULT _stdcall QueryInterface(const IID&,void**);
  237. ULONG _stdcall AddRef();
  238. ULONG _stdcall Release();
  239. HRESULT _stdcall Initialize( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent );
  240. HRESULT _stdcall BandedDataCallback(
  241. LONG lReason,
  242. LONG lStatus,
  243. LONG lPercentComplete,
  244. LONG lOffset,
  245. LONG lLength,
  246. LONG lReserved,
  247. LONG lResLength,
  248. BYTE *pbBuffer );
  249. };
  250. HRESULT _stdcall CWiaDataCallback::QueryInterface(const IID& iid, void** ppv)
  251. {
  252. *ppv = NULL;
  253. if (iid == IID_IUnknown || iid == IID_IWiaDataCallback)
  254. {
  255. *ppv = (IWiaDataCallback*)this;
  256. }
  257. else
  258. {
  259. return(E_NOINTERFACE);
  260. }
  261. AddRef();
  262. return(S_OK);
  263. }
  264. ULONG _stdcall CWiaDataCallback::AddRef()
  265. {
  266. InterlockedIncrement((long*) &m_cRef);
  267. return(m_cRef);
  268. }
  269. ULONG _stdcall CWiaDataCallback::Release()
  270. {
  271. ULONG ulRefCount = m_cRef - 1;
  272. if (InterlockedDecrement((long*) &m_cRef) == 0)
  273. {
  274. delete this;
  275. return(0);
  276. }
  277. return(ulRefCount);
  278. }
  279. CWiaDataCallback::CWiaDataCallback()
  280. : m_cRef(0),
  281. m_hWndNotify(NULL)
  282. {
  283. }
  284. CWiaDataCallback::~CWiaDataCallback()
  285. {
  286. }
  287. HRESULT _stdcall CWiaDataCallback::Initialize( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent )
  288. {
  289. m_hWndNotify = hWndNotify;
  290. m_dwGlobalInterfaceTableCookie = dwGlobalInterfaceTableCookie;
  291. m_CancelEvent = hCancelEvent;
  292. m_dwPreviousTickCount = 0xFFFFFF;
  293. m_nPercentGranularity = 3;
  294. return(S_OK);
  295. }
  296. HRESULT _stdcall CWiaDataCallback::BandedDataCallback(
  297. LONG lMessage,
  298. LONG lStatus,
  299. LONG lPercentComplete,
  300. LONG lOffset,
  301. LONG lLength,
  302. LONG lReserved,
  303. LONG lResLength,
  304. BYTE * /* pbBuffer */
  305. )
  306. {
  307. WIA_TRACE((TEXT("BandedDataCallback: lMessage: %d, lStatus: %d, lPercentComplete: %d, lOffset: %d, lLength: %d, lReserved: %d, lResLength: %d"), lMessage, lStatus, lPercentComplete, lOffset, lLength, lReserved, lResLength ));
  308. if (m_CancelEvent.Signalled())
  309. return(S_FALSE);
  310. switch (lMessage)
  311. {
  312. case IT_MSG_DATA_HEADER:
  313. {
  314. } // IT_MSG_DATA_HEADER
  315. case IT_MSG_DATA:
  316. {
  317. } // IT_STATUS_TRANSFER_TO_CLIENT
  318. break;
  319. case IT_MSG_STATUS:
  320. {
  321. // Don't send status messages too frequently. Limit to one per PERCENT_UPDATE_GRANULARITY ms
  322. DWORD dwTickCount = GetTickCount();
  323. if ((dwTickCount - m_dwPreviousTickCount >= PERCENT_UPDATE_GRANULARITY) || (m_dwPreviousTickCount > dwTickCount))
  324. {
  325. m_dwPreviousTickCount = dwTickCount;
  326. PostMessage( m_hWndNotify, PWM_PREVIEWPERCENT, (WPARAM)m_dwGlobalInterfaceTableCookie, (LPARAM)MAKELPARAM((WORD)lPercentComplete,(WORD)lStatus));
  327. }
  328. } // IT_MSG_STATUS
  329. break;
  330. case IT_MSG_TERMINATION:
  331. {
  332. } // IT_MSG_TERMINATION
  333. break;
  334. }
  335. return(S_OK);
  336. }
  337. BOOL WINAPI CCameraAcquireDialog::OnGetPreview( CThreadMessage *pMsg )
  338. {
  339. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnGetThumbnail"));
  340. CSimpleStringWide strwImageName(L"");
  341. CPreviewThreadMessage *pPreviewMsg = (CPreviewThreadMessage *)(pMsg);
  342. if (pPreviewMsg)
  343. {
  344. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  345. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable,
  346. NULL,
  347. CLSCTX_INPROC_SERVER,
  348. IID_IGlobalInterfaceTable,
  349. (void **)&pGlobalInterfaceTable);
  350. if (SUCCEEDED(hr))
  351. {
  352. CComPtr<IWiaItem> pIWiaItem;
  353. hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pPreviewMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem );
  354. if (SUCCEEDED(hr))
  355. {
  356. CComPtr<IWiaDataTransfer> pIBandedTran;
  357. WIA_TRACE((TEXT("Preparing to call pIWiaItem->QueryInterface for IID_IWiaDataTransfer")));
  358. hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&pIBandedTran);
  359. if (SUCCEEDED(hr))
  360. {
  361. if (PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_FORMAT, WiaImgFmt_BMP, WIA_IPA_FIRST ) &&
  362. PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_TYMED, TYMED_FILE, WIA_IPA_FIRST ))
  363. {
  364. CWiaDataCallback* pCDataCB = new CWiaDataCallback();
  365. WIA_TRACE((TEXT("Preparing to call pCDataCB->Initialize")));
  366. if (pCDataCB)
  367. {
  368. hr = pCDataCB->Initialize( pPreviewMsg->NotifyWindow(), pPreviewMsg->GlobalInterfaceTableCookie(), pPreviewMsg->CancelEvent().Event() );
  369. if (SUCCEEDED(hr))
  370. {
  371. WIA_TRACE((TEXT("Preparing to call pCDataCB->QueryInterface on IID_IWiaDataCallback")));
  372. CComPtr<IWiaDataCallback> pIWiaDataCallback;
  373. hr = pCDataCB->QueryInterface(IID_IWiaDataCallback,(void **)&pIWiaDataCallback);
  374. if (SUCCEEDED(hr))
  375. {
  376. STGMEDIUM StgMedium;
  377. StgMedium.tymed = TYMED_FILE;
  378. StgMedium.pUnkForRelease = NULL;
  379. StgMedium.hGlobal = NULL;
  380. StgMedium.lpszFileName = NULL;
  381. WIA_TRACE((TEXT("Preparing to call pIBandedTran->ibtGetData")));
  382. hr = pIBandedTran->idtGetData( &StgMedium, pIWiaDataCallback );
  383. if (SUCCEEDED(hr) && S_FALSE != hr)
  384. {
  385. strwImageName = StgMedium.lpszFileName;
  386. WIA_TRACE((TEXT("pIBandedTran->ibtGetData returned %s"),StgMedium.lpszFileName));
  387. }
  388. else
  389. {
  390. WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, ibtGetData failed")));
  391. }
  392. //
  393. // Prevent leaks by freeing the filename. We don't call ReleaseStgMeduim, because
  394. // it deletes the file as well.
  395. //
  396. if (SUCCEEDED(hr) && StgMedium.lpszFileName)
  397. {
  398. CoTaskMemFree(StgMedium.lpszFileName);
  399. }
  400. }
  401. else
  402. {
  403. WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, QI of IID_IWiaDataCallback failed")));
  404. }
  405. }
  406. else
  407. {
  408. WIA_PRINTHRESULT((hr,TEXT("pCDataCB->Initialize failed")));
  409. }
  410. }
  411. else
  412. {
  413. WIA_ERROR((TEXT("CCameraAcquireDialog::OnGetPreview, new on CWiaDataCallback failed")));
  414. }
  415. }
  416. else
  417. {
  418. hr = MAKE_HRESULT(3,FACILITY_WIN32,ERROR_INVALID_DATA);
  419. WIA_ERROR((TEXT("SetProperty on TYMED or FORMAT failed")));
  420. }
  421. }
  422. else
  423. {
  424. WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, QI of IID_IWiaDataTransfer failed")));
  425. }
  426. WIA_TRACE((TEXT("End CCameraAcquireDialog::OnGetPreviewBandedTransfer")));
  427. }
  428. }
  429. //
  430. // Allocate the filename string to return to the UI thread
  431. //
  432. CSimpleString *pstrDibFilename = new CSimpleString( CSimpleStringConvert::NaturalString(strwImageName) );
  433. //
  434. // Send the message to the UI thread
  435. //
  436. LRESULT lRes = SendMessage( pPreviewMsg->NotifyWindow(), PWM_PREVIEWSTATUS, pPreviewMsg->GlobalInterfaceTableCookie(), reinterpret_cast<LPARAM>(pstrDibFilename));
  437. //
  438. // If it fails for any reason, we will clean up to avoid leaks and orphaned temp files
  439. //
  440. if (HANDLED_THREAD_MESSAGE != lRes)
  441. {
  442. DeleteFile(CSimpleStringConvert::NaturalString(strwImageName));
  443. if (pstrDibFilename)
  444. {
  445. delete pstrDibFilename;
  446. }
  447. }
  448. }
  449. return(TRUE);
  450. }
  451. BOOL WINAPI CCameraAcquireDialog::OnGetThumbnail( CThreadMessage *pMsg )
  452. {
  453. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnGetThumbnail"));
  454. HBITMAP hBmpThumbnail = NULL;
  455. CThumbnailThreadMessage *pThumbMsg = (CThumbnailThreadMessage *)(pMsg);
  456. if (pThumbMsg)
  457. {
  458. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  459. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable,
  460. NULL,
  461. CLSCTX_INPROC_SERVER,
  462. IID_IGlobalInterfaceTable,
  463. (void **)&pGlobalInterfaceTable);
  464. if (SUCCEEDED(hr))
  465. {
  466. CComPtr<IWiaItem> pIWiaItem;
  467. hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pThumbMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem );
  468. if (SUCCEEDED(hr))
  469. {
  470. #if defined(DBG)
  471. CSimpleStringWide strItemName;
  472. PropStorageHelpers::GetProperty( pIWiaItem, WIA_IPA_FULL_ITEM_NAME, strItemName );
  473. WIA_TRACE((TEXT("Getting thumbnail for %ws (0x%d, 0x%p)"), strItemName.String(), pThumbMsg->GlobalInterfaceTableCookie(), pIWiaItem.p ));
  474. #endif
  475. CComPtr<IWiaPropertyStorage> pIWiaPropertyStorage;
  476. hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage);
  477. if (SUCCEEDED(hr))
  478. {
  479. PROPVARIANT PropVar[3];
  480. PROPSPEC PropSpec[3];
  481. PropSpec[0].ulKind = PRSPEC_PROPID;
  482. PropSpec[0].propid = WIA_IPC_THUMB_WIDTH;
  483. PropSpec[1].ulKind = PRSPEC_PROPID;
  484. PropSpec[1].propid = WIA_IPC_THUMB_HEIGHT;
  485. PropSpec[2].ulKind = PRSPEC_PROPID;
  486. PropSpec[2].propid = WIA_IPC_THUMBNAIL;
  487. hr = pIWiaPropertyStorage->ReadMultiple(ARRAYSIZE(PropSpec),PropSpec,PropVar );
  488. if (SUCCEEDED(hr))
  489. {
  490. 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));
  491. if ((PropVar[0].vt == VT_I4 || PropVar[0].vt == VT_UI4) &&
  492. (PropVar[1].vt == VT_I4 || PropVar[1].vt == VT_UI4) &&
  493. (PropVar[2].vt == (VT_UI1|VT_VECTOR)))
  494. {
  495. UINT nBitmapDataSize = WiaUiUtil::Align(PropVar[0].ulVal*3,sizeof(DWORD)) * PropVar[1].ulVal;
  496. if (nBitmapDataSize <= PropVar[2].caub.cElems)
  497. {
  498. BITMAPINFO bmi = {0};
  499. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  500. bmi.bmiHeader.biWidth = PropVar[0].ulVal;
  501. bmi.bmiHeader.biHeight = PropVar[1].ulVal;
  502. bmi.bmiHeader.biPlanes = 1;
  503. bmi.bmiHeader.biBitCount = 24;
  504. bmi.bmiHeader.biCompression = BI_RGB;
  505. bmi.bmiHeader.biSizeImage = 0;
  506. bmi.bmiHeader.biXPelsPerMeter = 0;
  507. bmi.bmiHeader.biYPelsPerMeter = 0;
  508. bmi.bmiHeader.biClrUsed = 0;
  509. bmi.bmiHeader.biClrImportant = 0;
  510. HDC hDC = GetDC(NULL);
  511. if (hDC)
  512. {
  513. PBYTE *pBits;
  514. HBITMAP hDibSection = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (PVOID*)&pBits, NULL, 0 );
  515. if (hDibSection)
  516. {
  517. WIA_TRACE((TEXT("pBits: 0x%p, PropVar[2].caub.pElems: 0x%p, PropVar[2].caub.cElems: %d"), pBits, PropVar[2].caub.pElems, PropVar[2].caub.cElems));
  518. CopyMemory( pBits, PropVar[2].caub.pElems, nBitmapDataSize );
  519. hr = ScaleImage( hDC, hDibSection, hBmpThumbnail, pThumbMsg->ThumbSize());
  520. if (SUCCEEDED(hr))
  521. {
  522. WIA_TRACE((TEXT("Sending this image (%p) to the notification window: %p"), hBmpThumbnail, pThumbMsg->NotifyWindow() ));
  523. }
  524. else hBmpThumbnail = NULL;
  525. DeleteObject(hDibSection);
  526. }
  527. else
  528. {
  529. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed")));
  530. }
  531. ReleaseDC(NULL,hDC);
  532. }
  533. else
  534. {
  535. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("GetDC failed")));
  536. }
  537. }
  538. else
  539. {
  540. WIA_ERROR((TEXT("nBitmapDataSize <= PropVar[2].caub.cElems was FALSE (%d, %d)"), nBitmapDataSize, PropVar[2].caub.cElems ));
  541. }
  542. }
  543. PropVariantClear(&PropVar[0]);
  544. PropVariantClear(&PropVar[1]);
  545. PropVariantClear(&PropVar[2]);
  546. }
  547. else
  548. {
  549. WIA_PRINTHRESULT((hr,TEXT("pIWiaPropertyStorage->ReadMultiple failed")));
  550. }
  551. }
  552. else
  553. {
  554. WIA_PRINTHRESULT((hr,TEXT("QueryInterface failed on IID_IWiaPropertyStorage")));
  555. }
  556. }
  557. else
  558. {
  559. WIA_PRINTHRESULT((hr,TEXT("GetInterfaceFromGlobal failed on %08X"), pThumbMsg->GlobalInterfaceTableCookie() ));
  560. }
  561. }
  562. else
  563. {
  564. WIA_PRINTHRESULT((hr,TEXT("CoCreateInstance failed on CLSID_StdGlobalInterfaceTable")));
  565. }
  566. //
  567. // Send the message to the UI thread
  568. //
  569. LRESULT lRes = SendMessage( pThumbMsg->NotifyWindow(), PWM_THUMBNAILSTATUS, (WPARAM)pThumbMsg->GlobalInterfaceTableCookie(), (LPARAM)hBmpThumbnail );
  570. //
  571. // If it fails for any reason, we will clean up to avoid leaks
  572. //
  573. if (HANDLED_THREAD_MESSAGE != lRes)
  574. {
  575. if (hBmpThumbnail)
  576. {
  577. DeleteObject( hBmpThumbnail );
  578. }
  579. }
  580. }
  581. else
  582. {
  583. WIA_ERROR((TEXT("pThumbMsg")));
  584. }
  585. return(TRUE);
  586. }
  587. int CCameraAcquireDialog::FindItemInList( CCameraItem *pItem )
  588. {
  589. WIA_PUSH_FUNCTION((TEXT("CCameraAcquireDialog::FindItemInList( %08X )"), pItem ));
  590. if (pItem)
  591. {
  592. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  593. if (hwndList)
  594. {
  595. for (int i=0;i<ListView_GetItemCount(hwndList);i++)
  596. {
  597. CCameraItem *pCurrItem = GetListItemNode(i);
  598. if (pCurrItem)
  599. {
  600. WIA_TRACE((TEXT("Comparing %08X and %08X [%ws] [%ws]"), pCurrItem, pItem, pCurrItem->FullItemName().String(), pItem->FullItemName().String() ));
  601. if (*pCurrItem == *pItem)
  602. {
  603. return i;
  604. }
  605. }
  606. }
  607. }
  608. }
  609. return(-1);
  610. }
  611. CCameraItem *CCameraAcquireDialog::GetCurrentPreviewItem(void)
  612. {
  613. CSimpleDynamicArray<int> aSelIndices;
  614. GetSelectionIndices(aSelIndices);
  615. if (0 == aSelIndices.Size())
  616. return(NULL);
  617. if (1 == aSelIndices.Size())
  618. return(GetListItemNode(aSelIndices[0]));
  619. return(NULL);
  620. }
  621. bool CCameraAcquireDialog::SetCurrentPreviewImage( const CSimpleString &strFilename, const CSimpleString &strTitle )
  622. {
  623. CWaitCursor wc;
  624. bool bResult = true;
  625. SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_SETTEXT, 0, (LPARAM)strTitle.String() );
  626. SIZE sizeSavedAspectRatio = m_CurrentAspectRatio;
  627. // Set up a reasonable default
  628. m_CurrentAspectRatio.cx = 4;
  629. m_CurrentAspectRatio.cy = 3;
  630. if (strFilename.Length())
  631. {
  632. HBITMAP hBmp = (HBITMAP)LoadImage( g_hInstance, strFilename.String(), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE );
  633. if (hBmp)
  634. {
  635. BITMAP bm;
  636. if (GetObject( hBmp, sizeof(BITMAP), &bm ))
  637. {
  638. m_CurrentAspectRatio.cx = bm.bmWidth;
  639. m_CurrentAspectRatio.cy = bm.bmHeight;
  640. }
  641. }
  642. SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_SETBITMAP, MAKEWPARAM(FALSE,FALSE), (LPARAM)hBmp );
  643. if (memcmp(&sizeSavedAspectRatio,&m_CurrentAspectRatio,sizeof(SIZE)))
  644. ResizeAll();
  645. bResult = (hBmp != NULL);
  646. }
  647. else
  648. {
  649. if (SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_GETBITMAP, 0, 0 ))
  650. SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_SETBITMAP, MAKEWPARAM(FALSE,FALSE), 0 );
  651. if (memcmp(&sizeSavedAspectRatio,&m_CurrentAspectRatio,sizeof(SIZE)))
  652. ResizeAll();
  653. }
  654. InvalidateRect( GetDlgItem( m_hWnd, IDC_PREVIEW ), NULL, FALSE );
  655. UpdateWindow( GetDlgItem( m_hWnd, IDC_PREVIEW ) );
  656. return(bResult);
  657. }
  658. // wParam = GIT cookie
  659. // lParam = nPercent
  660. LRESULT CCameraAcquireDialog::OnPreviewPercent( WPARAM wParam, LPARAM lParam )
  661. {
  662. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnPreviewPercent"));
  663. CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam );
  664. if (pCameraItem)
  665. {
  666. pCameraItem->CurrentPreviewPercentage((int)LOWORD(lParam));
  667. CCameraItem *pCurrSel = GetCurrentPreviewItem();
  668. if (pCameraItem == pCurrSel)
  669. {
  670. UpdatePreview();
  671. }
  672. }
  673. return(0);
  674. }
  675. // wParam = GIT cookie
  676. // lParam = HBITMAP
  677. LRESULT CCameraAcquireDialog::OnPreviewStatus( WPARAM wParam, LPARAM lParam )
  678. {
  679. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnPreviewStatus"));
  680. CSimpleString *pstrFilename = reinterpret_cast<CSimpleString*>(lParam);
  681. if (pstrFilename)
  682. {
  683. CCameraItem *pCameraItem = m_CameraItemList.Find( static_cast<DWORD>(wParam) );
  684. if (pCameraItem)
  685. {
  686. if (!pCameraItem->CancelQueueEvent().Signalled())
  687. {
  688. // If we weren't cancelled, set the filename
  689. pCameraItem->PreviewFileName(*pstrFilename);
  690. }
  691. pCameraItem->CloseCancelEvent();
  692. CCameraItem *pCurrSel = GetCurrentPreviewItem();
  693. if (pCameraItem == pCurrSel)
  694. {
  695. SetCurrentPreviewImage( pCameraItem->PreviewFileName() );
  696. }
  697. }
  698. delete pstrFilename;
  699. }
  700. return HANDLED_THREAD_MESSAGE;
  701. }
  702. LRESULT CCameraAcquireDialog::OnThumbnailStatus( WPARAM wParam, LPARAM lParam )
  703. {
  704. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThumbnailStatus"));
  705. WIA_TRACE((TEXT("Looking for the item with the ID %08X"),wParam));
  706. CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam );
  707. if (pCameraItem)
  708. {
  709. WIA_TRACE((TEXT("Found a CameraItem * (%08X)"),pCameraItem));
  710. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  711. if (hwndList)
  712. {
  713. WIA_TRACE((TEXT("Got the list control")));
  714. HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL );
  715. if (hImageList)
  716. {
  717. WIA_TRACE((TEXT("Got the image list")));
  718. if ((HBITMAP)lParam)
  719. {
  720. WIA_TRACE((TEXT("hBitmap = %p"), lParam));
  721. if (ImageList_Replace( hImageList, pCameraItem->ImageListIndex(), reinterpret_cast<HBITMAP>(lParam), NULL ))
  722. {
  723. WIA_TRACE((TEXT("Replaced the image in the list")));
  724. int nItem = FindItemInList(pCameraItem);
  725. if (nItem >= 0)
  726. {
  727. WIA_TRACE((TEXT("Found the item in the list")));
  728. //
  729. // Set the image to a dummy image
  730. //
  731. LV_ITEM lvItem;
  732. ::ZeroMemory(&lvItem,sizeof(LV_ITEM));
  733. lvItem.iItem = nItem;
  734. lvItem.mask = LVIF_IMAGE;
  735. lvItem.iImage = -1;
  736. ListView_SetItem( hwndList, &lvItem );
  737. //
  738. // Then set the image to the real image
  739. //
  740. ::ZeroMemory(&lvItem,sizeof(LV_ITEM));
  741. lvItem.iItem = nItem;
  742. lvItem.mask = LVIF_IMAGE;
  743. lvItem.iImage = pCameraItem->ImageListIndex();
  744. ListView_SetItem( hwndList, &lvItem );
  745. }
  746. }
  747. }
  748. }
  749. }
  750. }
  751. //
  752. // Clean up the bitmap, regardless of any other failures, to avoid memory leaks
  753. //
  754. HBITMAP hBmpThumb = reinterpret_cast<HBITMAP>(lParam);
  755. if (hBmpThumb)
  756. {
  757. DeleteObject(hBmpThumb);
  758. }
  759. return HANDLED_THREAD_MESSAGE;
  760. }
  761. static CThreadMessageMap g_MsgMap[] =
  762. {
  763. { TQ_DESTROY, CCameraAcquireDialog::OnThreadDestroy },
  764. { TQ_GETTHUMBNAIL, CCameraAcquireDialog::OnGetThumbnail },
  765. { TQ_GETPREVIEW, CCameraAcquireDialog::OnGetPreview },
  766. { TQ_DELETEITEM, CCameraAcquireDialog::OnThreadDeleteItem },
  767. { 0, NULL}
  768. };
  769. //
  770. // Sole constructor
  771. //
  772. CCameraAcquireDialog::CCameraAcquireDialog( HWND hWnd )
  773. : m_hWnd(hWnd),
  774. m_bPreviewActive(false),
  775. m_pCurrentParentItem(NULL),
  776. m_bFirstTime(true),
  777. m_hBackgroundThread(NULL),
  778. m_hBigFont(NULL),
  779. m_nDialogMode(0),
  780. m_hAccelTable(NULL),
  781. m_nListViewWidth(0),
  782. m_hIconLarge(NULL),
  783. m_hIconSmall(NULL),
  784. m_pThreadMessageQueue(NULL),
  785. m_bTakePictureIsSupported(false),
  786. m_ToolbarBitmapInfo( g_hInstance, IDB_TOOLBAR )
  787. {
  788. m_pThreadMessageQueue = new CThreadMessageQueue;
  789. if (m_pThreadMessageQueue)
  790. {
  791. //
  792. // Note that CBackgroundThread takes ownership of m_pThreadMessageQueue, and it doesn't have to be deleted in this thread
  793. //
  794. m_hBackgroundThread = CBackgroundThread::Create( m_pThreadMessageQueue, g_MsgMap, m_CancelEvent.Event(), g_hInstance );
  795. }
  796. m_sizeThumbnails.cx = c_nMaxThumbnailWidth;
  797. m_sizeThumbnails.cy = c_nMaxThumbnailHeight;
  798. m_CurrentAspectRatio.cx = 4;
  799. m_CurrentAspectRatio.cy = 3;
  800. WIA_ASSERT(m_hBackgroundThread != NULL);
  801. }
  802. HWND CCameraAcquireDialog::CreateCameraDialogToolbar(VOID)
  803. {
  804. ToolbarHelper::CButtonDescriptor aSingleSelModeButtons[] =
  805. {
  806. { 0, IDC_ICONMODE, TBSTATE_ENABLED|TBSTATE_CHECKED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_ICONMODE },
  807. { 1, IDC_PREVIEWMODE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_PREVIEWMODE },
  808. { 2, IDC_TAKEPICTURE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, &m_bTakePictureIsSupported, IDS_TAKEPICTURE },
  809. { 4, IDC_DELETE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, false, NULL, IDS_DELETE_SINGULAR }
  810. };
  811. ToolbarHelper::CButtonDescriptor aMultiSelModeButtons[] =
  812. {
  813. { 0, IDC_ICONMODE, TBSTATE_ENABLED|TBSTATE_CHECKED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_ICONMODE },
  814. { 1, IDC_PREVIEWMODE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_PREVIEWMODE },
  815. { 2, IDC_TAKEPICTURE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, &m_bTakePictureIsSupported, IDS_TAKEPICTURE },
  816. { 3, IDC_SELECTALL, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, NULL, IDS_SELECTALL },
  817. { 4, IDC_DELETE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, false, NULL, IDS_DELETE }
  818. };
  819. ToolbarHelper::CButtonDescriptor *pButtonDescriptors = aSingleSelModeButtons;
  820. int nButtonDescriptorCount = ARRAYSIZE(aSingleSelModeButtons);
  821. if (m_nDialogMode & MULTISEL_MODE)
  822. {
  823. pButtonDescriptors = aMultiSelModeButtons;
  824. nButtonDescriptorCount = ARRAYSIZE(aMultiSelModeButtons);
  825. }
  826. return ToolbarHelper::CreateToolbar( m_hWnd, GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ), GetDlgItem( m_hWnd, IDC_TOOLBAR_FRAME ), ToolbarHelper::AlignLeft|ToolbarHelper::AlignTop, IDC_TOOLBAR, m_ToolbarBitmapInfo, pButtonDescriptors, nButtonDescriptorCount );
  827. }
  828. HRESULT CCameraAcquireDialog::EnumerateItems( CCameraItem *pCurrentParent, IEnumWiaItem *pIEnumWiaItem )
  829. {
  830. WIA_PUSHFUNCTION(TEXT("CCameraItemList::EnumerateItems"));
  831. HRESULT hr = E_FAIL;
  832. if (pIEnumWiaItem != NULL)
  833. {
  834. hr = pIEnumWiaItem->Reset();
  835. while (hr == S_OK)
  836. {
  837. CComPtr<IWiaItem> pIWiaItem;
  838. hr = pIEnumWiaItem->Next(1, &pIWiaItem, NULL);
  839. if (hr == S_OK)
  840. {
  841. CCameraItem *pNewCameraItem = new CCameraItem( pIWiaItem );
  842. if (pNewCameraItem && pNewCameraItem->Item())
  843. {
  844. LONG ItemType = 0;
  845. hr = pNewCameraItem->Item()->GetItemType(&ItemType);
  846. if (SUCCEEDED(hr))
  847. {
  848. //
  849. // If it is an image, add it to the list
  850. //
  851. if (ItemType & WiaItemTypeImage)
  852. {
  853. //
  854. // Add it to the list
  855. //
  856. m_CameraItemList.Add( pCurrentParent, pNewCameraItem );
  857. WIA_TRACE((TEXT("Found an image")));
  858. }
  859. //
  860. // If it is a folder, enumerate its child items and recurse
  861. //
  862. else if (ItemType & WiaItemTypeFolder)
  863. {
  864. //
  865. // Add this folder to the list
  866. //
  867. m_CameraItemList.Add( pCurrentParent, pNewCameraItem );
  868. //
  869. // Enumerate the child items
  870. //
  871. CComPtr <IEnumWiaItem> pIEnumChildItem;
  872. if (S_OK == pIWiaItem->EnumChildItems(&pIEnumChildItem))
  873. {
  874. EnumerateItems( pNewCameraItem, pIEnumChildItem );
  875. }
  876. }
  877. else
  878. {
  879. //
  880. // Delete this item, since we didn't add it to the list
  881. //
  882. delete pNewCameraItem;
  883. WIA_TRACE((TEXT("Found something that is NOT an image")));
  884. }
  885. }
  886. }
  887. }
  888. }
  889. }
  890. return hr;
  891. }
  892. HRESULT CCameraAcquireDialog::EnumerateAllCameraItems(void)
  893. {
  894. CComPtr<IEnumWiaItem> pIEnumItem;
  895. HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->EnumChildItems(&pIEnumItem);
  896. if (hr == S_OK)
  897. {
  898. hr = EnumerateItems( NULL, pIEnumItem );
  899. }
  900. return(hr);
  901. }
  902. void CCameraAcquireDialog::OnItemCreatedEvent( CGenericWiaEventHandler::CEventMessage *pEventMessage )
  903. {
  904. //
  905. // Get the listview, which we'll need later
  906. //
  907. HWND hwndListview = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  908. if (hwndListview)
  909. {
  910. //
  911. // Get the image list
  912. //
  913. HIMAGELIST hImageList = ListView_GetImageList( hwndListview, LVSIL_NORMAL );
  914. if (hImageList)
  915. {
  916. //
  917. // Make sure we don't already have this item
  918. //
  919. CCameraItem *pCreatedItem = m_CameraItemList.Find(CSimpleBStr(pEventMessage->FullItemName()));
  920. if (!pCreatedItem)
  921. {
  922. //
  923. // Get the IWiaItem* for this item
  924. //
  925. CComPtr<IWiaItem> pWiaItem;
  926. HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->FindItemByName(0,CSimpleBStr(pEventMessage->FullItemName()).BString(),&pWiaItem);
  927. if (SUCCEEDED(hr) && pWiaItem.p)
  928. {
  929. //
  930. // Create an item wrapper
  931. //
  932. CCameraItem *pNewCameraItem = new CCameraItem( pWiaItem );
  933. if (pNewCameraItem && pNewCameraItem->Item())
  934. {
  935. //
  936. // Add it to the list
  937. //
  938. m_CameraItemList.Add( NULL, pNewCameraItem );
  939. //
  940. // Generate a thumbnail
  941. //
  942. CreateThumbnail( pNewCameraItem, hImageList, false );
  943. //
  944. // If this item is in the current folder, add it to the listview
  945. //
  946. if (m_pCurrentParentItem == pNewCameraItem->Parent())
  947. {
  948. int nListViewCount = ListView_GetItemCount(hwndListview);
  949. //
  950. // Add the item
  951. //
  952. LVITEM lvItem = {0};
  953. lvItem.iItem = nListViewCount;
  954. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  955. lvItem.iImage = pNewCameraItem->ImageListIndex();
  956. lvItem.lParam = reinterpret_cast<LPARAM>(pNewCameraItem);
  957. int nIndex = ListView_InsertItem( hwndListview, &lvItem );
  958. //
  959. // Make sure the new item is visible
  960. //
  961. if (nIndex >= 0)
  962. {
  963. ListView_EnsureVisible( hwndListview, nIndex, FALSE );
  964. }
  965. }
  966. //
  967. // Request a thumbnail from the background thread
  968. //
  969. m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pNewCameraItem->GlobalInterfaceTableCookie(), m_sizeThumbnails ) );
  970. }
  971. }
  972. }
  973. }
  974. }
  975. }
  976. bool CCameraAcquireDialog::PopulateList( CCameraItem *pOldParent )
  977. {
  978. //
  979. // Which item should be selected?
  980. //
  981. int nSelItem = 0;
  982. //
  983. // Get the list view control
  984. //
  985. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  986. if (hwndList)
  987. {
  988. //
  989. // Empty the list
  990. //
  991. ListView_DeleteAllItems( hwndList );
  992. //
  993. // Where to insert the current item
  994. //
  995. int nCurrentItem = 0;
  996. CCameraItem *pCurr;
  997. //
  998. // If this is a child directory...
  999. //
  1000. if (m_pCurrentParentItem)
  1001. {
  1002. //
  1003. // Start adding children
  1004. //
  1005. pCurr = m_pCurrentParentItem->Children();
  1006. //
  1007. // Insert a dummy item that the user can use to switch to the parent directory
  1008. //
  1009. LVITEM lvItem;
  1010. ZeroMemory( &lvItem, sizeof(lvItem) );
  1011. lvItem.iItem = nCurrentItem++;
  1012. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  1013. lvItem.iImage = m_nParentFolderImageListIndex;
  1014. lvItem.lParam = 0;
  1015. ListView_InsertItem( hwndList, &lvItem );
  1016. }
  1017. //
  1018. // Otherwise, we are at the root
  1019. //
  1020. else pCurr = m_CameraItemList.Root();
  1021. //
  1022. // Iterate through this list of images, and add each one
  1023. //
  1024. while (pCurr)
  1025. {
  1026. //
  1027. // If this is the last parent directory, we want it to be selected instead of the first image
  1028. //
  1029. if (pOldParent && *pCurr == *pOldParent)
  1030. {
  1031. nSelItem = nCurrentItem;
  1032. }
  1033. //
  1034. // If this image hasn't been deleted
  1035. //
  1036. if (pCurr->DeleteState() != CCameraItem::Delete_Deleted)
  1037. {
  1038. //
  1039. // Add the item
  1040. //
  1041. LVITEM lvItem = {0};
  1042. lvItem.iItem = nCurrentItem++;
  1043. lvItem.mask = LVIF_IMAGE|LVIF_PARAM;
  1044. lvItem.iImage = pCurr->ImageListIndex();
  1045. lvItem.lParam = reinterpret_cast<LPARAM>(pCurr);
  1046. int nIndex = ListView_InsertItem( hwndList, &lvItem );
  1047. if (nIndex >= 0 && pCurr->DeleteState() == CCameraItem::Delete_Pending)
  1048. {
  1049. MarkItemDeletePending(nIndex,true);
  1050. }
  1051. }
  1052. //
  1053. // Advance
  1054. //
  1055. pCurr = pCurr->Next();
  1056. }
  1057. }
  1058. //
  1059. // If we've not calculated the width of the list in preview mode, attempt to do it
  1060. //
  1061. if (!m_nListViewWidth)
  1062. {
  1063. RECT rcItem;
  1064. if (ListView_GetItemRect( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), 0, &rcItem, LVIR_ICON ))
  1065. {
  1066. m_nListViewWidth = (rcItem.right-rcItem.left) + rcItem.left * 2 + GetSystemMetrics(SM_CXHSCROLL) + c_nAdditionalMarginX;
  1067. }
  1068. }
  1069. //
  1070. // Set the selected item to either the previous directory, or the first image
  1071. //
  1072. SetSelectedListItem(nSelItem);
  1073. return(true);
  1074. }
  1075. void CCameraAcquireDialog::CreateThumbnail( CCameraItem *pCurr, HIMAGELIST hImageList, bool bForce )
  1076. {
  1077. //
  1078. // Make sure we have a valid item
  1079. //
  1080. if (pCurr && (pCurr->ImageListIndex()<0 || bForce))
  1081. {
  1082. //
  1083. // Get the item name
  1084. //
  1085. CSimpleStringWide strItemName;
  1086. PropStorageHelpers::GetProperty( pCurr->Item(), WIA_IPA_ITEM_NAME, strItemName );
  1087. //
  1088. // Create the title for the icon
  1089. //
  1090. CSimpleString strIconTitle;
  1091. if (pCurr->IsFolder())
  1092. {
  1093. strIconTitle = CSimpleStringConvert::NaturalString(strItemName);
  1094. }
  1095. else if (strItemName.Length())
  1096. {
  1097. strIconTitle.Format( IDS_DOWNLOADINGTHUMBNAIL, g_hInstance, CSimpleStringConvert::NaturalString(strItemName).String() );
  1098. }
  1099. //
  1100. // Create the thumbnail
  1101. //
  1102. HBITMAP hBmp = WiaUiUtil::CreateIconThumbnail( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, pCurr->IsImage()?IDI_UNAVAILABLE:IDI_FOLDER, strIconTitle );
  1103. if (hBmp)
  1104. {
  1105. //
  1106. // If we don't have an image yet, add it
  1107. //
  1108. if (pCurr->ImageListIndex()<0)
  1109. {
  1110. pCurr->ImageListIndex(ImageList_Add( hImageList, hBmp, NULL ));
  1111. }
  1112. //
  1113. // Otherwise, replace it
  1114. //
  1115. else
  1116. {
  1117. pCurr->ImageListIndex(ImageList_Replace( hImageList, pCurr->ImageListIndex(), hBmp, NULL ));
  1118. }
  1119. //
  1120. // Delete it, since the imagelist makes a copy
  1121. //
  1122. DeleteObject(hBmp);
  1123. }
  1124. }
  1125. }
  1126. void CCameraAcquireDialog::CreateThumbnails( CCameraItem *pRoot, HIMAGELIST hImageList, bool bForce )
  1127. {
  1128. CCameraItem *pCurr = pRoot;
  1129. while (pCurr)
  1130. {
  1131. //
  1132. // Create the thumbnail
  1133. //
  1134. CreateThumbnail( pCurr, hImageList, bForce );
  1135. //
  1136. // If there are children, recurse into that list
  1137. //
  1138. CreateThumbnails( pCurr->Children(), hImageList, bForce );
  1139. //
  1140. // Advance
  1141. //
  1142. pCurr = pCurr->Next();
  1143. }
  1144. }
  1145. void CCameraAcquireDialog::RequestThumbnails( CCameraItem *pRoot )
  1146. {
  1147. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::RequestThumbnails"));
  1148. CCameraItem *pCurr = pRoot;
  1149. while (pCurr)
  1150. {
  1151. if (pCurr->IsImage())
  1152. {
  1153. m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pCurr->GlobalInterfaceTableCookie(), m_sizeThumbnails ) );
  1154. }
  1155. if (pCurr->Children())
  1156. {
  1157. RequestThumbnails( pCurr->Children() );
  1158. }
  1159. pCurr = pCurr->Next();
  1160. }
  1161. }
  1162. void CCameraAcquireDialog::CreateThumbnails( bool bForce )
  1163. {
  1164. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1165. if (hwndList)
  1166. {
  1167. HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL );
  1168. if (hImageList)
  1169. {
  1170. //
  1171. // Create the parent folder image
  1172. //
  1173. HBITMAP hParentBitmap = WiaUiUtil::CreateIconThumbnail( hwndList, m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, IDI_PARENTFOLDER, TEXT("(..)") );
  1174. if (hParentBitmap)
  1175. {
  1176. m_nParentFolderImageListIndex = ImageList_Add( hImageList, hParentBitmap, NULL );
  1177. DeleteObject(hParentBitmap);
  1178. }
  1179. CCameraAcquireDialog::CreateThumbnails( m_CameraItemList.Root(), hImageList, bForce );
  1180. }
  1181. }
  1182. }
  1183. bool CCameraAcquireDialog::FindMaximumThumbnailSize(void)
  1184. {
  1185. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::FindMaximumThumbnailSize"));
  1186. bool bResult = false;
  1187. if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot)
  1188. {
  1189. LONG nWidth, nHeight;
  1190. if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nWidth ) &&
  1191. PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nHeight ))
  1192. {
  1193. m_sizeThumbnails.cx = max(c_nMinThumbnailWidth,min(nWidth,c_nMaxThumbnailWidth));
  1194. m_sizeThumbnails.cy = max(c_nMinThumbnailHeight,min(nHeight,c_nMaxThumbnailHeight));
  1195. }
  1196. else WIA_TRACE((TEXT("FindMaximumThumbnailSize: Unable to retrieve thumbnail size for device")));
  1197. }
  1198. return(bResult && m_sizeThumbnails.cx && m_sizeThumbnails.cy);
  1199. }
  1200. //
  1201. // Hook procedure and static variables used to handle accelerators
  1202. //
  1203. LRESULT CALLBACK CCameraAcquireDialog::DialogHookProc( int nCode, WPARAM wParam, LPARAM lParam )
  1204. {
  1205. if (nCode < 0)
  1206. return CallNextHookEx( s_hMessageHook, nCode, wParam, lParam );
  1207. if (nCode == MSGF_DIALOGBOX)
  1208. {
  1209. MSG *pMsg = reinterpret_cast<MSG*>(lParam);
  1210. if (pMsg)
  1211. {
  1212. if (pMsg->hwnd == s_hWndDialog || (s_hWndDialog && IsChild(s_hWndDialog,pMsg->hwnd)))
  1213. {
  1214. CCameraAcquireDialog *pCameraAcquireDialog = reinterpret_cast<CCameraAcquireDialog*>(GetWindowLongPtr(s_hWndDialog,DWLP_USER));
  1215. if (pCameraAcquireDialog && pCameraAcquireDialog->m_hAccelTable)
  1216. {
  1217. if (TranslateAccelerator(s_hWndDialog,pCameraAcquireDialog->m_hAccelTable,pMsg))
  1218. return 1; // Ensure the window won't process the message
  1219. }
  1220. }
  1221. }
  1222. }
  1223. return CallNextHookEx( s_hMessageHook, nCode, wParam, lParam );
  1224. }
  1225. LRESULT CCameraAcquireDialog::OnInitDialog( WPARAM, LPARAM lParam )
  1226. {
  1227. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnInitDialog"));
  1228. CWaitCursor wc;
  1229. //
  1230. // Make sure the background queue was successfully created
  1231. //
  1232. if (!m_pThreadMessageQueue)
  1233. {
  1234. WIA_ERROR((TEXT("CAMDLG: unable to start background queue")));
  1235. EndDialog( m_hWnd, E_OUTOFMEMORY );
  1236. return(0);
  1237. }
  1238. m_pDeviceDialogData = (PDEVICEDIALOGDATA)lParam;
  1239. // Save the window handle for the hook
  1240. s_hWndDialog = m_hWnd;
  1241. // Install the message hook, which we use for accelerator support
  1242. s_hMessageHook = SetWindowsHookEx( WH_MSGFILTER, DialogHookProc, g_hInstance, GetCurrentThreadId() );
  1243. if (!s_hMessageHook)
  1244. {
  1245. WIA_ERROR((TEXT("CAMDLG: Unable to set thread msg hook")));
  1246. EndDialog( m_hWnd, HRESULT_FROM_WIN32(GetLastError()));
  1247. return(0);
  1248. }
  1249. // Make sure we have valid arguments
  1250. if (!m_pDeviceDialogData)
  1251. {
  1252. WIA_ERROR((TEXT("CAMDLG: Invalid paramater: PDEVICEDIALOGDATA")));
  1253. EndDialog( m_hWnd, E_INVALIDARG );
  1254. return(0);
  1255. }
  1256. // Initialialize our return stuff
  1257. if (m_pDeviceDialogData)
  1258. {
  1259. m_pDeviceDialogData->lItemCount = 0;
  1260. m_pDeviceDialogData->ppWiaItems = NULL;
  1261. }
  1262. // Make sure we have valid a valid device
  1263. if (!m_pDeviceDialogData->pIWiaItemRoot)
  1264. {
  1265. WIA_ERROR((TEXT("CAMDLG: Invalid paramaters: pIWiaItem")));
  1266. EndDialog( m_hWnd, E_INVALIDARG );
  1267. return(0);
  1268. }
  1269. //
  1270. // Find out if Take Picture is supported
  1271. //
  1272. m_bTakePictureIsSupported = WiaUiUtil::IsDeviceCommandSupported( m_pDeviceDialogData->pIWiaItemRoot, WIA_CMD_TAKE_PICTURE );
  1273. // Prevent multiple selection
  1274. if (m_pDeviceDialogData->dwFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE)
  1275. {
  1276. LONG_PTR lStyle = GetWindowLongPtr( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), GWL_STYLE );
  1277. SetWindowLongPtr( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), GWL_STYLE, lStyle | LVS_SINGLESEL );
  1278. // Set the single sel titles
  1279. CSimpleString( IDS_TITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ) );
  1280. CSimpleString( IDS_SUBTITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ) );
  1281. CSimpleString( IDS_OK_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) );
  1282. m_nDialogMode = SINGLESEL_MODE;
  1283. }
  1284. else
  1285. {
  1286. // Set the multi sel subtitle
  1287. CSimpleString( IDS_TITLE_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ) );
  1288. CSimpleString( IDS_SUBTITLE_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ) );
  1289. CSimpleString( IDS_OK_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) );
  1290. m_nDialogMode = MULTISEL_MODE;
  1291. }
  1292. // Make the lovely font
  1293. m_hBigFont = WiaUiUtil::CreateFontWithPointSizeFromWindow( GetDlgItem(m_hWnd,IDC_CAMDLG_BIG_TITLE), 14, false, false );
  1294. if (m_hBigFont)
  1295. SendDlgItemMessage( m_hWnd, IDC_CAMDLG_BIG_TITLE, WM_SETFONT, reinterpret_cast<WPARAM>(m_hBigFont), MAKELPARAM(TRUE,0));
  1296. // Create the Tool Bar and resize the dialog to accommodate it
  1297. (void)CreateCameraDialogToolbar();
  1298. // Get the minimum size of the dialog
  1299. RECT rcWindow;
  1300. GetWindowRect( m_hWnd, &rcWindow );
  1301. m_sizeMinimumWindow.cx = rcWindow.right - rcWindow.left;
  1302. m_sizeMinimumWindow.cy = rcWindow.bottom - rcWindow.top;
  1303. // Initialize the preview control
  1304. WiaPreviewControl_AllowNullSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE );
  1305. WiaPreviewControl_ClearSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ) );
  1306. WiaPreviewControl_DisableSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE );
  1307. WiaPreviewControl_SetBorderSize( GetDlgItem( m_hWnd, IDC_PREVIEW ), FALSE, FALSE, 0 );
  1308. WiaPreviewControl_SetBgAlpha( GetDlgItem( m_hWnd, IDC_PREVIEW ), FALSE, 0xFF );
  1309. // Set the lovely title
  1310. CSimpleStringWide strwDeviceName;
  1311. if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DIP_DEV_NAME, strwDeviceName ))
  1312. {
  1313. CSimpleString().Format( IDS_CAMERADLG_TITLE, g_hInstance, strwDeviceName.String() ).SetWindowText( m_hWnd );
  1314. }
  1315. // Create the sizing control
  1316. (void)CreateWindowEx( 0, TEXT("scrollbar"), TEXT(""),
  1317. WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP|WS_CLIPSIBLINGS|SBS_SIZEBOXBOTTOMRIGHTALIGN|SBS_BOTTOMALIGN|WS_GROUP,
  1318. CSimpleRect(m_hWnd).Width()-GetSystemMetrics(SM_CXVSCROLL),
  1319. CSimpleRect(m_hWnd).Height()-GetSystemMetrics(SM_CYHSCROLL),
  1320. GetSystemMetrics(SM_CXVSCROLL),
  1321. GetSystemMetrics(SM_CYHSCROLL),
  1322. m_hWnd, reinterpret_cast<HMENU>(IDC_SIZEBOX),
  1323. g_hInstance, NULL );
  1324. // Reposition all the controls
  1325. ResizeAll();
  1326. // Center the window over its parent
  1327. WiaUiUtil::CenterWindow( m_hWnd, GetParent(m_hWnd) );
  1328. // Get the device icons and set the window icons
  1329. CSimpleStringWide strwDeviceId, strwClassId;
  1330. LONG nDeviceType;
  1331. if (PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_UI_CLSID,strwClassId) &&
  1332. PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,strwDeviceId) &&
  1333. PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_TYPE,nDeviceType))
  1334. {
  1335. //
  1336. // Register for disconnect event
  1337. //
  1338. CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_DEVICE_DISCONNECTED, &m_DisconnectEvent, m_hWnd, PWM_WIAEVENT );
  1339. CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_ITEM_DELETED, &m_DeleteItemEvent, m_hWnd, PWM_WIAEVENT );
  1340. CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_ITEM_CREATED, &m_CreateItemEvent, m_hWnd, PWM_WIAEVENT );
  1341. if (SUCCEEDED(WiaUiExtensionHelper::GetDeviceIcons( CSimpleBStr(strwClassId), nDeviceType, &m_hIconSmall, &m_hIconLarge )))
  1342. {
  1343. if (m_hIconSmall)
  1344. {
  1345. SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(m_hIconSmall) );
  1346. }
  1347. if (m_hIconLarge)
  1348. {
  1349. SendMessage( m_hWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(m_hIconLarge) );
  1350. }
  1351. }
  1352. }
  1353. int nAcceleratorCount = 0;
  1354. ACCEL Accelerators[10];
  1355. //
  1356. // Load the accelerator table resource and convert it to an ACCEL array
  1357. //
  1358. HACCEL hAccel = LoadAccelerators( g_hInstance, MAKEINTRESOURCE(IDR_CAMERA_ACCEL) );
  1359. if (hAccel)
  1360. {
  1361. //
  1362. // Copy the accelerator table to an array of ACCEL
  1363. //
  1364. nAcceleratorCount = CopyAcceleratorTable( hAccel, Accelerators, ARRAYSIZE(Accelerators) );
  1365. //
  1366. // Free the accelerator table
  1367. //
  1368. DestroyAcceleratorTable( hAccel );
  1369. }
  1370. //
  1371. // Create the accelerator table for the toolbar
  1372. //
  1373. nAcceleratorCount += ToolbarHelper::GetButtonBarAccelerators( GetDlgItem( m_hWnd, IDC_TOOLBAR ), Accelerators+nAcceleratorCount, ARRAYSIZE(Accelerators)-nAcceleratorCount );
  1374. if (nAcceleratorCount)
  1375. {
  1376. m_hAccelTable = CreateAcceleratorTable( Accelerators, nAcceleratorCount );
  1377. if (!m_hAccelTable)
  1378. {
  1379. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateAcceleratorTable failed")));
  1380. }
  1381. }
  1382. SetForegroundWindow(m_hWnd);
  1383. //
  1384. // Make sure the listview has the focus
  1385. //
  1386. SetFocus( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) );
  1387. return (TRUE);
  1388. }
  1389. VOID CCameraAcquireDialog::ResizeAll(VOID)
  1390. {
  1391. CSimpleRect rcClient(m_hWnd);
  1392. CMoveWindow mw;
  1393. CDialogUnits dialogUnits(m_hWnd);
  1394. // Resize the big title
  1395. mw.Size( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ),
  1396. rcClient.Width() - dialogUnits.StandardMargin().cx * 2,
  1397. 0,
  1398. CMoveWindow::NO_SIZEY );
  1399. // Resize the subtitle
  1400. mw.Size( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ),
  1401. rcClient.Width() - dialogUnits.StandardMargin().cx * 2,
  1402. 0,
  1403. CMoveWindow::NO_SIZEY );
  1404. int nToolBarHeight = (int)(HIWORD((DWORD)(SendMessage(GetDlgItem( m_hWnd, IDC_TOOLBAR ), TB_GETBUTTONSIZE, 0,0))));
  1405. // Resize the toolbar frame
  1406. mw.Size( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME),
  1407. rcClient.Width() - dialogUnits.StandardMargin().cx * 2,
  1408. nToolBarHeight + 4,
  1409. 0 );
  1410. // Get the dialog's client coordinates of the toolbar frame's client rect
  1411. CSimpleRect rcToolbarFrameInside( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME), CSimpleRect::ClientRect );
  1412. rcToolbarFrameInside = rcToolbarFrameInside.ClientToScreen(GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME));
  1413. rcToolbarFrameInside = rcToolbarFrameInside.ScreenToClient(m_hWnd);
  1414. // Move and resize the toolbar
  1415. mw.SizeMove( GetDlgItem( m_hWnd, IDC_TOOLBAR ),
  1416. rcToolbarFrameInside.left + 2,
  1417. rcToolbarFrameInside.top + 2,
  1418. rcClient.Width() - dialogUnits.StandardMargin().cx * 2 - 4,
  1419. nToolBarHeight,
  1420. 0 );
  1421. // Save the bottom of this control for later
  1422. int nBottomOfToolbarFrame = CSimpleRect( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top + nToolBarHeight + 4;
  1423. // Move the Properties control
  1424. mw.SizeMove( GetDlgItem( m_hWnd, IDC_CAMDLG_PROPERTIES ),
  1425. 0,
  1426. rcClient.Height() - dialogUnits.StandardMargin().cy - dialogUnits.Y(8) + 2,
  1427. dialogUnits.StandardMargin().cx,
  1428. dialogUnits.Y(8) + 2,
  1429. CMoveWindow::NO_MOVEX|CMoveWindow::NO_SIZEX );
  1430. // Move the static text above it
  1431. mw.Move( GetDlgItem( m_hWnd, IDC_YOU_CAN_ALSO ),
  1432. dialogUnits.StandardMargin().cx,
  1433. rcClient.Height() - dialogUnits.StandardMargin().cy - dialogUnits.Y(8) - 2 - dialogUnits.Y(8)
  1434. );
  1435. CSimpleRect rcOK( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect );
  1436. CSimpleRect rcCancel( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect );
  1437. // Move the OK button
  1438. mw.Move( GetDlgItem( m_hWnd, IDOK ),
  1439. rcClient.Width() - dialogUnits.StandardMargin().cx - dialogUnits.StandardButtonMargin().cx - rcCancel.Width() - rcOK.Width(),
  1440. rcClient.Height() - dialogUnits.StandardMargin().cy - rcOK.Height(),
  1441. 0 );
  1442. // Move the cancel button
  1443. mw.Move( GetDlgItem( m_hWnd, IDCANCEL ),
  1444. rcClient.Width() - dialogUnits.StandardMargin().cx - rcCancel.Width(),
  1445. rcClient.Height() - dialogUnits.StandardMargin().cy - rcCancel.Height(),
  1446. 0 );
  1447. // Move the resizing handle
  1448. mw.Move( GetDlgItem( m_hWnd, IDC_SIZEBOX ),
  1449. rcClient.Width() - GetSystemMetrics(SM_CXVSCROLL),
  1450. rcClient.Height() - GetSystemMetrics(SM_CYHSCROLL)
  1451. );
  1452. int nHeightOfBottomControls =
  1453. dialogUnits.Y(8) + 2 + // Highlight control
  1454. dialogUnits.Y(8) + // Static description text
  1455. dialogUnits.StandardMargin().cy; // Top of these controls
  1456. CSimpleRect rcAvailableArea(
  1457. dialogUnits.StandardMargin().cx,
  1458. nBottomOfToolbarFrame + dialogUnits.StandardMargin().cy,
  1459. rcClient.right - dialogUnits.StandardMargin().cx,
  1460. rcClient.bottom - nHeightOfBottomControls - dialogUnits.StandardMargin().cy
  1461. );
  1462. if (m_bPreviewActive)
  1463. {
  1464. // If we've already calculated the actual width of the preview mode list, use it, otherwise use the default
  1465. int nListViewWidth = m_nListViewWidth ? m_nListViewWidth : c_nDefaultListViewWidth;
  1466. // Move the thumbnail list
  1467. mw.SizeMove( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),
  1468. rcAvailableArea.left,
  1469. rcAvailableArea.top,
  1470. nListViewWidth,
  1471. rcAvailableArea.Height()
  1472. );
  1473. // Remove the rect of the list view from the preview area
  1474. rcAvailableArea.left += nListViewWidth + dialogUnits.StandardMargin().cx;
  1475. // Use up the remaining area
  1476. mw.SizeMove( GetDlgItem( m_hWnd, IDC_PREVIEW ),
  1477. rcAvailableArea.left,
  1478. rcAvailableArea.top,
  1479. rcAvailableArea.Width(),
  1480. rcAvailableArea.Height() );
  1481. }
  1482. else
  1483. {
  1484. // Move the thumbnail list
  1485. mw.SizeMove( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),
  1486. rcAvailableArea.left,
  1487. rcAvailableArea.top,
  1488. rcAvailableArea.Width(),
  1489. rcAvailableArea.Height()
  1490. );
  1491. }
  1492. // Explicitly apply the moves, because the toolbar frame doesn't get painted properly
  1493. mw.Apply();
  1494. if (m_bPreviewActive)
  1495. {
  1496. // Show the preview in case it isn't visible
  1497. mw.Show( GetDlgItem( m_hWnd, IDC_PREVIEW ) );
  1498. }
  1499. else
  1500. {
  1501. // Hide the preview in case it is visible
  1502. mw.Hide( GetDlgItem( m_hWnd, IDC_PREVIEW ) );
  1503. }
  1504. //
  1505. // Update the dialog's background to remove any weird stuff left behind
  1506. //
  1507. InvalidateRect( m_hWnd, NULL, FALSE );
  1508. UpdateWindow( m_hWnd );
  1509. }
  1510. LRESULT CCameraAcquireDialog::OnItemDeleted( WPARAM wParam, LPARAM lParam )
  1511. {
  1512. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnItemDeleted"));
  1513. CCameraItem *pDeletedItem = m_CameraItemList.Find((DWORD)wParam);
  1514. if (pDeletedItem)
  1515. {
  1516. BOOL bSuccess = (BOOL)lParam;
  1517. pDeletedItem->DeleteState( bSuccess ? CCameraItem::Delete_Deleted : CCameraItem::Delete_Visible );
  1518. if (pDeletedItem == m_pCurrentParentItem)
  1519. {
  1520. ChangeFolder(m_pCurrentParentItem->Parent());
  1521. }
  1522. int nIndex = FindItemInList(pDeletedItem);
  1523. if (nIndex >= 0)
  1524. {
  1525. if (bSuccess)
  1526. {
  1527. // Remove the item from the list
  1528. ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),nIndex);
  1529. // Make sure we leave something selected
  1530. if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST )))
  1531. {
  1532. int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ));
  1533. if (nItemCount)
  1534. {
  1535. if (nIndex >= nItemCount)
  1536. nIndex = nItemCount-1;
  1537. SetSelectedListItem(nIndex);
  1538. }
  1539. }
  1540. else
  1541. {
  1542. // Make sure we update control's state when the list is empty
  1543. HandleSelectionChange();
  1544. }
  1545. }
  1546. else
  1547. {
  1548. // If the delete failed, remove the deleted state
  1549. MarkItemDeletePending(nIndex,false);
  1550. // Tell the user
  1551. MessageBeep( MB_ICONASTERISK );
  1552. }
  1553. }
  1554. }
  1555. return (0);
  1556. }
  1557. LRESULT CCameraAcquireDialog::OnWiaEvent( WPARAM, LPARAM lParam )
  1558. {
  1559. WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnWiaEvent"));
  1560. CGenericWiaEventHandler::CEventMessage *pEventMessage = reinterpret_cast<CGenericWiaEventHandler::CEventMessage *>(lParam);
  1561. if (pEventMessage)
  1562. {
  1563. if (pEventMessage->EventId() == WIA_EVENT_DEVICE_DISCONNECTED)
  1564. {
  1565. WIA_TRACE((TEXT("Received disconnect event")));
  1566. EndDialog( m_hWnd, WIA_ERROR_OFFLINE );
  1567. }
  1568. else if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED)
  1569. {
  1570. OnItemCreatedEvent( pEventMessage );
  1571. }
  1572. else if (pEventMessage->EventId() == WIA_EVENT_ITEM_DELETED)
  1573. {
  1574. WIA_TRACE((TEXT("Received deleted item event")));
  1575. CCameraItem *pDeletedItem = m_CameraItemList.Find(CSimpleBStr(pEventMessage->FullItemName()));
  1576. if (pDeletedItem)
  1577. {
  1578. //
  1579. // If we're deleting the current parent item,
  1580. // select a new one.
  1581. //
  1582. if (pDeletedItem == m_pCurrentParentItem)
  1583. {
  1584. ChangeFolder(m_pCurrentParentItem->Parent());
  1585. }
  1586. int nIndex = FindItemInList(pDeletedItem);
  1587. if (nIndex >= 0)
  1588. {
  1589. //
  1590. // Remove the item from the listview
  1591. //
  1592. ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),nIndex);
  1593. //
  1594. // Make sure we leave something selected
  1595. //
  1596. if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST )))
  1597. {
  1598. int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ));
  1599. if (nItemCount)
  1600. {
  1601. if (nIndex >= nItemCount)
  1602. {
  1603. nIndex = nItemCount-1;
  1604. }
  1605. SetSelectedListItem(nIndex);
  1606. }
  1607. }
  1608. else
  1609. {
  1610. //
  1611. // Make sure we update control's state when the list is empty
  1612. //
  1613. HandleSelectionChange();
  1614. }
  1615. }
  1616. else
  1617. {
  1618. WIA_ERROR((TEXT("FindItemInList coulnd't find the item")));
  1619. }
  1620. //
  1621. // Mark the item as deleted.
  1622. //
  1623. pDeletedItem->DeleteState( CCameraItem::Delete_Deleted );
  1624. }
  1625. else
  1626. {
  1627. WIA_ERROR((TEXT("The item could not be found in m_CameraItemList")));
  1628. }
  1629. }
  1630. delete pEventMessage;
  1631. }
  1632. return HANDLED_EVENT_MESSAGE;
  1633. }
  1634. LRESULT CCameraAcquireDialog::OnEnterSizeMove( WPARAM, LPARAM )
  1635. {
  1636. SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_ENTERSIZEMOVE, 0, 0 );
  1637. return(0);
  1638. }
  1639. LRESULT CCameraAcquireDialog::OnExitSizeMove( WPARAM, LPARAM )
  1640. {
  1641. SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_EXITSIZEMOVE, 0, 0 );
  1642. return(0);
  1643. }
  1644. LRESULT CCameraAcquireDialog::OnSize( WPARAM, LPARAM )
  1645. {
  1646. ResizeAll();
  1647. return(0);
  1648. }
  1649. LRESULT CCameraAcquireDialog::OnShow( WPARAM, LPARAM )
  1650. {
  1651. if (m_bFirstTime)
  1652. {
  1653. PostMessage( m_hWnd, PWM_POSTINIT, 0, 0 );
  1654. m_bFirstTime = false;
  1655. }
  1656. return(0);
  1657. }
  1658. LRESULT CCameraAcquireDialog::OnGetMinMaxInfo( WPARAM, LPARAM lParam )
  1659. {
  1660. LPMINMAXINFO pMinMaxInfo = (LPMINMAXINFO)lParam;
  1661. pMinMaxInfo->ptMinTrackSize.x = m_sizeMinimumWindow.cx;
  1662. pMinMaxInfo->ptMinTrackSize.y = m_sizeMinimumWindow.cy;
  1663. return(0);
  1664. }
  1665. LRESULT CCameraAcquireDialog::OnDestroy( WPARAM, LPARAM )
  1666. {
  1667. //
  1668. // Get rid of all preview requests
  1669. //
  1670. CancelAllPreviewRequests( m_CameraItemList.Root() );
  1671. //
  1672. // Tell the background thread to destroy itself
  1673. //
  1674. m_pThreadMessageQueue->Enqueue( new CThreadMessage(TQ_DESTROY),CThreadMessageQueue::PriorityUrgent);
  1675. //
  1676. // Set the window icon to NULL
  1677. //
  1678. SendMessage( m_hWnd, WM_SETICON, ICON_BIG, 0 );
  1679. SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, 0 );
  1680. //
  1681. // Clear the image list and list view. This should be unnecessary, but BoundsChecker
  1682. // complains if I don't do it.
  1683. //
  1684. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1685. if (hwndList)
  1686. {
  1687. ListView_DeleteAllItems(hwndList);
  1688. HIMAGELIST hImgList = ListView_SetImageList( hwndList, NULL, LVSIL_NORMAL );
  1689. if (hImgList)
  1690. {
  1691. ImageList_Destroy(hImgList);
  1692. }
  1693. }
  1694. //
  1695. // Delete resources
  1696. //
  1697. if (m_hBigFont)
  1698. {
  1699. DeleteObject(m_hBigFont);
  1700. m_hBigFont = NULL;
  1701. }
  1702. if (m_hImageList)
  1703. {
  1704. m_hImageList = NULL;
  1705. }
  1706. if (m_hAccelTable)
  1707. {
  1708. DestroyAcceleratorTable(m_hAccelTable);
  1709. m_hAccelTable = NULL;
  1710. }
  1711. if (s_hMessageHook)
  1712. {
  1713. UnhookWindowsHookEx(s_hMessageHook);
  1714. s_hMessageHook = NULL;
  1715. }
  1716. if (m_hIconLarge)
  1717. {
  1718. DestroyIcon(m_hIconLarge);
  1719. m_hIconLarge = NULL;
  1720. }
  1721. if (m_hIconSmall)
  1722. {
  1723. DestroyIcon(m_hIconSmall);
  1724. m_hIconSmall = NULL;
  1725. }
  1726. if (m_hBackgroundThread)
  1727. {
  1728. CloseHandle(m_hBackgroundThread);
  1729. m_hBackgroundThread = NULL;
  1730. }
  1731. return(0);
  1732. }
  1733. VOID CCameraAcquireDialog::OnPreviewMode( WPARAM, LPARAM )
  1734. {
  1735. m_bPreviewActive = true;
  1736. SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PREVIEWMODE, MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0) );
  1737. SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_ICONMODE, MAKELONG(TBSTATE_ENABLED,0) );
  1738. ResizeAll();
  1739. UpdatePreview();
  1740. }
  1741. VOID CCameraAcquireDialog::OnTakePicture( WPARAM, LPARAM )
  1742. {
  1743. //
  1744. // Tell the device to snap a picture
  1745. //
  1746. if (m_pDeviceDialogData->pIWiaItemRoot && m_bTakePictureIsSupported)
  1747. {
  1748. CWaitCursor wc;
  1749. CComPtr<IWiaItem> pNewWiaItem;
  1750. m_pDeviceDialogData->pIWiaItemRoot->DeviceCommand(0,&WIA_CMD_TAKE_PICTURE,&pNewWiaItem);
  1751. }
  1752. }
  1753. VOID CCameraAcquireDialog::OnIconMode( WPARAM, LPARAM )
  1754. {
  1755. m_bPreviewActive = false;
  1756. SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_ICONMODE, MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0) );
  1757. SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PREVIEWMODE, MAKELONG(TBSTATE_ENABLED,0) );
  1758. ResizeAll();
  1759. UpdatePreview();
  1760. }
  1761. LRESULT CCameraAcquireDialog::OnPostInit( WPARAM, LPARAM )
  1762. {
  1763. //
  1764. // Create the progress dialog
  1765. //
  1766. CComPtr<IWiaProgressDialog> pWiaProgressDialog;
  1767. HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaProgressDialog, (void**)&pWiaProgressDialog );
  1768. if (SUCCEEDED(hr))
  1769. {
  1770. //
  1771. // Initialize the progress dialog
  1772. //
  1773. pWiaProgressDialog->Create( m_hWnd, WIA_PROGRESSDLG_ANIM_CAMERA_COMMUNICATE|WIA_PROGRESSDLG_NO_PROGRESS|WIA_PROGRESSDLG_NO_CANCEL|WIA_PROGRESSDLG_NO_TITLE );
  1774. pWiaProgressDialog->SetTitle( CSimpleStringConvert::WideString(CSimpleString(IDS_CAMDLG_PROGDLG_TITLE,g_hInstance)));
  1775. pWiaProgressDialog->SetMessage( CSimpleStringConvert::WideString(CSimpleString(IDS_CAMDLG_PROGDLG_MESSAGE,g_hInstance)));
  1776. //
  1777. // Show the progress dialog
  1778. //
  1779. pWiaProgressDialog->Show();
  1780. //
  1781. // Find all of the images in the camera
  1782. //
  1783. EnumerateAllCameraItems();
  1784. //
  1785. // Find the largest possible thumbnail
  1786. //
  1787. FindMaximumThumbnailSize();
  1788. //
  1789. // Initialize Thumbnail Listview control
  1790. //
  1791. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1792. if (hwndList)
  1793. {
  1794. //
  1795. // Get rid of the border and icon labels
  1796. //
  1797. ListView_SetExtendedListViewStyleEx( hwndList, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_DOUBLEBUFFER, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_DOUBLEBUFFER );
  1798. //
  1799. // Create the large image list
  1800. //
  1801. m_hImageList = ImageList_Create( m_sizeThumbnails.cx, m_sizeThumbnails.cy, ILC_COLOR24|ILC_MIRROR, 50, 50 );
  1802. if (m_hImageList)
  1803. {
  1804. //
  1805. // Set the image list
  1806. //
  1807. ListView_SetImageList( hwndList, m_hImageList, LVSIL_NORMAL );
  1808. }
  1809. //
  1810. // Set the icon spacing
  1811. //
  1812. ListView_SetIconSpacing( hwndList, m_sizeThumbnails.cx + c_nAdditionalMarginX, m_sizeThumbnails.cy + c_nAdditionalMarginY );
  1813. }
  1814. //
  1815. // Create all of the initial thumbnails
  1816. //
  1817. CreateThumbnails();
  1818. //
  1819. // This causes the list to be populated
  1820. //
  1821. ChangeFolder(NULL);
  1822. //
  1823. // Force a selection change
  1824. //
  1825. HandleSelectionChange();
  1826. //
  1827. // Download all of the thumbnails
  1828. //
  1829. RequestThumbnails( m_CameraItemList.Root() );
  1830. //
  1831. // Close the progress dialog
  1832. //
  1833. pWiaProgressDialog->Destroy();
  1834. }
  1835. return(0);
  1836. }
  1837. LRESULT CCameraAcquireDialog::OnChangeToParent( WPARAM, LPARAM )
  1838. {
  1839. if (m_pCurrentParentItem)
  1840. ChangeFolder(m_pCurrentParentItem->Parent());
  1841. return(0);
  1842. }
  1843. VOID CCameraAcquireDialog::OnParentDir( WPARAM, LPARAM )
  1844. {
  1845. if (m_pCurrentParentItem && m_pCurrentParentItem->Parent())
  1846. ChangeFolder(m_pCurrentParentItem->Parent());
  1847. else ChangeFolder(NULL);
  1848. }
  1849. void CCameraAcquireDialog::MarkItemDeletePending( int nIndex, bool bSet )
  1850. {
  1851. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1852. if (hwndList)
  1853. {
  1854. ListView_SetItemState( hwndList, nIndex, bSet ? LVIS_CUT : 0, LVIS_CUT );
  1855. }
  1856. }
  1857. // Recursively delete items
  1858. void CCameraAcquireDialog::DeleteItem( CCameraItem *pItemNode )
  1859. {
  1860. if (pItemNode)
  1861. {
  1862. CCameraItem *pChild = pItemNode->Children();
  1863. while (pChild)
  1864. {
  1865. DeleteItem(pChild);
  1866. pChild = pChild->Next();
  1867. }
  1868. if (pItemNode->DeleteState() == CCameraItem::Delete_Visible)
  1869. {
  1870. int nIndex = FindItemInList( pItemNode );
  1871. if (nIndex >= 0)
  1872. {
  1873. //
  1874. // Mark it pending in the UI
  1875. //
  1876. MarkItemDeletePending(nIndex,true);
  1877. }
  1878. //
  1879. // Mark it pending
  1880. //
  1881. pItemNode->DeleteState( CCameraItem::Delete_Pending );
  1882. //
  1883. // Fire off the request
  1884. //
  1885. m_pThreadMessageQueue->Enqueue( new CDeleteThreadMessage(m_hWnd, pItemNode->GlobalInterfaceTableCookie()), CThreadMessageQueue::PriorityHigh );
  1886. }
  1887. }
  1888. }
  1889. VOID CCameraAcquireDialog::OnDelete( WPARAM, LPARAM )
  1890. {
  1891. CSimpleDynamicArray<int> aSelIndices;
  1892. if (GetSelectionIndices( aSelIndices ))
  1893. {
  1894. //
  1895. // We only want to show the confirm dialog once
  1896. //
  1897. bool bShowConfirmDialog = true;
  1898. for (int i=0;i<aSelIndices.Size();i++)
  1899. {
  1900. CCameraItem *pItemNode = GetListItemNode(aSelIndices[i]);
  1901. //
  1902. // If we haven't already deleted this image, do so
  1903. //
  1904. if (pItemNode && pItemNode->DeleteState() == CCameraItem::Delete_Visible && pItemNode->ItemRights() & WIA_ITEM_CAN_BE_DELETED)
  1905. {
  1906. if (bShowConfirmDialog)
  1907. {
  1908. bShowConfirmDialog = false;
  1909. if (IDYES!=MessageBox( m_hWnd, CSimpleString( IDS_DELETE_CONFIRM, g_hInstance ), CSimpleString( IDS_DELETE_CONFIRM_TITLE, g_hInstance ), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 ))
  1910. {
  1911. break;
  1912. }
  1913. }
  1914. DeleteItem( pItemNode );
  1915. }
  1916. }
  1917. }
  1918. }
  1919. int CCameraAcquireDialog::GetSelectionIndices( CSimpleDynamicArray<int> &aIndices )
  1920. {
  1921. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1922. if (!hwndList)
  1923. return(0);
  1924. int iCount = ListView_GetItemCount(hwndList);
  1925. for (int i=0;i<iCount;i++)
  1926. if (ListView_GetItemState(hwndList,i,LVIS_SELECTED) & LVIS_SELECTED)
  1927. aIndices.Append(i);
  1928. return(aIndices.Size());
  1929. }
  1930. bool CCameraAcquireDialog::SetSelectedListItem( int nIndex )
  1931. {
  1932. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1933. if (!hwndList)
  1934. return(false);
  1935. int iCount = ListView_GetItemCount(hwndList);
  1936. for (int i=0;i<iCount;i++)
  1937. ListView_SetItemState(hwndList,i,LVIS_SELECTED|LVIS_FOCUSED,0);
  1938. ListView_SetItemState(hwndList,nIndex,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);
  1939. ListView_EnsureVisible(hwndList,nIndex,FALSE);
  1940. return(true);
  1941. }
  1942. CCameraItem *CCameraAcquireDialog::GetListItemNode( int nIndex )
  1943. {
  1944. HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST );
  1945. if (!hwndList)
  1946. return(NULL);
  1947. LV_ITEM lvItem;
  1948. ::ZeroMemory(&lvItem,sizeof(LV_ITEM));
  1949. lvItem.mask = LVIF_PARAM;
  1950. lvItem.iItem = nIndex;
  1951. if (!ListView_GetItem( hwndList, &lvItem ))
  1952. return(NULL);
  1953. return((CCameraItem *)lvItem.lParam);
  1954. }
  1955. bool CCameraAcquireDialog::ChangeFolder( CCameraItem *pNode )
  1956. {
  1957. CCameraItem *pOldParent = m_pCurrentParentItem;
  1958. m_pCurrentParentItem = pNode;
  1959. return(PopulateList(pOldParent));
  1960. }
  1961. bool CCameraAcquireDialog::ChangeToSelectedFolder(void)
  1962. {
  1963. CSimpleDynamicArray<int> aSelIndices;
  1964. if (GetSelectionIndices(aSelIndices))
  1965. {
  1966. //
  1967. // Find out if only folders are selected
  1968. //
  1969. bool bOnlyFoldersSelected = true;
  1970. for (int i=0;i<aSelIndices.Size();i++)
  1971. {
  1972. CCameraItem *pItemNode = GetListItemNode(aSelIndices[i]);
  1973. if (pItemNode && !pItemNode->IsFolder())
  1974. {
  1975. bOnlyFoldersSelected = false;
  1976. break;
  1977. }
  1978. }
  1979. WIA_TRACE((TEXT("bOnlyFoldersSelected = %d"),bOnlyFoldersSelected));
  1980. //
  1981. // If only folders are selected, switch to the first selected folder
  1982. //
  1983. if (bOnlyFoldersSelected && aSelIndices.Size())
  1984. {
  1985. CCameraItem *pItemNode = GetListItemNode(aSelIndices[0]);
  1986. if (!pItemNode)
  1987. {
  1988. //
  1989. // NULL item node == parent folder
  1990. //
  1991. SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 );
  1992. return(true);
  1993. }
  1994. if (pItemNode && pItemNode->IsFolder() && pItemNode->DeleteState() == CCameraItem::Delete_Visible)
  1995. {
  1996. if (ChangeFolder(pItemNode))
  1997. {
  1998. return(true);
  1999. }
  2000. }
  2001. }
  2002. }
  2003. return(false);
  2004. }
  2005. VOID CCameraAcquireDialog::OnOK( WPARAM, LPARAM )
  2006. {
  2007. if (!ChangeToSelectedFolder())
  2008. {
  2009. HRESULT hr = S_OK;
  2010. m_pDeviceDialogData->lItemCount = 0;
  2011. m_pDeviceDialogData->ppWiaItems = NULL;
  2012. CSimpleDynamicArray<int> aIndices;
  2013. GetSelectionIndices( aIndices );
  2014. if (aIndices.Size())
  2015. {
  2016. int nArraySizeInBytes = sizeof(IWiaItem*) * aIndices.Size();
  2017. m_pDeviceDialogData->ppWiaItems = (IWiaItem**)CoTaskMemAlloc(nArraySizeInBytes);
  2018. if (m_pDeviceDialogData->ppWiaItems)
  2019. {
  2020. ZeroMemory( m_pDeviceDialogData->ppWiaItems, nArraySizeInBytes );
  2021. int nCurrItem = 0;
  2022. for (int i=0;i<aIndices.Size();i++)
  2023. {
  2024. CCameraItem *pItem = GetListItemNode(aIndices[i]);
  2025. //
  2026. // Add the item to the list if it is both a valid picture item and it hasn't been deleted
  2027. //
  2028. if (pItem && pItem->Item() && pItem->IsImage() && pItem->DeleteState() == CCameraItem::Delete_Visible)
  2029. {
  2030. m_pDeviceDialogData->ppWiaItems[nCurrItem] = pItem->Item();
  2031. m_pDeviceDialogData->ppWiaItems[nCurrItem]->AddRef();
  2032. nCurrItem++;
  2033. }
  2034. }
  2035. m_pDeviceDialogData->lItemCount = nCurrItem;
  2036. }
  2037. else
  2038. {
  2039. // Unable to alloc mem
  2040. hr = E_OUTOFMEMORY;
  2041. }
  2042. }
  2043. else
  2044. {
  2045. return;
  2046. }
  2047. EndDialog( m_hWnd, hr );
  2048. }
  2049. }
  2050. VOID CCameraAcquireDialog::OnCancel( WPARAM, LPARAM )
  2051. {
  2052. EndDialog( m_hWnd, S_FALSE );
  2053. }
  2054. VOID CCameraAcquireDialog::OnSelectAll( WPARAM, LPARAM )
  2055. {
  2056. ListView_SetItemState( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), -1, LVIS_SELECTED, LVIS_SELECTED );
  2057. }
  2058. VOID CCameraAcquireDialog::OnProperties( WPARAM, LPARAM )
  2059. {
  2060. CSimpleDynamicArray<int> aSelIndices;
  2061. if (GetSelectionIndices( aSelIndices ))
  2062. {
  2063. if (aSelIndices.Size() == 1)
  2064. {
  2065. CCameraItem *pItemNode = GetListItemNode(aSelIndices[0]);
  2066. if (pItemNode && pItemNode->Item())
  2067. {
  2068. m_pThreadMessageQueue->Pause();
  2069. HRESULT hr = WiaUiUtil::SystemPropertySheet( g_hInstance, m_hWnd, pItemNode->Item(), CSimpleString( IDS_CAMDLG_PROPERTIES_TITLE, g_hInstance ) );
  2070. if (!SUCCEEDED(hr))
  2071. {
  2072. if (PROP_SHEET_ERROR_NO_PAGES == hr)
  2073. {
  2074. MessageBox( m_hWnd, CSimpleString( IDS_CAMDLG_PROPSHEETNOPAGES, g_hInstance ), CSimpleString( IDS_CAMDLG_ERROR_TITLE, g_hInstance ), MB_ICONINFORMATION );
  2075. }
  2076. else
  2077. {
  2078. MessageBox( m_hWnd, CSimpleString( IDS_CAMDLG_PROPSHEETERROR, g_hInstance ), CSimpleString( IDS_CAMDLG_ERROR_TITLE, g_hInstance ), MB_ICONINFORMATION );
  2079. }
  2080. WIA_PRINTHRESULT((hr,TEXT("SystemPropertySheet failed")));
  2081. }
  2082. m_pThreadMessageQueue->Resume();
  2083. }
  2084. }
  2085. }
  2086. }
  2087. LRESULT CCameraAcquireDialog::OnDblClkImageList( WPARAM, LPARAM )
  2088. {
  2089. SendMessage( m_hWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 );
  2090. return(0);
  2091. }
  2092. void CCameraAcquireDialog::CancelAllPreviewRequests( CCameraItem *pRoot )
  2093. {
  2094. CCameraItem *pCurr = pRoot;
  2095. while (pCurr)
  2096. {
  2097. if (pCurr->PreviewRequestPending())
  2098. pCurr->SetCancelEvent();
  2099. if (pCurr->Children())
  2100. CancelAllPreviewRequests( pCurr->Children() );
  2101. pCurr = pCurr->Next();
  2102. }
  2103. }
  2104. void CCameraAcquireDialog::UpdatePreview(void)
  2105. {
  2106. if (m_bPreviewActive)
  2107. {
  2108. CCameraItem *pCurrPreviewItem = GetCurrentPreviewItem();
  2109. if (pCurrPreviewItem && pCurrPreviewItem->IsImage())
  2110. {
  2111. // If we're not already downloading this preview image...
  2112. if (!pCurrPreviewItem->PreviewRequestPending())
  2113. {
  2114. // Cancel all other preview requests
  2115. CancelAllPreviewRequests( m_CameraItemList.Root() );
  2116. if (pCurrPreviewItem->PreviewFileName().Length())
  2117. {
  2118. // Set the preview if we've got it cached
  2119. SetCurrentPreviewImage( pCurrPreviewItem->PreviewFileName() );
  2120. }
  2121. else
  2122. {
  2123. CSimpleString strPct;
  2124. strPct.Format( IDS_DOWNLOADINGPREVIEW, g_hInstance, 0 );
  2125. // Clear the preview window
  2126. SetCurrentPreviewImage( TEXT(""), strPct );
  2127. // Create our cancel event
  2128. pCurrPreviewItem->CreateCancelEvent();
  2129. // Reset it, just in case
  2130. pCurrPreviewItem->ResetCancelEvent();
  2131. // Make the request
  2132. m_pThreadMessageQueue->Enqueue( new CPreviewThreadMessage( m_hWnd, pCurrPreviewItem->GlobalInterfaceTableCookie(), pCurrPreviewItem->CancelQueueEvent().Event() ), CThreadMessageQueue::PriorityHigh );
  2133. }
  2134. }
  2135. else
  2136. {
  2137. CSimpleString strPct;
  2138. strPct.Format( IDS_DOWNLOADINGPREVIEW, g_hInstance, pCurrPreviewItem->CurrentPreviewPercentage() );
  2139. SetCurrentPreviewImage( TEXT(""), strPct );
  2140. }
  2141. }
  2142. else
  2143. {
  2144. SetCurrentPreviewImage( TEXT("") );
  2145. CancelAllPreviewRequests( m_CameraItemList.Root() );
  2146. }
  2147. }
  2148. else
  2149. {
  2150. CancelAllPreviewRequests( m_CameraItemList.Root() );
  2151. SetCurrentPreviewImage( TEXT("") );
  2152. }
  2153. }
  2154. LRESULT CCameraAcquireDialog::OnTimer( WPARAM wParam, LPARAM )
  2155. {
  2156. switch (wParam)
  2157. {
  2158. case IDT_UPDATEPREVIEW:
  2159. {
  2160. KillTimer( m_hWnd, IDT_UPDATEPREVIEW );
  2161. UpdatePreview();
  2162. }
  2163. break;
  2164. }
  2165. return(0);
  2166. }
  2167. // Avoids unnecessary state changes
  2168. static inline void MyEnableWindow( HWND hWnd, BOOL bEnable )
  2169. {
  2170. if (bEnable && !IsWindowEnabled(hWnd))
  2171. EnableWindow(hWnd,TRUE);
  2172. else if (!bEnable && IsWindowEnabled(hWnd))
  2173. EnableWindow(hWnd,FALSE);
  2174. }
  2175. // Avoids unnecessary state changes
  2176. static inline void MyEnableToolbarButton( HWND hWnd, int nId, BOOL bEnable )
  2177. {
  2178. LRESULT nState = SendMessage( hWnd, TB_GETSTATE, nId, 0 );
  2179. if (nState < 0)
  2180. return;
  2181. if ((nState & TBSTATE_ENABLED) && !bEnable)
  2182. SendMessage( hWnd, TB_ENABLEBUTTON, nId, nState & ~TBSTATE_ENABLED);
  2183. else if (!(nState & TBSTATE_ENABLED) && bEnable)
  2184. SendMessage( hWnd, TB_ENABLEBUTTON, nId, nState | TBSTATE_ENABLED );
  2185. }
  2186. void CCameraAcquireDialog::HandleSelectionChange(void)
  2187. {
  2188. CWaitCursor wc;
  2189. int nSelCount = ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) );
  2190. int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) );
  2191. //
  2192. // Properties should be disabled for multiple items
  2193. // and parent folder icons
  2194. //
  2195. bool bDisableProperties = true;
  2196. if (nSelCount == 1)
  2197. {
  2198. CSimpleDynamicArray<int> aIndices;
  2199. if (CCameraAcquireDialog::GetSelectionIndices( aIndices ))
  2200. {
  2201. if (CCameraAcquireDialog::GetListItemNode( aIndices[0] ))
  2202. {
  2203. bDisableProperties = false;
  2204. }
  2205. }
  2206. }
  2207. MyEnableWindow( GetDlgItem(m_hWnd,IDC_CAMDLG_PROPERTIES), !bDisableProperties );
  2208. // OK should be disabled for 0 items
  2209. MyEnableWindow( GetDlgItem(m_hWnd,IDOK), nSelCount != 0 );
  2210. // Select all should be disabled for 0 items
  2211. MyEnableToolbarButton( GetDlgItem(m_hWnd,IDC_TOOLBAR), IDC_SELECTALL, nItemCount != 0 );
  2212. //
  2213. // Decide whether or not delete should be enabled
  2214. // If any of the selected items are deletable, then delete is enabled
  2215. //
  2216. bool bEnableDelete = false;
  2217. //
  2218. // Get the selected items
  2219. //
  2220. CSimpleDynamicArray<int> aSelIndices;
  2221. if (GetSelectionIndices( aSelIndices ))
  2222. {
  2223. //
  2224. // Loop through all of the selected items. Break out if we find a reason
  2225. // to enable delete.
  2226. //
  2227. for (int i=0;i<aSelIndices.Size() && !bEnableDelete;i++)
  2228. {
  2229. //
  2230. // Get the item
  2231. //
  2232. CCameraItem *pItemNode = GetListItemNode(aSelIndices[i]);
  2233. //
  2234. // If we don't have an item, it is a parent folder
  2235. //
  2236. if (pItemNode)
  2237. {
  2238. //
  2239. // If the access rights include the right to delete items,
  2240. // break out.
  2241. //
  2242. if (pItemNode->ItemRights() & WIA_ITEM_CAN_BE_DELETED)
  2243. {
  2244. //
  2245. // Found one, so we are done.
  2246. //
  2247. bEnableDelete = true;
  2248. break;
  2249. }
  2250. }
  2251. }
  2252. }
  2253. MyEnableToolbarButton( GetDlgItem(m_hWnd,IDC_TOOLBAR), IDC_DELETE, bEnableDelete );
  2254. KillTimer( m_hWnd, IDT_UPDATEPREVIEW );
  2255. SetTimer( m_hWnd, IDT_UPDATEPREVIEW, UPDATE_PREVIEW_DELAY, NULL );
  2256. }
  2257. LRESULT CCameraAcquireDialog::OnImageListItemChanged( WPARAM, LPARAM )
  2258. {
  2259. HandleSelectionChange();
  2260. return(0);
  2261. }
  2262. LRESULT CCameraAcquireDialog::OnImageListKeyDown( WPARAM, LPARAM lParam )
  2263. {
  2264. LPNMLVKEYDOWN pnkd = reinterpret_cast<LPNMLVKEYDOWN>(lParam);
  2265. if (pnkd)
  2266. {
  2267. bool bAlt = ((GetKeyState(VK_MENU) & 0x8000) != 0);
  2268. bool bControl = ((GetKeyState(VK_CONTROL) & 0x8000) != 0);
  2269. bool bShift = ((GetKeyState(VK_SHIFT) & 0x8000) != 0);
  2270. if (VK_LEFT == pnkd->wVKey && bAlt && !bControl && !bShift)
  2271. {
  2272. SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 );
  2273. }
  2274. else if (VK_BACK == pnkd->wVKey && !bAlt && !bControl && !bShift)
  2275. {
  2276. SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 );
  2277. }
  2278. else if (VK_DELETE == pnkd->wVKey)
  2279. {
  2280. SendMessage( m_hWnd, WM_COMMAND, IDC_DELETE, 0 );
  2281. }
  2282. }
  2283. return (0);
  2284. }
  2285. LRESULT CCameraAcquireDialog::OnHelp( WPARAM wParam, LPARAM lParam )
  2286. {
  2287. return WiaHelp::HandleWmHelp( wParam, lParam, g_HelpIDs );
  2288. }
  2289. LRESULT CCameraAcquireDialog::OnContextMenu( WPARAM wParam, LPARAM lParam )
  2290. {
  2291. return WiaHelp::HandleWmContextMenu( wParam, lParam, g_HelpIDs );
  2292. }
  2293. LRESULT CCameraAcquireDialog::OnSysColorChange( WPARAM wParam, LPARAM lParam )
  2294. {
  2295. WiaPreviewControl_SetBkColor( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE, TRUE, GetSysColor(COLOR_WINDOW) );
  2296. WiaPreviewControl_SetBkColor( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE, FALSE, GetSysColor(COLOR_WINDOW) );
  2297. SendDlgItemMessage( m_hWnd, IDC_THUMBNAILLIST, WM_SYSCOLORCHANGE, wParam, lParam );
  2298. SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, WM_SYSCOLORCHANGE, wParam, lParam );
  2299. SendDlgItemMessage( m_hWnd, IDC_CAMDLG_PROPERTIES, WM_SYSCOLORCHANGE, wParam, lParam );
  2300. m_ToolbarBitmapInfo.ReloadAndReplaceBitmap();
  2301. return 0;
  2302. }
  2303. LRESULT CCameraAcquireDialog::OnNotify( WPARAM wParam, LPARAM lParam )
  2304. {
  2305. SC_BEGIN_NOTIFY_MESSAGE_HANDLERS()
  2306. {
  2307. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( NM_DBLCLK, IDC_THUMBNAILLIST, OnDblClkImageList );
  2308. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_ITEMCHANGED, IDC_THUMBNAILLIST, OnImageListItemChanged );
  2309. SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_KEYDOWN, IDC_THUMBNAILLIST, OnImageListKeyDown );
  2310. }
  2311. SC_END_NOTIFY_MESSAGE_HANDLERS();
  2312. }
  2313. // WM_COMMAND Handler
  2314. LRESULT CCameraAcquireDialog::OnCommand( WPARAM wParam, LPARAM lParam )
  2315. {
  2316. SC_BEGIN_COMMAND_HANDLERS()
  2317. {
  2318. SC_HANDLE_COMMAND(IDOK,OnOK);
  2319. SC_HANDLE_COMMAND(IDCANCEL,OnCancel);
  2320. SC_HANDLE_COMMAND(IDC_CAMDLG_PROPERTIES,OnProperties);
  2321. SC_HANDLE_COMMAND(IDC_PREVIEWMODE,OnPreviewMode);
  2322. SC_HANDLE_COMMAND(IDC_TAKEPICTURE,OnTakePicture);
  2323. SC_HANDLE_COMMAND(IDC_ICONMODE,OnIconMode);
  2324. SC_HANDLE_COMMAND(IDC_DELETE,OnDelete);
  2325. SC_HANDLE_COMMAND(IDC_SELECTALL,OnSelectAll);
  2326. }
  2327. SC_END_COMMAND_HANDLERS();
  2328. }
  2329. INT_PTR CALLBACK CCameraAcquireDialog::DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  2330. {
  2331. SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CCameraAcquireDialog)
  2332. {
  2333. SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog );
  2334. SC_HANDLE_DIALOG_MESSAGE( WM_SIZE, OnSize );
  2335. SC_HANDLE_DIALOG_MESSAGE( WM_SHOWWINDOW, OnShow );
  2336. SC_HANDLE_DIALOG_MESSAGE( WM_ENTERSIZEMOVE, OnEnterSizeMove );
  2337. SC_HANDLE_DIALOG_MESSAGE( WM_EXITSIZEMOVE, OnExitSizeMove );
  2338. SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand );
  2339. SC_HANDLE_DIALOG_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo );
  2340. SC_HANDLE_DIALOG_MESSAGE( WM_NOTIFY, OnNotify );
  2341. SC_HANDLE_DIALOG_MESSAGE( WM_DESTROY, OnDestroy );
  2342. SC_HANDLE_DIALOG_MESSAGE( PWM_POSTINIT, OnPostInit );
  2343. SC_HANDLE_DIALOG_MESSAGE( PWM_CHANGETOPARENT, OnChangeToParent );
  2344. SC_HANDLE_DIALOG_MESSAGE( PWM_THUMBNAILSTATUS, OnThumbnailStatus );
  2345. SC_HANDLE_DIALOG_MESSAGE( PWM_PREVIEWSTATUS, OnPreviewStatus );
  2346. SC_HANDLE_DIALOG_MESSAGE( PWM_PREVIEWPERCENT, OnPreviewPercent );
  2347. SC_HANDLE_DIALOG_MESSAGE( PWM_ITEMDELETED, OnItemDeleted );
  2348. SC_HANDLE_DIALOG_MESSAGE( PWM_WIAEVENT, OnWiaEvent );
  2349. SC_HANDLE_DIALOG_MESSAGE( WM_TIMER, OnTimer );
  2350. SC_HANDLE_DIALOG_MESSAGE( WM_HELP, OnHelp );
  2351. SC_HANDLE_DIALOG_MESSAGE( WM_CONTEXTMENU, OnContextMenu );
  2352. SC_HANDLE_DIALOG_MESSAGE( WM_SYSCOLORCHANGE, OnSysColorChange );
  2353. }
  2354. SC_END_DIALOG_MESSAGE_HANDLERS();
  2355. }
  2356. // Static hook-related data
  2357. HWND CCameraAcquireDialog::s_hWndDialog = NULL;
  2358. HHOOK CCameraAcquireDialog::s_hMessageHook = NULL;