windows-nt/Source/XPSP1/NT/printscan/ui/wiaacmgr/wiaitem.h
2020-09-26 16:20:57 +08:00

1081 lines
31 KiB
C++

#ifndef __WIAITEM_H_INCLUDED
#define __WIAITEM_H_INCLUDED
#include <windows.h>
#include <windowsx.h>
#include <wia.h>
#include <uicommon.h>
#include <itranhlp.h>
#include "pshelper.h"
#include "propstrm.h"
#include "resource.h"
#include "gphelper.h"
#include "wiaffmt.h"
class CWiaItem
{
public:
//
// Used to store the region for the scanner
//
struct CScanRegionSettings
{
SIZE sizeResolution;
POINT ptOrigin;
SIZE sizeExtent;
};
private:
CComPtr<IWiaItem> m_pWiaItem;
DWORD m_dwGlobalInterfaceTableCookie;
bool m_bSelectedForDownload;
HBITMAP m_hBitmapImage;
PBYTE m_pBitmapData;
LONG m_nWidth;
LONG m_nHeight;
LONG m_nBitmapDataLength;
CScanRegionSettings m_ScanRegionSettings;
CPropertyStream m_SavedPropertyStream;
CPropertyStream m_CustomPropertyStream;
bool m_bDeleted;
bool m_bAttemptedThumbnailDownload;
mutable LONG m_nItemType;
CWiaItem *m_pParent;
CWiaItem *m_pChildren;
CWiaItem *m_pNext;
GUID m_guidDefaultFormat;
LONG m_nAccessRights;
LONG m_nImageWidth;
LONG m_nImageHeight;
int m_nRotationAngle;
CSimpleStringWide m_strwFullItemName;
CSimpleStringWide m_strwItemName;
CAnnotationType m_AnnotationType;
CSimpleString m_strDefExt;
private:
// No implementation
CWiaItem(void);
CWiaItem( const CWiaItem & );
CWiaItem &operator=( const CWiaItem & );
public:
explicit CWiaItem( IWiaItem *pWiaItem )
: m_pWiaItem(pWiaItem),
m_dwGlobalInterfaceTableCookie(0),
m_bSelectedForDownload(false),
m_hBitmapImage(NULL),
m_pBitmapData(NULL),
m_nWidth(0),
m_nHeight(0),
m_nBitmapDataLength(0),
m_pParent(NULL),
m_pChildren(NULL),
m_pNext(NULL),
m_guidDefaultFormat(IID_NULL),
m_nRotationAngle(0),
m_nAccessRights(0),
m_nItemType(0),
m_nImageWidth(0),
m_nImageHeight(0),
m_AnnotationType(AnnotationNone),
m_bAttemptedThumbnailDownload(false)
{
WIA_PUSH_FUNCTION((TEXT("CWiaItem::CWiaItem")));
if (m_pWiaItem)
{
CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable );
if (SUCCEEDED(hr))
{
hr = pGlobalInterfaceTable->RegisterInterfaceInGlobal( pWiaItem, IID_IWiaItem, &m_dwGlobalInterfaceTableCookie );
if (SUCCEEDED(hr))
{
WIA_TRACE((TEXT("IGlobalInterfaceTable::RegisterInterfaceInGlobal gave us a cookie of %d"), m_dwGlobalInterfaceTableCookie ));
}
}
//
// NOTE: This is a here to get the item name so we can delete it later
// in response to a delete event, because there is no other way to find an item
// since ReadMultiple will fail after the item is deleted. This is the only item
// property I read on the foreground thread during initialization, unfortunately.
// but i need it immediately. One other awful alternative would be to just walk
// the item tree and call ReadMultiple on each item and prune the ones that return
// WIA_ERROR_ITEM_DELETED in response to delete item event.
//
PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_FULL_ITEM_NAME, m_strwFullItemName );
PropStorageHelpers::GetProperty( m_pWiaItem, WIA_IPA_ITEM_NAME, m_strwItemName );
}
}
~CWiaItem(void)
{
WIA_PUSH_FUNCTION((TEXT("CWiaItem::~CWiaItem")));
//
// Remove the item from the GIT
//
if (m_pWiaItem)
{
CComPtr<IGlobalInterfaceTable> pGlobalInterfaceTable;
HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&pGlobalInterfaceTable );
if (SUCCEEDED(hr))
{
hr = pGlobalInterfaceTable->RevokeInterfaceFromGlobal( m_dwGlobalInterfaceTableCookie );
if (SUCCEEDED(hr))
{
WIA_TRACE((TEXT("IGlobalInterfaceTable::RevokeInterfaceFromGlobal succeeded on %d"), m_dwGlobalInterfaceTableCookie ));
}
}
}
// Delete the item's Thumbnail
if (m_hBitmapImage)
{
DeleteObject(m_hBitmapImage);
m_hBitmapImage = NULL;
}
//
// Delete the thumbnail data
//
if (m_pBitmapData)
{
LocalFree(m_pBitmapData);
m_pBitmapData = NULL;
}
//
// NULL out all the other members
//
m_pWiaItem = NULL;
m_dwGlobalInterfaceTableCookie = 0;
m_nWidth = m_nHeight = m_nImageWidth = m_nImageHeight = m_nBitmapDataLength = 0;
m_pParent = m_pChildren = m_pNext = NULL;
}
LONG ItemType(void) const
{
//
// If we've already read the item type, don't read it again
//
if (!m_nItemType && m_pWiaItem)
{
(void)m_pWiaItem->GetItemType(&m_nItemType);
}
//
// Return m_nItemType even if IWiaItem::GetItemType fails, because it will still be 0, which
// also works as an error result
//
return m_nItemType;
}
bool Deleted(void) const
{
return m_bDeleted;
}
void MarkDeleted(void)
{
m_bDeleted = true;
m_bSelectedForDownload = false;
}
bool RotationEnabled( bool bAllowUninitializedRotation=false ) const
{
WIA_PUSH_FUNCTION((TEXT("CWiaItem::RotationEnabled(%d)"),bAllowUninitializedRotation));
//
// If this image doesn't have a thumbnail AND we tried to get the thumbnail, don't allow
// rotation even if the caller says it is OK. This image doesn't have a thumbnail
// because it didn't provide one, not because we don't have one yet
//
if (m_bAttemptedThumbnailDownload && !HasThumbnail())
{
return false;
}
//
// If this is an uninitialized image and we are told to allow uninitialized rotation,
// we will allow rotation, which we will discard when the image is initialized.
//
if (bAllowUninitializedRotation && m_guidDefaultFormat==IID_NULL && m_nImageWidth==0 && m_nImageHeight==0)
{
WIA_TRACE((TEXT("Uninitialized image: returning true")));
return true;
}
return WiaUiUtil::CanWiaImageBeSafelyRotated( m_guidDefaultFormat, m_nImageWidth, m_nImageHeight );
}
bool AttemptedThumbnailDownload( bool bAttemptedThumbnailDownload )
{
return (m_bAttemptedThumbnailDownload = bAttemptedThumbnailDownload);
}
bool AttemptedThumbnailDownload() const
{
return m_bAttemptedThumbnailDownload;
}
void DiscardRotationIfNecessary(void)
{
WIA_PUSHFUNCTION(TEXT("CWiaItem::DiscardRotationIfNecessary"));
//
// After the image is initialized, we will discard the rotation angle if it turns out the
// image cannot be rotated
//
if (!RotationEnabled())
{
WIA_TRACE((TEXT("Discarding rotation")));
m_nRotationAngle = 0;
}
}
bool IsValid(void) const
{
return(m_pWiaItem && m_dwGlobalInterfaceTableCookie);
}
CSimpleStringWide FullItemName(void) const
{
return m_strwFullItemName;
}
CSimpleStringWide ItemName(void) const
{
return m_strwItemName;
}
GUID DefaultFormat(void)
{
return m_guidDefaultFormat;
}
void DefaultFormat( const GUID &guidDefaultFormat )
{
m_guidDefaultFormat = guidDefaultFormat;
}
LONG AccessRights(void) const
{
return m_nAccessRights;
}
void AccessRights( LONG nAccessRights )
{
m_nAccessRights = nAccessRights;
}
void Rotate( bool bRight )
{
switch (m_nRotationAngle)
{
case 0:
m_nRotationAngle = bRight ? 90 : 270;
break;
case 90:
m_nRotationAngle = bRight ? 180 : 0;
break;
case 180:
m_nRotationAngle = bRight ? 270 : 90;
break;
case 270:
m_nRotationAngle = bRight ? 0 : 180;
break;
}
}
int Rotation(void) const
{
return m_nRotationAngle;
}
CSimpleString DefExt() const
{
return m_strDefExt;
}
const CSimpleString &DefExt( const CSimpleString &strDefExt )
{
return (m_strDefExt = strDefExt );
}
CScanRegionSettings &ScanRegionSettings(void)
{
return m_ScanRegionSettings;
}
const CScanRegionSettings &ScanRegionSettings(void) const
{
return m_ScanRegionSettings;
}
CPropertyStream &SavedPropertyStream(void)
{
return m_SavedPropertyStream;
}
const CPropertyStream &SavedPropertyStream(void) const
{
return m_SavedPropertyStream;
}
CPropertyStream &CustomPropertyStream(void)
{
return m_CustomPropertyStream;
}
const CPropertyStream &CustomPropertyStream(void) const
{
return m_CustomPropertyStream;
}
bool SelectedForDownload(void) const
{
return m_bSelectedForDownload;
}
bool SelectedForDownload( bool bSelectedForDownload )
{
return(m_bSelectedForDownload = bSelectedForDownload);
}
HBITMAP BitmapImage(void) const
{
return m_hBitmapImage;
}
HBITMAP BitmapImage( HBITMAP hBitmapImage )
{
if (m_hBitmapImage)
{
DeleteObject(m_hBitmapImage);
}
return(m_hBitmapImage = hBitmapImage);
}
PBYTE BitmapData(void) const
{
return m_pBitmapData;
}
PBYTE BitmapData( PBYTE pBitmapData )
{
if (m_pBitmapData)
{
LocalFree(m_pBitmapData);
}
return(m_pBitmapData = pBitmapData);
}
LONG Width(void) const
{
return m_nWidth;
}
LONG Width( LONG nWidth )
{
return (m_nWidth = nWidth);
}
LONG Height(void) const
{
return m_nHeight;
}
LONG Height( LONG nHeight )
{
return (m_nHeight = nHeight);
}
LONG BitmapDataLength(void) const
{
return m_nBitmapDataLength;
}
LONG BitmapDataLength( LONG nBitmapDataLength )
{
return (m_nBitmapDataLength = nBitmapDataLength);
}
LONG ImageWidth(void) const
{
return m_nImageWidth;
}
LONG ImageWidth( LONG nImageWidth )
{
return (m_nImageWidth = nImageWidth);
}
LONG ImageHeight(void) const
{
return m_nImageHeight;
}
LONG ImageHeight( LONG nImageHeight )
{
return (m_nImageHeight = nImageHeight);
}
bool HasThumbnail() const
{
return (m_pBitmapData && m_nWidth && m_nHeight);
}
HBITMAP CreateThumbnailFromBitmapData( HDC hDC )
{
//
// Assume failure
//
HBITMAP hbmpResult = NULL;
//
// If we've already attempted to download this image
//
if (m_bAttemptedThumbnailDownload)
{
//
// Make sure we have good data
//
if (m_pBitmapData && m_nWidth && m_nHeight)
{
//
// Initialize the bitmap info
//
BITMAPINFO BitmapInfo = {0};
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = m_nWidth;
BitmapInfo.bmiHeader.biHeight = m_nHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 24;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
//
// Create the bitmap
//
PBYTE pBits = NULL;
hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 );
if (hbmpResult)
{
//
// Calculate the size of the bitmap data
//
LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight;
//
// Copy the bitmap data to the bitmap. Make sure we use the minimum of the calculated
// and actual length
//
CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) );
}
else
{
WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!")));
}
}
}
return hbmpResult;
}
HBITMAP CreateThumbnailBitmap( HWND hWnd, CGdiPlusHelper &GdiPlusHelper, int nSizeX, int nSizeY )
{
//
// Initialize the return value. Assume failure.
//
HBITMAP hThumbnail = NULL;
//
// Only return a bitmap if we've already attempted to download one
//
if (m_bAttemptedThumbnailDownload)
{
//
// Make sure this is a real thumbnail. If not, we will create a fake one below.
//
if (HasThumbnail())
{
//
// Get the client DC
//
HDC hDC = GetDC( hWnd );
if (hDC)
{
//
// Create the bitmap from the raw bitmap data
//
HBITMAP hRawBitmap = CreateThumbnailFromBitmapData( hDC );
if (hRawBitmap)
{
//
// Rotate the thumbnail
//
HBITMAP hRotatedThumbnail = NULL;
if (SUCCEEDED(GdiPlusHelper.Rotate( hRawBitmap, hRotatedThumbnail, Rotation())))
{
//
// Make sure we got a valid rotated thumbnail
//
if (hRotatedThumbnail)
{
//
// Try to scale the image
//
SIZE sizeScaled = {nSizeX,nSizeY};
ScaleImage( hDC, hRotatedThumbnail, hThumbnail, sizeScaled );
//
// Nuke the rotated bitmap
//
DeleteBitmap(hRotatedThumbnail);
}
}
//
// Nuke the raw bitmap
//
DeleteBitmap(hRawBitmap);
}
//
// Release the client DC
//
ReleaseDC( hWnd, hDC );
}
}
else
{
WIA_PRINTGUID((m_guidDefaultFormat,TEXT("m_guidDefaultFormat")));
//
// Create a file format object and load the type icon
//
CWiaFileFormat WiaFileFormat;
WiaFileFormat.Format( m_guidDefaultFormat );
WiaFileFormat.Extension( m_strDefExt );
HICON hIcon = WiaFileFormat.AcquireIcon( NULL, false );
//
// Make sure we have an icon
//
if (hIcon)
{
//
// Create the icon thumbnail with the type icon and the name of the file
//
hThumbnail = WiaUiUtil::CreateIconThumbnail( hWnd, nSizeX, nSizeY, hIcon, CSimpleStringConvert::NaturalString(m_strwItemName) );
WIA_TRACE((TEXT("hThumbnail: %p"),hThumbnail));
//
// Destroy the icon to prevent leaks
//
DestroyIcon(hIcon);
}
else
{
WIA_ERROR((TEXT("Unable to get the icon")));
}
}
}
return hThumbnail;
}
HBITMAP CreateThumbnailBitmap( HDC hDC )
{
//
// Assume failure
//
HBITMAP hbmpResult = NULL;
//
// Make sure we have good data
//
WIA_TRACE((TEXT("m_pBitmapData: %08X, m_nWidth: %d, m_nWidth: %d"), m_pBitmapData, m_nWidth, m_nHeight ));
if (m_pBitmapData && m_nWidth && m_nHeight)
{
//
// Initialize the bitmap info
//
BITMAPINFO BitmapInfo = {0};
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = m_nWidth;
BitmapInfo.bmiHeader.biHeight = m_nHeight;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 24;
BitmapInfo.bmiHeader.biCompression = BI_RGB;
//
// Create the bitmap
//
PBYTE pBits = NULL;
hbmpResult = CreateDIBSection( hDC, &BitmapInfo, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 );
if (hbmpResult)
{
LONG nSizeOfBitmapData = WiaUiUtil::Align( m_nWidth * 3, sizeof(DWORD) ) * m_nHeight;
CopyMemory( pBits, m_pBitmapData, WiaUiUtil::Min(nSizeOfBitmapData,m_nBitmapDataLength) );
}
else
{
WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed!")));
}
}
return hbmpResult;
}
IWiaItem *WiaItem(void) const
{
return m_pWiaItem.p;
}
IWiaItem *WiaItem(void)
{
return m_pWiaItem.p;
}
const CWiaItem *Next(void) const
{
return(m_pNext);
}
CWiaItem *Next(void)
{
return(m_pNext);
}
CWiaItem *Next( CWiaItem *pNext )
{
return(m_pNext = pNext);
}
const CWiaItem *Children(void) const
{
return(m_pChildren);
}
CWiaItem *Children(void)
{
return(m_pChildren);
}
CWiaItem *Children( CWiaItem *pChildren )
{
return(m_pChildren = pChildren);
}
const CWiaItem *Parent(void) const
{
return(m_pParent);
}
CWiaItem *Parent(void)
{
return(m_pParent);
}
CWiaItem *Parent( CWiaItem *pParent )
{
return(m_pParent = pParent);
}
DWORD GlobalInterfaceTableCookie(void) const
{
return m_dwGlobalInterfaceTableCookie;
}
bool operator==( const CWiaItem &WiaItem )
{
return(WiaItem.WiaItem() == m_pWiaItem.p);
}
bool operator==( DWORD dwGlobalInterfaceTableCookie )
{
return(dwGlobalInterfaceTableCookie == GlobalInterfaceTableCookie());
}
bool IsDownloadableItemType(void) const
{
LONG nItemType = ItemType();
return ((nItemType & WiaItemTypeImage) || (nItemType & WiaItemTypeVideo));
}
CAnnotationType AnnotationType(void) const
{
return m_AnnotationType;
}
void AnnotationType( CAnnotationType AnnotationType )
{
m_AnnotationType = AnnotationType;
}
};
class CWiaItemList
{
public:
enum CEnumEvent
{
CountingItems, // Recursing tree, counting items. nData == current count
ReadingItemInfo // Recursing tree, reading info. nData == current item
};
typedef bool (*WiaItemEnumerationCallbackFunction)( CEnumEvent EnumEvent, UINT nData, LPARAM lParam, bool bForceUpdate );
private:
CWiaItem *m_pRoot;
private:
// No implementation
CWiaItemList( const CWiaItemList & );
CWiaItemList &operator=( const CWiaItemList & );
public:
CWiaItemList(void)
: m_pRoot(NULL)
{
}
~CWiaItemList(void)
{
Destroy();
}
void Destroy( CWiaItem *pRoot )
{
while (pRoot)
{
Destroy(pRoot->Children());
CWiaItem *pCurr = pRoot;
pRoot = pRoot->Next();
delete pCurr;
}
}
void Destroy(void)
{
Destroy(m_pRoot);
m_pRoot = NULL;
}
const CWiaItem *Root(void) const
{
return(m_pRoot);
}
CWiaItem *Root(void)
{
return(m_pRoot);
}
CWiaItem *Root( CWiaItem *pRoot )
{
return(m_pRoot = pRoot);
}
int Count( CWiaItem *pFirst )
{
int nCount = 0;
for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next())
{
if (pCurr->IsDownloadableItemType() && !pCurr->Deleted())
nCount++;
nCount += Count(pCurr->Children());
}
return nCount;
}
int Count(void)
{
return Count(m_pRoot);
}
int SelectedForDownloadCount( CWiaItem *pFirst )
{
int nCount = 0;
for (CWiaItem *pCurr = pFirst;pCurr;pCurr = pCurr->Next())
{
if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload())
nCount++;
nCount += SelectedForDownloadCount(pCurr->Children());
}
return nCount;
}
int SelectedForDownloadCount(void)
{
return SelectedForDownloadCount(Root());
}
static CWiaItem *Find( CWiaItem *pRoot, const CWiaItem *pNode )
{
for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
{
if (*pCurr == *pNode)
{
if (!pCurr->Deleted())
{
return pCurr;
}
}
if (pCurr->Children())
{
CWiaItem *pFind = Find( pCurr->Children(), pNode );
if (pFind)
{
return pFind;
}
}
}
return(NULL);
}
CWiaItem *Find( CWiaItem *pNode )
{
return(Find( m_pRoot, pNode ));
}
static CWiaItem *Find( CWiaItem *pRoot, IWiaItem *pItem )
{
for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
{
if (pCurr->WiaItem() == pItem)
{
if (!pCurr->Deleted())
{
return pCurr;
}
}
if (pCurr->Children())
{
CWiaItem *pFind = Find( pCurr->Children(), pItem );
if (pFind)
{
return pFind;
}
}
}
return(NULL);
}
CWiaItem *Find( IWiaItem *pItem )
{
return(Find( m_pRoot, pItem ));
}
static CWiaItem *Find( CWiaItem *pRoot, LPCWSTR pwszFindName )
{
for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
{
if (CSimpleStringConvert::NaturalString(CSimpleStringWide(pwszFindName)) == CSimpleStringConvert::NaturalString(pCurr->FullItemName()))
{
if (!pCurr->Deleted())
{
return pCurr;
}
}
if (pCurr->Children())
{
CWiaItem *pFind = Find( pCurr->Children(), pwszFindName );
if (pFind)
{
return pFind;
}
}
}
return(NULL);
}
CWiaItem *Find( LPCWSTR pwszFindName )
{
return(Find( m_pRoot, pwszFindName ));
}
static CWiaItem *Find( CWiaItem *pRoot, DWORD dwGlobalInterfaceTableCookie )
{
for (CWiaItem *pCurr = pRoot;pCurr;pCurr = pCurr->Next())
{
if (pCurr->GlobalInterfaceTableCookie() == dwGlobalInterfaceTableCookie)
{
if (!pCurr->Deleted())
{
return pCurr;
}
}
if (pCurr->Children())
{
CWiaItem *pFind = Find( pCurr->Children(), dwGlobalInterfaceTableCookie );
if (pFind)
{
return pFind;
}
}
}
return(NULL);
}
CWiaItem *Find( DWORD dwGlobalInterfaceTableCookie )
{
return(Find( m_pRoot, dwGlobalInterfaceTableCookie ));
}
HRESULT Add( CWiaItem *pParent, CWiaItem *pNewWiaItemNode )
{
WIA_PUSHFUNCTION(TEXT("CWiaItemList::Add"));
WIA_TRACE((TEXT("Root(): 0x%08X"), Root()));
if (pNewWiaItemNode)
{
if (!Root())
{
Root(pNewWiaItemNode);
pNewWiaItemNode->Parent(NULL);
pNewWiaItemNode->Children(NULL);
pNewWiaItemNode->Next(NULL);
}
else
{
if (!pParent)
{
CWiaItem *pCurr=Root();
while (pCurr && pCurr->Next())
{
pCurr=pCurr->Next();
}
pCurr->Next(pNewWiaItemNode);
pNewWiaItemNode->Next(NULL);
pNewWiaItemNode->Children(NULL);
pNewWiaItemNode->Parent(NULL);
}
else if (!pParent->Children())
{
pParent->Children(pNewWiaItemNode);
pNewWiaItemNode->Next(NULL);
pNewWiaItemNode->Children(NULL);
pNewWiaItemNode->Parent(pParent);
}
else
{
CWiaItem *pCurr=pParent->Children();
while (pCurr && pCurr->Next())
{
pCurr=pCurr->Next();
}
pCurr->Next(pNewWiaItemNode);
pNewWiaItemNode->Next(NULL);
pNewWiaItemNode->Children(NULL);
pNewWiaItemNode->Parent(pParent);
}
}
}
return S_OK;
}
HRESULT EnumerateItems( CWiaItem *pCurrentParent, IEnumWiaItem *pEnumWiaItem, int &nCurrentItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 )
{
WIA_PUSHFUNCTION(TEXT("CWiaItemList::EnumerateItems"));
//
// Assume failure
//
HRESULT hr = E_FAIL;
//
// Make sure we have a valid enumerator
//
if (pEnumWiaItem != NULL)
{
//
// Start at the beginning
//
hr = pEnumWiaItem->Reset();
while (hr == S_OK)
{
//
// Get the next item
//
CComPtr<IWiaItem> pWiaItem;
hr = pEnumWiaItem->Next(1, &pWiaItem, NULL);
if (S_OK == hr)
{
if (pfnWiaItemEnumerationCallback)
{
bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, false );
if (!bContinue)
{
hr = S_FALSE;
break;
}
}
//
// Create a CWiaItem wrapper
//
CWiaItem *pNewWiaItem = new CWiaItem( pWiaItem );
if (pNewWiaItem && pNewWiaItem->WiaItem())
{
//
// Get the item type
//
LONG nItemType = pNewWiaItem->ItemType();
if (nItemType)
{
//
// Add it to the list
//
Add( pCurrentParent, pNewWiaItem );
//
// If it is an image, mark it as downloadeable
//
if (pNewWiaItem->IsDownloadableItemType())
{
pNewWiaItem->SelectedForDownload(true);
nCurrentItem++;
WIA_TRACE((TEXT("Found an image")));
}
//
// If it is not an image, mark it as downloadeable
//
else
{
pNewWiaItem->SelectedForDownload(false);
WIA_TRACE((TEXT("Found something that is NOT an image")));
}
//
// If it is a folder, enumerate its child items and recurse
//
if (nItemType & WiaItemTypeFolder)
{
CComPtr <IEnumWiaItem> pIEnumChildItem;
if (S_OK == pWiaItem->EnumChildItems(&pIEnumChildItem))
{
EnumerateItems( pNewWiaItem, pIEnumChildItem, nCurrentItem, pfnWiaItemEnumerationCallback, lParam );
}
}
}
}
}
//
// Since we are using S_FALSE for cancel, we need to break out of this loop and set hr to S_OK
//
else if (S_FALSE == hr)
{
hr = S_OK;
break;
}
}
}
//
// Call the callback function one more time, and force the update
//
if (pfnWiaItemEnumerationCallback)
{
bool bContinue = pfnWiaItemEnumerationCallback( ReadingItemInfo, nCurrentItem, lParam, true );
if (!bContinue)
{
hr = S_FALSE;
}
}
return hr;
}
HRESULT EnumerateAllWiaItems( IWiaItem *pWiaRootItem, WiaItemEnumerationCallbackFunction pfnWiaItemEnumerationCallback = NULL, LPARAM lParam = 0 )
{
//
// Make sure we have a valid root item
//
if (!pWiaRootItem)
{
return E_INVALIDARG;
}
//
// Enumerate the child items
//
CComPtr<IEnumWiaItem> pEnumItem;
HRESULT hr = pWiaRootItem->EnumChildItems(&pEnumItem);
if (hr == S_OK)
{
int nItemCount = 0;
//
// Entry point to the recursive enumeration routine
//
hr = EnumerateItems( NULL, pEnumItem, nItemCount, pfnWiaItemEnumerationCallback, lParam );
}
return hr;
}
};
#endif // __WIAITEM_H_INCLUDED