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.

1080 lines
31 KiB

  1. #ifndef __WIAITEM_H_INCLUDED
  2. #define __WIAITEM_H_INCLUDED
  3. #include <windows.h>
  4. #include <windowsx.h>
  5. #include <wia.h>
  6. #include <uicommon.h>
  7. #include <itranhlp.h>
  8. #include "pshelper.h"
  9. #include "propstrm.h"
  10. #include "resource.h"
  11. #include "gphelper.h"
  12. #include "wiaffmt.h"
  13. class CWiaItem
  14. {
  15. public:
  16. //
  17. // Used to store the region for the scanner
  18. //
  19. struct CScanRegionSettings
  20. {
  21. SIZE sizeResolution;
  22. POINT ptOrigin;
  23. SIZE sizeExtent;
  24. };
  25. private:
  26. CComPtr<IWiaItem> m_pWiaItem;
  27. DWORD m_dwGlobalInterfaceTableCookie;
  28. bool m_bSelectedForDownload;
  29. HBITMAP m_hBitmapImage;
  30. PBYTE m_pBitmapData;
  31. LONG m_nWidth;
  32. LONG m_nHeight;
  33. LONG m_nBitmapDataLength;
  34. CScanRegionSettings m_ScanRegionSettings;
  35. CPropertyStream m_SavedPropertyStream;
  36. CPropertyStream m_CustomPropertyStream;
  37. bool m_bDeleted;
  38. bool m_bAttemptedThumbnailDownload;
  39. mutable LONG m_nItemType;
  40. CWiaItem *m_pParent;
  41. CWiaItem *m_pChildren;
  42. CWiaItem *m_pNext;
  43. GUID m_guidDefaultFormat;
  44. LONG m_nAccessRights;
  45. LONG m_nImageWidth;
  46. LONG m_nImageHeight;
  47. int m_nRotationAngle;
  48. CSimpleStringWide m_strwFullItemName;
  49. CSimpleStringWide m_strwItemName;
  50. CAnnotationType m_AnnotationType;
  51. CSimpleString m_strDefExt;
  52. private:
  53. // No implementation
  54. CWiaItem(void);
  55. CWiaItem( const CWiaItem & );
  56. CWiaItem &operator=( const CWiaItem & );
  57. public:
  58. explicit CWiaItem( IWiaItem *pWiaItem )
  59. : m_pWiaItem(pWiaItem),
  60. m_dwGlobalInterfaceTableCookie(0),
  61. m_bSelectedForDownload(false),
  62. m_hBitmapImage(NULL),
  63. m_pBitmapData(NULL),
  64. m_nWidth(0),
  65. m_nHeight(0),
  66. m_nBitmapDataLength(0),
  67. m_pParent(NULL),
  68. m_pChildren(NULL),
  69. m_pNext(NULL),
  70. m_guidDefaultFormat(IID_NULL),
  71. m_nRotationAngle(0),
  72. m_nAccessRights(0),
  73. m_nItemType(0),
  74. m_nImageWidth(0),
  75. m_nImageHeight(0),
  76. m_AnnotationType(AnnotationNone),
  77. m_bAttemptedThumbnailDownload(false)
  78. {
  79. WIA_PUSH_FUNCTION((TEXT("CWiaItem::CWiaItem")));
  80. if (m_pWiaItem)
  81. {
  82. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  83. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable );
  84. if (SUCCEEDED(hr))
  85. {
  86. hr = pGlobalInterfaceTable->RegisterInterfaceInGlobal( pWiaItem, IID_IWiaItem, &m_dwGlobalInterfaceTableCookie );
  87. if (SUCCEEDED(hr))
  88. {
  89. WIA_TRACE((TEXT("IGlobalInterfaceTable::RegisterInterfaceInGlobal gave us a cookie of %d"), m_dwGlobalInterfaceTableCookie ));
  90. }
  91. }
  92. //
  93. // NOTE: This is a here to get the item name so we can delete it later
  94. // in response to a delete event, because there is no other way to find an item
  95. // since ReadMultiple will fail after the item is deleted. This is the only item
  96. // property I read on the foreground thread during initialization, unfortunately.
  97. // but i need it immediately. One other awful alternative would be to just walk
  98. // the item tree and call ReadMultiple on each item and prune the ones that return
  99. // WIA_ERROR_ITEM_DELETED in response to delete item event.
  100. //
  101. PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_FULL_ITEM_NAME, m_strwFullItemName );
  102. PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_ITEM_NAME, m_strwItemName );
  103. }
  104. }
  105. ~CWiaItem(void)
  106. {
  107. WIA_PUSH_FUNCTION((TEXT("CWiaItem::~CWiaItem")));
  108. //
  109. // Remove the item from the GIT
  110. //
  111. if (m_pWiaItem)
  112. {
  113. CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
  114. HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable );
  115. if (SUCCEEDED(hr))
  116. {
  117. hr = pGlobalInterfaceTable->RevokeInterfaceFromGlobal( m_dwGlobalInterfaceTableCookie );
  118. if (SUCCEEDED(hr))
  119. {
  120. WIA_TRACE((TEXT("IGlobalInterfaceTable::RevokeInterfaceFromGlobal succeeded on %d"), m_dwGlobalInterfaceTableCookie ));
  121. }
  122. }
  123. }
  124. // Delete the item's Thumbnail
  125. if (m_hBitmapImage)
  126. {
  127. DeleteObject(m_hBitmapImage);
  128. m_hBitmapImage = NULL;
  129. }
  130. //
  131. // Delete the thumbnail data
  132. //
  133. if (m_pBitmapData)
  134. {
  135. LocalFree(m_pBitmapData);
  136. m_pBitmapData = NULL;
  137. }
  138. //
  139. // NULL out all the other members
  140. //
  141. m_pWiaItem = NULL;
  142. m_dwGlobalInterfaceTableCookie = 0;
  143. m_nWidth = m_nHeight = m_nImageWidth = m_nImageHeight = m_nBitmapDataLength = 0;
  144. m_pParent = m_pChildren = m_pNext = NULL;
  145. }
  146. LONG ItemType(void) const
  147. {
  148. //
  149. // If we've already read the item type, don't read it again
  150. //
  151. if (!m_nItemType && m_pWiaItem)
  152. {
  153. (void)m_pWiaItem->GetItemType(&m_nItemType);
  154. }
  155. //
  156. // Return m_nItemType even if IWiaItem::GetItemType fails, because it will still be 0, which
  157. // also works as an error result
  158. //
  159. return m_nItemType;
  160. }
  161. bool Deleted(void) const
  162. {
  163. return m_bDeleted;
  164. }
  165. void MarkDeleted(void)
  166. {
  167. m_bDeleted = true;
  168. m_bSelectedForDownload = false;
  169. }
  170. bool RotationEnabled( bool bAllowUninitializedRotation=false ) const
  171. {
  172. WIA_PUSH_FUNCTION((TEXT("CWiaItem::RotationEnabled(%d)"),bAllowUninitializedRotation));
  173. //
  174. // If this image doesn't have a thumbnail AND we tried to get the thumbnail, don't allow
  175. // rotation even if the caller says it is OK. This image doesn't have a thumbnail
  176. // because it didn't provide one, not because we don't have one yet
  177. //
  178. if (m_bAttemptedThumbnailDownload && !HasThumbnail())
  179. {
  180. return false;
  181. }
  182. //
  183. // If this is an uninitialized image and we are told to allow uninitialized rotation,
  184. // we will allow rotation, which we will discard when the image is initialized.
  185. //
  186. if (bAllowUninitializedRotation && m_guidDefaultFormat==IID_NULL && m_nImageWidth==0 && m_nImageHeight==0)
  187. {
  188. WIA_TRACE((TEXT("Uninitialized image: returning true")));
  189. return true;
  190. }
  191. return WiaUiUtil::CanWiaImageBeSafelyRotated( m_guidDefaultFormat, m_nImageWidth, m_nImageHeight );
  192. }
  193. bool AttemptedThumbnailDownload( bool bAttemptedThumbnailDownload )
  194. {
  195. return (m_bAttemptedThumbnailDownload = bAttemptedThumbnailDownload);
  196. }
  197. bool AttemptedThumbnailDownload() const
  198. {
  199. return m_bAttemptedThumbnailDownload;
  200. }
  201. void DiscardRotationIfNecessary(void)
  202. {
  203. WIA_PUSHFUNCTION(TEXT("CWiaItem::DiscardRotationIfNecessary"));
  204. //
  205. // After the image is initialized, we will discard the rotation angle if it turns out the
  206. // image cannot be rotated
  207. //
  208. if (!RotationEnabled())
  209. {
  210. WIA_TRACE((TEXT("Discarding rotation")));
  211. m_nRotationAngle = 0;
  212. }
  213. }
  214. bool IsValid(void) const
  215. {
  216. return(m_pWiaItem && m_dwGlobalInterfaceTableCookie);
  217. }
  218. CSimpleStringWide FullItemName(void) const
  219. {
  220. return m_strwFullItemName;
  221. }
  222. CSimpleStringWide ItemName(void) const
  223. {
  224. return m_strwItemName;
  225. }
  226. GUID DefaultFormat(void)
  227. {
  228. return m_guidDefaultFormat;
  229. }
  230. void DefaultFormat( const GUID &guidDefaultFormat )
  231. {
  232. m_guidDefaultFormat = guidDefaultFormat;
  233. }
  234. LONG AccessRights(void) const
  235. {
  236. return m_nAccessRights;
  237. }
  238. void AccessRights( LONG nAccessRights )
  239. {
  240. m_nAccessRights = nAccessRights;
  241. }
  242. void Rotate( bool bRight )
  243. {
  244. switch (m_nRotationAngle)
  245. {
  246. case 0:
  247. m_nRotationAngle = bRight ? 90 : 270;
  248. break;
  249. case 90:
  250. m_nRotationAngle = bRight ? 180 : 0;
  251. break;
  252. case 180:
  253. m_nRotationAngle = bRight ? 270 : 90;
  254. break;
  255. case 270:
  256. m_nRotationAngle = bRight ? 0 : 180;
  257. break;
  258. }
  259. }
  260. int Rotation(void) const
  261. {
  262. return m_nRotationAngle;
  263. }
  264. CSimpleString DefExt() const
  265. {
  266. return m_strDefExt;
  267. }
  268. const CSimpleString &DefExt( const CSimpleString &strDefExt )
  269. {
  270. return (m_strDefExt = strDefExt );
  271. }
  272. CScanRegionSettings &ScanRegionSettings(void)
  273. {
  274. return m_ScanRegionSettings;
  275. }
  276. const CScanRegionSettings &ScanRegionSettings(void) const
  277. {
  278. return m_ScanRegionSettings;
  279. }
  280. CPropertyStream &SavedPropertyStream(void)
  281. {
  282. return m_SavedPropertyStream;
  283. }
  284. const CPropertyStream &SavedPropertyStream(void) const
  285. {
  286. return m_SavedPropertyStream;
  287. }
  288. CPropertyStream &CustomPropertyStream(void)
  289. {
  290. return m_CustomPropertyStream;
  291. }
  292. const CPropertyStream &CustomPropertyStream(void) const
  293. {
  294. return m_CustomPropertyStream;
  295. }
  296. bool SelectedForDownload(void) const
  297. {
  298. return m_bSelectedForDownload;
  299. }
  300. bool SelectedForDownload( bool bSelectedForDownload )
  301. {
  302. return(m_bSelectedForDownload = bSelectedForDownload);
  303. }
  304. HBITMAP BitmapImage(void) const
  305. {
  306. return m_hBitmapImage;
  307. }
  308. HBITMAP BitmapImage( HBITMAP hBitmapImage )
  309. {
  310. if (m_hBitmapImage)
  311. {
  312. DeleteObject(m_hBitmapImage);
  313. }
  314. return(m_hBitmapImage = hBitmapImage);
  315. }
  316. PBYTE BitmapData(void) const
  317. {
  318. return m_pBitmapData;
  319. }
  320. PBYTE BitmapData( PBYTE pBitmapData )
  321. {
  322. if (m_pBitmapData)
  323. {
  324. LocalFree(m_pBitmapData);
  325. }
  326. return(m_pBitmapData = pBitmapData);
  327. }
  328. LONG Width(void) const
  329. {
  330. return m_nWidth;
  331. }
  332. LONG Width( LONG nWidth )
  333. {
  334. return (m_nWidth = nWidth);
  335. }
  336. LONG Height(void) const
  337. {
  338. return m_nHeight;
  339. }
  340. LONG Height( LONG nHeight )
  341. {
  342. return (m_nHeight = nHeight);
  343. }
  344. LONG BitmapDataLength(void) const
  345. {
  346. return m_nBitmapDataLength;
  347. }
  348. LONG BitmapDataLength( LONG nBitmapDataLength )
  349. {
  350. return (m_nBitmapDataLength = nBitmapDataLength);
  351. }
  352. LONG ImageWidth(void) const
  353. {
  354. return m_nImageWidth;
  355. }
  356. LONG ImageWidth( LONG nImageWidth )
  357. {
  358. return (m_nImageWidth = nImageWidth);
  359. }
  360. LONG ImageHeight(void) const
  361. {
  362. return m_nImageHeight;
  363. }
  364. LONG ImageHeight( LONG nImageHeight )
  365. {
  366. return (m_nImageHeight = nImageHeight);
  367. }
  368. bool HasThumbnail() const
  369. {
  370. return (m_pBitmapData && m_nWidth && m_nHeight);
  371. }
  372. HBITMAP CreateThumbnailFromBitmapData( HDC hDC )
  373. {
  374. //
  375. // Assume failure
  376. //
  377. HBITMAP hbmpResult = NULL;
  378. //
  379. // If we've already attempted to download this image
  380. //
  381. if (m_bAttemptedThumbnailDownload)
  382. {
  383. //
  384. // Make sure we have good data
  385. //
  386. if (m_pBitmapData && m_nWidth && m_nHeight)
  387. {
  388. //
  389. // Initialize the bitmap info
  390. //
  391. BITMAPINFO BitmapInfo = {0};
  392. BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  393. BitmapInfo.bmiHeader.biWidth = m_nWidth;
  394. BitmapInfo.bmiHeader.biHeight = m_nHeight;
  395. BitmapInfo.bmiHeader.biPlanes = 1;
  396. BitmapInfo.bmiHeader.biBitCount = 24;
  397. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  398. //
  399. // Create the bitmap
  400. //
  401. PBYTE pBits = NULL;
  402. hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 );
  403. if (hbmpResult)
  404. {
  405. //
  406. // Calculate the size of the bitmap data
  407. //
  408. LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight;
  409. //
  410. // Copy the bitmap data to the bitmap. Make sure we use the minimum of the calculated
  411. // and actual length
  412. //
  413. CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) );
  414. }
  415. else
  416. {
  417. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!")));
  418. }
  419. }
  420. }
  421. return hbmpResult;
  422. }
  423. HBITMAP CreateThumbnailBitmap( HWND hWnd, CGdiPlusHelper &GdiPlusHelper, int nSizeX, int nSizeY )
  424. {
  425. //
  426. // Initialize the return value. Assume failure.
  427. //
  428. HBITMAP hThumbnail = NULL;
  429. //
  430. // Only return a bitmap if we've already attempted to download one
  431. //
  432. if (m_bAttemptedThumbnailDownload)
  433. {
  434. //
  435. // Make sure this is a real thumbnail. If not, we will create a fake one below.
  436. //
  437. if (HasThumbnail())
  438. {
  439. //
  440. // Get the client DC
  441. //
  442. HDC hDC = GetDC( hWnd );
  443. if (hDC)
  444. {
  445. //
  446. // Create the bitmap from the raw bitmap data
  447. //
  448. HBITMAP hRawBitmap = CreateThumbnailFromBitmapData( hDC );
  449. if (hRawBitmap)
  450. {
  451. //
  452. // Rotate the thumbnail
  453. //
  454. HBITMAP hRotatedThumbnail = NULL;
  455. if (SUCCEEDED(GdiPlusHelper.Rotate( hRawBitmap, hRotatedThumbnail, Rotation())))
  456. {
  457. //
  458. // Make sure we got a valid rotated thumbnail
  459. //
  460. if (hRotatedThumbnail)
  461. {
  462. //
  463. // Try to scale the image
  464. //
  465. SIZE sizeScaled = {nSizeX,nSizeY};
  466. ScaleImage( hDC, hRotatedThumbnail, hThumbnail, sizeScaled );
  467. //
  468. // Nuke the rotated bitmap
  469. //
  470. DeleteBitmap(hRotatedThumbnail);
  471. }
  472. }
  473. //
  474. // Nuke the raw bitmap
  475. //
  476. DeleteBitmap(hRawBitmap);
  477. }
  478. //
  479. // Release the client DC
  480. //
  481. ReleaseDC( hWnd, hDC );
  482. }
  483. }
  484. else
  485. {
  486. WIA_PRINTGUID((m_guidDefaultFormat,TEXT("m_guidDefaultFormat")));
  487. //
  488. // Create a file format object and load the type icon
  489. //
  490. CWiaFileFormat WiaFileFormat;
  491. WiaFileFormat.Format( m_guidDefaultFormat );
  492. WiaFileFormat.Extension( m_strDefExt );
  493. HICON hIcon = WiaFileFormat.AcquireIcon( NULL, false );
  494. //
  495. // Make sure we have an icon
  496. //
  497. if (hIcon)
  498. {
  499. //
  500. // Create the icon thumbnail with the type icon and the name of the file
  501. //
  502. hThumbnail = WiaUiUtil::CreateIconThumbnail( hWnd, nSizeX, nSizeY, hIcon, CSimpleStringConvert::NaturalString(m_strwItemName) );
  503. WIA_TRACE((TEXT("hThumbnail: %p"),hThumbnail));
  504. //
  505. // Destroy the icon to prevent leaks
  506. //
  507. DestroyIcon(hIcon);
  508. }
  509. else
  510. {
  511. WIA_ERROR((TEXT("Unable to get the icon")));
  512. }
  513. }
  514. }
  515. return hThumbnail;
  516. }
  517. HBITMAP CreateThumbnailBitmap( HDC hDC )
  518. {
  519. //
  520. // Assume failure
  521. //
  522. HBITMAP hbmpResult = NULL;
  523. //
  524. // Make sure we have good data
  525. //
  526. WIA_TRACE((TEXT("m_pBitmapData: %08X, m_nWidth: %d, m_nWidth: %d"), m_pBitmapData, m_nWidth, m_nHeight ));
  527. if (m_pBitmapData && m_nWidth && m_nHeight)
  528. {
  529. //
  530. // Initialize the bitmap info
  531. //
  532. BITMAPINFO BitmapInfo = {0};
  533. BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  534. BitmapInfo.bmiHeader.biWidth = m_nWidth;
  535. BitmapInfo.bmiHeader.biHeight = m_nHeight;
  536. BitmapInfo.bmiHeader.biPlanes = 1;
  537. BitmapInfo.bmiHeader.biBitCount = 24;
  538. BitmapInfo.bmiHeader.biCompression = BI_RGB;
  539. //
  540. // Create the bitmap
  541. //
  542. PBYTE pBits = NULL;
  543. hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 );
  544. if (hbmpResult)
  545. {
  546. LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight;
  547. CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) );
  548. }
  549. else
  550. {
  551. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!")));
  552. }
  553. }
  554. return hbmpResult;
  555. }
  556. IWiaItem *WiaItem(void) const
  557. {
  558. return m_pWiaItem.p;
  559. }
  560. IWiaItem *WiaItem(void)
  561. {
  562. return m_pWiaItem.p;
  563. }
  564. const CWiaItem *Next(void) const
  565. {
  566. return(m_pNext);
  567. }
  568. CWiaItem *Next(void)
  569. {
  570. return(m_pNext);
  571. }
  572. CWiaItem *Next( CWiaItem *pNext )
  573. {
  574. return(m_pNext = pNext);
  575. }
  576. const CWiaItem *Children(void) const
  577. {
  578. return(m_pChildren);
  579. }
  580. CWiaItem *Children(void)
  581. {
  582. return(m_pChildren);
  583. }
  584. CWiaItem *Children( CWiaItem *pChildren )
  585. {
  586. return(m_pChildren = pChildren);
  587. }
  588. const CWiaItem *Parent(void) const
  589. {
  590. return(m_pParent);
  591. }
  592. CWiaItem *Parent(void)
  593. {
  594. return(m_pParent);
  595. }
  596. CWiaItem *Parent( CWiaItem *pParent )
  597. {
  598. return(m_pParent = pParent);
  599. }
  600. DWORD GlobalInterfaceTableCookie(void) const
  601. {
  602. return m_dwGlobalInterfaceTableCookie;
  603. }
  604. bool operator==( const CWiaItem &WiaItem )
  605. {
  606. return(WiaItem.WiaItem() == m_pWiaItem.p);
  607. }
  608. bool operator==( DWORD dwGlobalInterfaceTableCookie )
  609. {
  610. return(dwGlobalInterfaceTableCookie == GlobalInterfaceTableCookie());
  611. }
  612. bool IsDownloadableItemType(void) const
  613. {
  614. LONG nItemType = ItemType();
  615. return ((nItemType & WiaItemTypeImage) || (nItemType & WiaItemTypeVideo));
  616. }
  617. CAnnotationType AnnotationType(void) const
  618. {
  619. return m_AnnotationType;
  620. }
  621. void AnnotationType( CAnnotationType AnnotationType )
  622. {
  623. m_AnnotationType = AnnotationType;
  624. }
  625. };
  626. class CWiaItemList
  627. {
  628. public:
  629. enum CEnumEvent
  630. {
  631. CountingItems, // Recursing tree, counting items. nData == current count
  632. ReadingItemInfo // Recursing tree, reading info. nData == current item
  633. };
  634. typedef bool (*WiaItemEnumerationCallbackFunction)( CEnumEvent EnumEvent, UINT nData, LPARAM lParam, bool bForceUpdate );
  635. private:
  636. CWiaItem *m_pRoot;
  637. private:
  638. // No implementation
  639. CWiaItemList( const CWiaItemList & );
  640. CWiaItemList &operator=( const CWiaItemList & );
  641. public:
  642. CWiaItemList(void)
  643. : m_pRoot(NULL)
  644. {
  645. }
  646. ~CWiaItemList(void)
  647. {
  648. Destroy();
  649. }
  650. void Destroy( CWiaItem *pRoot )
  651. {
  652. while (pRoot)
  653. {
  654. Destroy(pRoot->Children());
  655. CWiaItem *pCurr = pRoot;
  656. pRoot = pRoot->Next();
  657. delete pCurr;
  658. }
  659. }
  660. void Destroy(void)
  661. {
  662. Destroy(m_pRoot);
  663. m_pRoot = NULL;
  664. }
  665. const CWiaItem *Root(void) const
  666. {
  667. return(m_pRoot);
  668. }
  669. CWiaItem *Root(void)
  670. {
  671. return(m_pRoot);
  672. }
  673. CWiaItem *Root( CWiaItem *pRoot )
  674. {
  675. return(m_pRoot = pRoot);
  676. }
  677. int Count( CWiaItem *pFirst )
  678. {
  679. int nCount = 0;
  680. for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next())
  681. {
  682. if (pCurr->IsDownloadableItemType() && !pCurr->Deleted())
  683. nCount++;
  684. nCount += Count(pCurr->Children());
  685. }
  686. return nCount;
  687. }
  688. int Count(void)
  689. {
  690. return Count(m_pRoot);
  691. }
  692. int SelectedForDownloadCount( CWiaItem *pFirst )
  693. {
  694. int nCount = 0;
  695. for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next())
  696. {
  697. if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload())
  698. nCount++;
  699. nCount += SelectedForDownloadCount(pCurr->Children());
  700. }
  701. return nCount;
  702. }
  703. int SelectedForDownloadCount(void)
  704. {
  705. return SelectedForDownloadCount(Root());
  706. }
  707. static CWiaItem *Find( CWiaItem *pRoot, const CWiaItem *pNode )
  708. {
  709. for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
  710. {
  711. if (*pCurr == *pNode)
  712. {
  713. if (!pCurr->Deleted())
  714. {
  715. return pCurr;
  716. }
  717. }
  718. if (pCurr->Children())
  719. {
  720. CWiaItem *pFind = Find( pCurr->Children(), pNode );
  721. if (pFind)
  722. {
  723. return pFind;
  724. }
  725. }
  726. }
  727. return(NULL);
  728. }
  729. CWiaItem *Find( CWiaItem *pNode )
  730. {
  731. return(Find( m_pRoot, pNode ));
  732. }
  733. static CWiaItem *Find( CWiaItem *pRoot, IWiaItem *pItem )
  734. {
  735. for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
  736. {
  737. if (pCurr->WiaItem() == pItem)
  738. {
  739. if (!pCurr->Deleted())
  740. {
  741. return pCurr;
  742. }
  743. }
  744. if (pCurr->Children())
  745. {
  746. CWiaItem *pFind = Find( pCurr->Children(), pItem );
  747. if (pFind)
  748. {
  749. return pFind;
  750. }
  751. }
  752. }
  753. return(NULL);
  754. }
  755. CWiaItem *Find( IWiaItem *pItem )
  756. {
  757. return(Find( m_pRoot, pItem ));
  758. }
  759. static CWiaItem *Find( CWiaItem *pRoot, LPCWSTR pwszFindName )
  760. {
  761. for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
  762. {
  763. if (CSimpleStringConvert::NaturalString(CSimpleStringWide(pwszFindName)) == CSimpleStringConvert::NaturalString(pCurr->FullItemName()))
  764. {
  765. if (!pCurr->Deleted())
  766. {
  767. return pCurr;
  768. }
  769. }
  770. if (pCurr->Children())
  771. {
  772. CWiaItem *pFind = Find( pCurr->Children(), pwszFindName );
  773. if (pFind)
  774. {
  775. return pFind;
  776. }
  777. }
  778. }
  779. return(NULL);
  780. }
  781. CWiaItem *Find( LPCWSTR pwszFindName )
  782. {
  783. return(Find( m_pRoot, pwszFindName ));
  784. }
  785. static CWiaItem *Find( CWiaItem *pRoot, DWORD dwGlobalInterfaceTableCookie )
  786. {
  787. for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
  788. {
  789. if (pCurr->GlobalInterfaceTableCookie() == dwGlobalInterfaceTableCookie)
  790. {
  791. if (!pCurr->Deleted())
  792. {
  793. return pCurr;
  794. }
  795. }
  796. if (pCurr->Children())
  797. {
  798. CWiaItem *pFind = Find( pCurr->Children(), dwGlobalInterfaceTableCookie );
  799. if (pFind)
  800. {
  801. return pFind;
  802. }
  803. }
  804. }
  805. return(NULL);
  806. }
  807. CWiaItem *Find( DWORD dwGlobalInterfaceTableCookie )
  808. {
  809. return(Find( m_pRoot, dwGlobalInterfaceTableCookie ));
  810. }
  811. HRESULT Add( CWiaItem *pParent, CWiaItem *pNewWiaItemNode )
  812. {
  813. WIA_PUSHFUNCTION(TEXT("CWiaItemList::Add"));
  814. WIA_TRACE((TEXT("Root(): 0x%08X"), Root()));
  815. if (pNewWiaItemNode)
  816. {
  817. if (!Root())
  818. {
  819. Root(pNewWiaItemNode);
  820. pNewWiaItemNode->Parent(NULL);
  821. pNewWiaItemNode->Children(NULL);
  822. pNewWiaItemNode->Next(NULL);
  823. }
  824. else
  825. {
  826. if (!pParent)
  827. {
  828. CWiaItem *pCurr=Root();
  829. while (pCurr && pCurr->Next())
  830. {
  831. pCurr=pCurr->Next();
  832. }
  833. pCurr->Next(pNewWiaItemNode);
  834. pNewWiaItemNode->Next(NULL);
  835. pNewWiaItemNode->Children(NULL);
  836. pNewWiaItemNode->Parent(NULL);
  837. }
  838. else if (!pParent->Children())
  839. {
  840. pParent->Children(pNewWiaItemNode);
  841. pNewWiaItemNode->Next(NULL);
  842. pNewWiaItemNode->Children(NULL);
  843. pNewWiaItemNode->Parent(pParent);
  844. }
  845. else
  846. {
  847. CWiaItem *pCurr=pParent->Children();
  848. while (pCurr && pCurr->Next())
  849. {
  850. pCurr=pCurr->Next();
  851. }
  852. pCurr->Next(pNewWiaItemNode);
  853. pNewWiaItemNode->Next(NULL);
  854. pNewWiaItemNode->Children(NULL);
  855. pNewWiaItemNode->Parent(pParent);
  856. }
  857. }
  858. }
  859. return S_OK;
  860. }
  861. HRESULT EnumerateItems( CWiaItem *pCurrentParent, IEnumWiaItem *pEnumWiaItem, int &nCurrentItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 )
  862. {
  863. WIA_PUSHFUNCTION(TEXT("CWiaItemList::EnumerateItems"));
  864. //
  865. // Assume failure
  866. //
  867. HRESULT hr = E_FAIL;
  868. //
  869. // Make sure we have a valid enumerator
  870. //
  871. if (pEnumWiaItem != NULL)
  872. {
  873. //
  874. // Start at the beginning
  875. //
  876. hr = pEnumWiaItem->Reset();
  877. while (hr == S_OK)
  878. {
  879. //
  880. // Get the next item
  881. //
  882. CComPtr<IWiaItem> pWiaItem;
  883. hr = pEnumWiaItem->Next(1, &pWiaItem, NULL);
  884. if (S_OK == hr)
  885. {
  886. if (pfnWiaItemEnumerationCallback)
  887. {
  888. bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, false );
  889. if (!bContinue)
  890. {
  891. hr = S_FALSE;
  892. break;
  893. }
  894. }
  895. //
  896. // Create a CWiaItem wrapper
  897. //
  898. CWiaItem *pNewWiaItem = new CWiaItem( pWiaItem );
  899. if (pNewWiaItem && pNewWiaItem->WiaItem())
  900. {
  901. //
  902. // Get the item type
  903. //
  904. LONG nItemType = pNewWiaItem->ItemType();
  905. if (nItemType)
  906. {
  907. //
  908. // Add it to the list
  909. //
  910. Add( pCurrentParent, pNewWiaItem );
  911. //
  912. // If it is an image, mark it as downloadeable
  913. //
  914. if (pNewWiaItem->IsDownloadableItemType())
  915. {
  916. pNewWiaItem->SelectedForDownload(true);
  917. nCurrentItem++;
  918. WIA_TRACE((TEXT("Found an image")));
  919. }
  920. //
  921. // If it is not an image, mark it as downloadeable
  922. //
  923. else
  924. {
  925. pNewWiaItem->SelectedForDownload(false);
  926. WIA_TRACE((TEXT("Found something that is NOT an image")));
  927. }
  928. //
  929. // If it is a folder, enumerate its child items and recurse
  930. //
  931. if (nItemType & WiaItemTypeFolder)
  932. {
  933. CComPtr <IEnumWiaItem> pIEnumChildItem;
  934. if (S_OK == pWiaItem->EnumChildItems(&pIEnumChildItem))
  935. {
  936. EnumerateItems( pNewWiaItem, pIEnumChildItem, nCurrentItem, pfnWiaItemEnumerationCallback, lParam );
  937. }
  938. }
  939. }
  940. }
  941. }
  942. //
  943. // Since we are using S_FALSE for cancel, we need to break out of this loop and set hr to S_OK
  944. //
  945. else if (S_FALSE == hr)
  946. {
  947. hr = S_OK;
  948. break;
  949. }
  950. }
  951. }
  952. //
  953. // Call the callback function one more time, and force the update
  954. //
  955. if (pfnWiaItemEnumerationCallback)
  956. {
  957. bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, true );
  958. if (!bContinue)
  959. {
  960. hr = S_FALSE;
  961. }
  962. }
  963. return hr;
  964. }
  965. HRESULT EnumerateAllWiaItems( IWiaItem *pWiaRootItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 )
  966. {
  967. //
  968. // Make sure we have a valid root item
  969. //
  970. if (!pWiaRootItem)
  971. {
  972. return E_INVALIDARG;
  973. }
  974. //
  975. // Enumerate the child items
  976. //
  977. CComPtr<IEnumWiaItem> pEnumItem;
  978. HRESULT hr = pWiaRootItem->EnumChildItems(&pEnumItem);
  979. if (hr == S_OK)
  980. {
  981. int nItemCount = 0;
  982. //
  983. // Entry point to the recursive enumeration routine
  984. //
  985. hr = EnumerateItems( NULL, pEnumItem, nItemCount, pfnWiaItemEnumerationCallback, lParam );
  986. }
  987. return hr;
  988. }
  989. };
  990. #endif // __WIAITEM_H_INCLUDED