#include "precomp.h" #pragma hdrstop #include #include #include #include #include #include #include "simstr.h" #include "camdlg.h" #include "camdlg.rh" #include "simcrack.h" #include "pviewids.h" #include "dlgunits.h" #include "miscutil.h" #include "waitcurs.h" #include "movewnd.h" #include "simrect.h" #include "simbstr.h" #include "uiexthlp.h" #include "gwiaevnt.h" #include "wiacsh.h" #include "wiadevdp.h" // // Thread queue messages // #define TQ_DESTROY (WM_USER+1) #define TQ_GETTHUMBNAIL (WM_USER+2) #define TQ_GETPREVIEW (WM_USER+3) #define TQ_DELETEITEM (WM_USER+4) // // Control ids // #define IDC_TOOLBAR 1112 #define IDC_SIZEBOX 1113 // // The UI thread will notify us that it took ownership of the data. // otherwise, it will be deleted in the worker thread // #define HANDLED_THREAD_MESSAGE 1000 // // Help IDs // static const DWORD g_HelpIDs[] = { IDC_CAMDLG_BIG_TITLE, -1, IDC_CAMDLG_SUBTITLE, -1, IDC_TOOLBAR_FRAME, IDH_WIA_BUTTONS, IDC_TOOLBAR, IDH_WIA_BUTTONS, IDOK, IDH_WIA_GET_PICS, IDC_THUMBNAILLIST, IDH_WIA_PIC_LIST, IDC_YOU_CAN_ALSO, IDH_WIA_VIEW_PIC_INFO, IDC_CAMDLG_PROPERTIES, IDH_WIA_VIEW_PIC_INFO, IDC_PREVIEW, IDH_WIA_PREVIEW_DETAIL, IDC_INNER_PREVIEW_WINDOW, IDH_WIA_PREVIEW_DETAIL, IDCANCEL, IDH_CANCEL, 0, 0 }; // // Update timer // #define IDT_UPDATEPREVIEW 1000 #define UPDATE_PREVIEW_DELAY 500 // // Number of milliseconds between percent display updates // #define PERCENT_UPDATE_GRANULARITY 1000 // // Private messages // #define PWM_POSTINIT (WM_USER+1) #define PWM_CHANGETOPARENT (WM_USER+2) #define PWM_THUMBNAILSTATUS (WM_USER+3) #define PWM_PREVIEWSTATUS (WM_USER+4) #define PWM_PREVIEWPERCENT (WM_USER+5) #define PWM_ITEMDELETED (WM_USER+6) #define PWM_WIAEVENT (WM_USER+7) // // Thumbnail whitespace: the space in between images and their selection rectangles // These values were discovered by trail and error. For instance, if you reduce // c_nAdditionalMarginY to 20, you get really bizarre spacing problems in the list view // in vertical mode. These values could become invalid in future versions of the listview. // static const int c_nAdditionalMarginX = 10; static const int c_nAdditionalMarginY = 6; static int c_nMinThumbnailWidth = 90; static int c_nMinThumbnailHeight = 90; static int c_nMaxThumbnailWidth = 120; static int c_nMaxThumbnailHeight = 120; // // Button bar button bitmap sizes // static const int c_nButtonBitmapSizeX = 16; static const int c_nButtonBitmapSizeY = 16; // // Button bar button sizes // static const int c_nButtonSizeX = 300; // Ridiculously large size to compensate for BTNS_AUTOSIZE bug. static const int c_nButtonSizeY = 16; // // Default preview mode list width // static const int c_nDefaultListViewWidth = 120; // // These defines let me compile with pre-nt5 headers // #ifndef BTNS_SEP #define BTNS_SEP TBSTYLE_SEP #endif #ifndef BTNS_BUTTON #define BTNS_BUTTON TBSTYLE_BUTTON #endif #ifndef ListView_SetExtendedListViewStyleEx #define ListView_SetExtendedListViewStyleEx( h, m, s ) #endif class CGlobalInterfaceTableThreadMessage : public CNotifyThreadMessage { private: DWORD m_dwGlobalInterfaceTableCookie; private: // // No implementation // CGlobalInterfaceTableThreadMessage(void); CGlobalInterfaceTableThreadMessage &operator=( const CGlobalInterfaceTableThreadMessage & ); CGlobalInterfaceTableThreadMessage( const CGlobalInterfaceTableThreadMessage & ); public: CGlobalInterfaceTableThreadMessage( int nMessage, HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie ) : CNotifyThreadMessage( nMessage, hWndNotify ), m_dwGlobalInterfaceTableCookie(dwGlobalInterfaceTableCookie) { } DWORD GlobalInterfaceTableCookie(void) const { return(m_dwGlobalInterfaceTableCookie); } }; class CThumbnailThreadMessage : public CGlobalInterfaceTableThreadMessage { private: SIZE m_sizeThumb; private: // // No implementation // CThumbnailThreadMessage(void); CThumbnailThreadMessage &operator=( const CThumbnailThreadMessage & ); CThumbnailThreadMessage( const CThumbnailThreadMessage & ); public: CThumbnailThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, const SIZE &sizeThumb ) : CGlobalInterfaceTableThreadMessage( TQ_GETTHUMBNAIL, hWndNotify, dwGlobalInterfaceTableCookie ), m_sizeThumb(sizeThumb) { } const SIZE &ThumbSize(void) const { return(m_sizeThumb); } }; class CDeleteThreadMessage : public CGlobalInterfaceTableThreadMessage { private: // // No implementation // CDeleteThreadMessage(void); CDeleteThreadMessage &operator=( const CDeleteThreadMessage & ); CDeleteThreadMessage( const CDeleteThreadMessage & ); public: CDeleteThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie ) : CGlobalInterfaceTableThreadMessage( TQ_DELETEITEM, hWndNotify, dwGlobalInterfaceTableCookie ) { } }; class CPreviewThreadMessage : public CGlobalInterfaceTableThreadMessage { private: CSimpleEvent m_CancelEvent; private: // // No implementation // CPreviewThreadMessage(void); CPreviewThreadMessage &operator=( const CPreviewThreadMessage & ); CPreviewThreadMessage( const CPreviewThreadMessage & ); public: CPreviewThreadMessage( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent ) : CGlobalInterfaceTableThreadMessage( TQ_GETPREVIEW, hWndNotify, dwGlobalInterfaceTableCookie ), m_CancelEvent(hCancelEvent) { } CSimpleEvent &CancelEvent(void) { return(m_CancelEvent); } }; BOOL WINAPI CCameraAcquireDialog::OnThreadDestroy( CThreadMessage * ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThreadDestroy")); return(FALSE); } BOOL WINAPI CCameraAcquireDialog::OnThreadDeleteItem( CThreadMessage *pMsg ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThreadDeleteItem")); CDeleteThreadMessage *pDeleteMsg = (CDeleteThreadMessage *)(pMsg); if (pDeleteMsg) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable); if (SUCCEEDED(hr)) { CComPtr pIWiaItem; hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pDeleteMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem ); if (SUCCEEDED(hr)) { hr = WiaUiUtil::DeleteItemAndChildren(pIWiaItem); WIA_TRACE((TEXT("********************* pIWiaItem->DeleteItem returned %08X"), hr )); PostMessage( pDeleteMsg->NotifyWindow(), PWM_ITEMDELETED, pDeleteMsg->GlobalInterfaceTableCookie(), SUCCEEDED(hr) ); } } } return(TRUE); } class CWiaDataCallback : public IWiaDataCallback { private: ULONG m_cRef; HWND m_hWndNotify; DWORD m_dwGlobalInterfaceTableCookie; CSimpleEvent m_CancelEvent; DWORD m_dwPreviousTickCount; int m_nPercentGranularity; public: CWiaDataCallback(); ~CWiaDataCallback(); HRESULT _stdcall QueryInterface(const IID&,void**); ULONG _stdcall AddRef(); ULONG _stdcall Release(); HRESULT _stdcall Initialize( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent ); HRESULT _stdcall BandedDataCallback( LONG lReason, LONG lStatus, LONG lPercentComplete, LONG lOffset, LONG lLength, LONG lReserved, LONG lResLength, BYTE *pbBuffer ); }; HRESULT _stdcall CWiaDataCallback::QueryInterface(const IID& iid, void** ppv) { *ppv = NULL; if (iid == IID_IUnknown || iid == IID_IWiaDataCallback) { *ppv = (IWiaDataCallback*)this; } else { return(E_NOINTERFACE); } AddRef(); return(S_OK); } ULONG _stdcall CWiaDataCallback::AddRef() { InterlockedIncrement((long*) &m_cRef); return(m_cRef); } ULONG _stdcall CWiaDataCallback::Release() { ULONG ulRefCount = m_cRef - 1; if (InterlockedDecrement((long*) &m_cRef) == 0) { delete this; return(0); } return(ulRefCount); } CWiaDataCallback::CWiaDataCallback() : m_cRef(0), m_hWndNotify(NULL) { } CWiaDataCallback::~CWiaDataCallback() { } HRESULT _stdcall CWiaDataCallback::Initialize( HWND hWndNotify, DWORD dwGlobalInterfaceTableCookie, HANDLE hCancelEvent ) { m_hWndNotify = hWndNotify; m_dwGlobalInterfaceTableCookie = dwGlobalInterfaceTableCookie; m_CancelEvent = hCancelEvent; m_dwPreviousTickCount = 0xFFFFFF; m_nPercentGranularity = 3; return(S_OK); } HRESULT _stdcall CWiaDataCallback::BandedDataCallback( LONG lMessage, LONG lStatus, LONG lPercentComplete, LONG lOffset, LONG lLength, LONG lReserved, LONG lResLength, BYTE * /* pbBuffer */ ) { 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 )); if (m_CancelEvent.Signalled()) return(S_FALSE); switch (lMessage) { case IT_MSG_DATA_HEADER: { } // IT_MSG_DATA_HEADER case IT_MSG_DATA: { } // IT_STATUS_TRANSFER_TO_CLIENT break; case IT_MSG_STATUS: { // Don't send status messages too frequently. Limit to one per PERCENT_UPDATE_GRANULARITY ms DWORD dwTickCount = GetTickCount(); if ((dwTickCount - m_dwPreviousTickCount >= PERCENT_UPDATE_GRANULARITY) || (m_dwPreviousTickCount > dwTickCount)) { m_dwPreviousTickCount = dwTickCount; PostMessage( m_hWndNotify, PWM_PREVIEWPERCENT, (WPARAM)m_dwGlobalInterfaceTableCookie, (LPARAM)MAKELPARAM((WORD)lPercentComplete,(WORD)lStatus)); } } // IT_MSG_STATUS break; case IT_MSG_TERMINATION: { } // IT_MSG_TERMINATION break; } return(S_OK); } BOOL WINAPI CCameraAcquireDialog::OnGetPreview( CThreadMessage *pMsg ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnGetThumbnail")); CSimpleStringWide strwImageName(L""); CPreviewThreadMessage *pPreviewMsg = (CPreviewThreadMessage *)(pMsg); if (pPreviewMsg) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable); if (SUCCEEDED(hr)) { CComPtr pIWiaItem; hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pPreviewMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem ); if (SUCCEEDED(hr)) { CComPtr pIBandedTran; WIA_TRACE((TEXT("Preparing to call pIWiaItem->QueryInterface for IID_IWiaDataTransfer"))); hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&pIBandedTran); if (SUCCEEDED(hr)) { if (PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_FORMAT, WiaImgFmt_BMP, WIA_IPA_FIRST ) && PropStorageHelpers::SetProperty( pIWiaItem, WIA_IPA_TYMED, TYMED_FILE, WIA_IPA_FIRST )) { CWiaDataCallback* pCDataCB = new CWiaDataCallback(); WIA_TRACE((TEXT("Preparing to call pCDataCB->Initialize"))); if (pCDataCB) { hr = pCDataCB->Initialize( pPreviewMsg->NotifyWindow(), pPreviewMsg->GlobalInterfaceTableCookie(), pPreviewMsg->CancelEvent().Event() ); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("Preparing to call pCDataCB->QueryInterface on IID_IWiaDataCallback"))); CComPtr pIWiaDataCallback; hr = pCDataCB->QueryInterface(IID_IWiaDataCallback,(void **)&pIWiaDataCallback); if (SUCCEEDED(hr)) { STGMEDIUM StgMedium; StgMedium.tymed = TYMED_FILE; StgMedium.pUnkForRelease = NULL; StgMedium.hGlobal = NULL; StgMedium.lpszFileName = NULL; WIA_TRACE((TEXT("Preparing to call pIBandedTran->ibtGetData"))); hr = pIBandedTran->idtGetData( &StgMedium, pIWiaDataCallback ); if (SUCCEEDED(hr) && S_FALSE != hr) { strwImageName = StgMedium.lpszFileName; WIA_TRACE((TEXT("pIBandedTran->ibtGetData returned %s"),StgMedium.lpszFileName)); } else { WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, ibtGetData failed"))); } // // Prevent leaks by freeing the filename. We don't call ReleaseStgMeduim, because // it deletes the file as well. // if (SUCCEEDED(hr) && StgMedium.lpszFileName) { CoTaskMemFree(StgMedium.lpszFileName); } } else { WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, QI of IID_IWiaDataCallback failed"))); } } else { WIA_PRINTHRESULT((hr,TEXT("pCDataCB->Initialize failed"))); } } else { WIA_ERROR((TEXT("CCameraAcquireDialog::OnGetPreview, new on CWiaDataCallback failed"))); } } else { hr = MAKE_HRESULT(3,FACILITY_WIN32,ERROR_INVALID_DATA); WIA_ERROR((TEXT("SetProperty on TYMED or FORMAT failed"))); } } else { WIA_PRINTHRESULT((hr,TEXT("CCameraAcquireDialog::OnGetPreview, QI of IID_IWiaDataTransfer failed"))); } WIA_TRACE((TEXT("End CCameraAcquireDialog::OnGetPreviewBandedTransfer"))); } } // // Allocate the filename string to return to the UI thread // CSimpleString *pstrDibFilename = new CSimpleString( CSimpleStringConvert::NaturalString(strwImageName) ); // // Send the message to the UI thread // LRESULT lRes = SendMessage( pPreviewMsg->NotifyWindow(), PWM_PREVIEWSTATUS, pPreviewMsg->GlobalInterfaceTableCookie(), reinterpret_cast(pstrDibFilename)); // // If it fails for any reason, we will clean up to avoid leaks and orphaned temp files // if (HANDLED_THREAD_MESSAGE != lRes) { DeleteFile(CSimpleStringConvert::NaturalString(strwImageName)); if (pstrDibFilename) { delete pstrDibFilename; } } } return(TRUE); } BOOL WINAPI CCameraAcquireDialog::OnGetThumbnail( CThreadMessage *pMsg ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnGetThumbnail")); HBITMAP hBmpThumbnail = NULL; CThumbnailThreadMessage *pThumbMsg = (CThumbnailThreadMessage *)(pMsg); if (pThumbMsg) { CComPtr pGlobalInterfaceTable; HRESULT hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&pGlobalInterfaceTable); if (SUCCEEDED(hr)) { CComPtr pIWiaItem; hr = pGlobalInterfaceTable->GetInterfaceFromGlobal( pThumbMsg->GlobalInterfaceTableCookie(), IID_IWiaItem, (void**)&pIWiaItem ); if (SUCCEEDED(hr)) { #if defined(DBG) CSimpleStringWide strItemName; PropStorageHelpers::GetProperty( pIWiaItem, WIA_IPA_FULL_ITEM_NAME, strItemName ); WIA_TRACE((TEXT("Getting thumbnail for %ws (0x%d, 0x%p)"), strItemName.String(), pThumbMsg->GlobalInterfaceTableCookie(), pIWiaItem.p )); #endif CComPtr pIWiaPropertyStorage; hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage, (void**)&pIWiaPropertyStorage); if (SUCCEEDED(hr)) { PROPVARIANT PropVar[3]; PROPSPEC PropSpec[3]; PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_IPC_THUMB_WIDTH; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_IPC_THUMB_HEIGHT; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_IPC_THUMBNAIL; hr = pIWiaPropertyStorage->ReadMultiple(ARRAYSIZE(PropSpec),PropSpec,PropVar ); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("Attempting to get the thumbnail for GIT entry: %08X, %08X, %08X, %08X"),pThumbMsg->GlobalInterfaceTableCookie(),PropVar[0].vt,PropVar[1].vt,PropVar[2].vt)); if ((PropVar[0].vt == VT_I4 || PropVar[0].vt == VT_UI4) && (PropVar[1].vt == VT_I4 || PropVar[1].vt == VT_UI4) && (PropVar[2].vt == (VT_UI1|VT_VECTOR))) { UINT nBitmapDataSize = WiaUiUtil::Align(PropVar[0].ulVal*3,sizeof(DWORD)) * PropVar[1].ulVal; if (nBitmapDataSize <= PropVar[2].caub.cElems) { BITMAPINFO bmi = {0}; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = PropVar[0].ulVal; bmi.bmiHeader.biHeight = PropVar[1].ulVal; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; HDC hDC = GetDC(NULL); if (hDC) { PBYTE *pBits; HBITMAP hDibSection = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (PVOID*)&pBits, NULL, 0 ); if (hDibSection) { 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)); CopyMemory( pBits, PropVar[2].caub.pElems, nBitmapDataSize ); hr = ScaleImage( hDC, hDibSection, hBmpThumbnail, pThumbMsg->ThumbSize()); if (SUCCEEDED(hr)) { WIA_TRACE((TEXT("Sending this image (%p) to the notification window: %p"), hBmpThumbnail, pThumbMsg->NotifyWindow() )); } else hBmpThumbnail = NULL; DeleteObject(hDibSection); } else { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateDIBSection failed"))); } ReleaseDC(NULL,hDC); } else { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("GetDC failed"))); } } else { WIA_ERROR((TEXT("nBitmapDataSize <= PropVar[2].caub.cElems was FALSE (%d, %d)"), nBitmapDataSize, PropVar[2].caub.cElems )); } } PropVariantClear(&PropVar[0]); PropVariantClear(&PropVar[1]); PropVariantClear(&PropVar[2]); } else { WIA_PRINTHRESULT((hr,TEXT("pIWiaPropertyStorage->ReadMultiple failed"))); } } else { WIA_PRINTHRESULT((hr,TEXT("QueryInterface failed on IID_IWiaPropertyStorage"))); } } else { WIA_PRINTHRESULT((hr,TEXT("GetInterfaceFromGlobal failed on %08X"), pThumbMsg->GlobalInterfaceTableCookie() )); } } else { WIA_PRINTHRESULT((hr,TEXT("CoCreateInstance failed on CLSID_StdGlobalInterfaceTable"))); } // // Send the message to the UI thread // LRESULT lRes = SendMessage( pThumbMsg->NotifyWindow(), PWM_THUMBNAILSTATUS, (WPARAM)pThumbMsg->GlobalInterfaceTableCookie(), (LPARAM)hBmpThumbnail ); // // If it fails for any reason, we will clean up to avoid leaks // if (HANDLED_THREAD_MESSAGE != lRes) { if (hBmpThumbnail) { DeleteObject( hBmpThumbnail ); } } } else { WIA_ERROR((TEXT("pThumbMsg"))); } return(TRUE); } int CCameraAcquireDialog::FindItemInList( CCameraItem *pItem ) { WIA_PUSH_FUNCTION((TEXT("CCameraAcquireDialog::FindItemInList( %08X )"), pItem )); if (pItem) { HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { for (int i=0;iFullItemName().String(), pItem->FullItemName().String() )); if (*pCurrItem == *pItem) { return i; } } } } } return(-1); } CCameraItem *CCameraAcquireDialog::GetCurrentPreviewItem(void) { CSimpleDynamicArray aSelIndices; GetSelectionIndices(aSelIndices); if (0 == aSelIndices.Size()) return(NULL); if (1 == aSelIndices.Size()) return(GetListItemNode(aSelIndices[0])); return(NULL); } bool CCameraAcquireDialog::SetCurrentPreviewImage( const CSimpleString &strFilename, const CSimpleString &strTitle ) { CWaitCursor wc; bool bResult = true; SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_SETTEXT, 0, (LPARAM)strTitle.String() ); SIZE sizeSavedAspectRatio = m_CurrentAspectRatio; // Set up a reasonable default m_CurrentAspectRatio.cx = 4; m_CurrentAspectRatio.cy = 3; if (strFilename.Length()) { HBITMAP hBmp = (HBITMAP)LoadImage( g_hInstance, strFilename.String(), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE ); if (hBmp) { BITMAP bm; if (GetObject( hBmp, sizeof(BITMAP), &bm )) { m_CurrentAspectRatio.cx = bm.bmWidth; m_CurrentAspectRatio.cy = bm.bmHeight; } } SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_SETBITMAP, MAKEWPARAM(FALSE,FALSE), (LPARAM)hBmp ); if (memcmp(&sizeSavedAspectRatio,&m_CurrentAspectRatio,sizeof(SIZE))) ResizeAll(); bResult = (hBmp != NULL); } else { if (SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_GETBITMAP, 0, 0 )) SendDlgItemMessage( m_hWnd, IDC_PREVIEW, PWM_SETBITMAP, MAKEWPARAM(FALSE,FALSE), 0 ); if (memcmp(&sizeSavedAspectRatio,&m_CurrentAspectRatio,sizeof(SIZE))) ResizeAll(); } InvalidateRect( GetDlgItem( m_hWnd, IDC_PREVIEW ), NULL, FALSE ); UpdateWindow( GetDlgItem( m_hWnd, IDC_PREVIEW ) ); return(bResult); } // wParam = GIT cookie // lParam = nPercent LRESULT CCameraAcquireDialog::OnPreviewPercent( WPARAM wParam, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnPreviewPercent")); CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam ); if (pCameraItem) { pCameraItem->CurrentPreviewPercentage((int)LOWORD(lParam)); CCameraItem *pCurrSel = GetCurrentPreviewItem(); if (pCameraItem == pCurrSel) { UpdatePreview(); } } return(0); } // wParam = GIT cookie // lParam = HBITMAP LRESULT CCameraAcquireDialog::OnPreviewStatus( WPARAM wParam, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnPreviewStatus")); CSimpleString *pstrFilename = reinterpret_cast(lParam); if (pstrFilename) { CCameraItem *pCameraItem = m_CameraItemList.Find( static_cast(wParam) ); if (pCameraItem) { if (!pCameraItem->CancelQueueEvent().Signalled()) { // If we weren't cancelled, set the filename pCameraItem->PreviewFileName(*pstrFilename); } pCameraItem->CloseCancelEvent(); CCameraItem *pCurrSel = GetCurrentPreviewItem(); if (pCameraItem == pCurrSel) { SetCurrentPreviewImage( pCameraItem->PreviewFileName() ); } } delete pstrFilename; } return HANDLED_THREAD_MESSAGE; } LRESULT CCameraAcquireDialog::OnThumbnailStatus( WPARAM wParam, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnThumbnailStatus")); WIA_TRACE((TEXT("Looking for the item with the ID %08X"),wParam)); CCameraItem *pCameraItem = m_CameraItemList.Find( (DWORD)wParam ); if (pCameraItem) { WIA_TRACE((TEXT("Found a CameraItem * (%08X)"),pCameraItem)); HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { WIA_TRACE((TEXT("Got the list control"))); HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL ); if (hImageList) { WIA_TRACE((TEXT("Got the image list"))); if ((HBITMAP)lParam) { WIA_TRACE((TEXT("hBitmap = %p"), lParam)); if (ImageList_Replace( hImageList, pCameraItem->ImageListIndex(), reinterpret_cast(lParam), NULL )) { WIA_TRACE((TEXT("Replaced the image in the list"))); int nItem = FindItemInList(pCameraItem); if (nItem >= 0) { WIA_TRACE((TEXT("Found the item in the list"))); // // Set the image to a dummy image // LV_ITEM lvItem; ::ZeroMemory(&lvItem,sizeof(LV_ITEM)); lvItem.iItem = nItem; lvItem.mask = LVIF_IMAGE; lvItem.iImage = -1; ListView_SetItem( hwndList, &lvItem ); // // Then set the image to the real image // ::ZeroMemory(&lvItem,sizeof(LV_ITEM)); lvItem.iItem = nItem; lvItem.mask = LVIF_IMAGE; lvItem.iImage = pCameraItem->ImageListIndex(); ListView_SetItem( hwndList, &lvItem ); } } } } } } // // Clean up the bitmap, regardless of any other failures, to avoid memory leaks // HBITMAP hBmpThumb = reinterpret_cast(lParam); if (hBmpThumb) { DeleteObject(hBmpThumb); } return HANDLED_THREAD_MESSAGE; } static CThreadMessageMap g_MsgMap[] = { { TQ_DESTROY, CCameraAcquireDialog::OnThreadDestroy }, { TQ_GETTHUMBNAIL, CCameraAcquireDialog::OnGetThumbnail }, { TQ_GETPREVIEW, CCameraAcquireDialog::OnGetPreview }, { TQ_DELETEITEM, CCameraAcquireDialog::OnThreadDeleteItem }, { 0, NULL} }; // // Sole constructor // CCameraAcquireDialog::CCameraAcquireDialog( HWND hWnd ) : m_hWnd(hWnd), m_bPreviewActive(false), m_pCurrentParentItem(NULL), m_bFirstTime(true), m_hBackgroundThread(NULL), m_hBigFont(NULL), m_nDialogMode(0), m_hAccelTable(NULL), m_nListViewWidth(0), m_hIconLarge(NULL), m_hIconSmall(NULL), m_pThreadMessageQueue(NULL), m_bTakePictureIsSupported(false), m_ToolbarBitmapInfo( g_hInstance, IDB_TOOLBAR ) { m_pThreadMessageQueue = new CThreadMessageQueue; if (m_pThreadMessageQueue) { // // Note that CBackgroundThread takes ownership of m_pThreadMessageQueue, and it doesn't have to be deleted in this thread // m_hBackgroundThread = CBackgroundThread::Create( m_pThreadMessageQueue, g_MsgMap, m_CancelEvent.Event(), g_hInstance ); } m_sizeThumbnails.cx = c_nMaxThumbnailWidth; m_sizeThumbnails.cy = c_nMaxThumbnailHeight; m_CurrentAspectRatio.cx = 4; m_CurrentAspectRatio.cy = 3; WIA_ASSERT(m_hBackgroundThread != NULL); } HWND CCameraAcquireDialog::CreateCameraDialogToolbar(VOID) { ToolbarHelper::CButtonDescriptor aSingleSelModeButtons[] = { { 0, IDC_ICONMODE, TBSTATE_ENABLED|TBSTATE_CHECKED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_ICONMODE }, { 1, IDC_PREVIEWMODE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_PREVIEWMODE }, { 2, IDC_TAKEPICTURE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, &m_bTakePictureIsSupported, IDS_TAKEPICTURE }, { 4, IDC_DELETE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, false, NULL, IDS_DELETE_SINGULAR } }; ToolbarHelper::CButtonDescriptor aMultiSelModeButtons[] = { { 0, IDC_ICONMODE, TBSTATE_ENABLED|TBSTATE_CHECKED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_ICONMODE }, { 1, IDC_PREVIEWMODE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON|BTNS_CHECK, true, NULL, IDS_PREVIEWMODE }, { 2, IDC_TAKEPICTURE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, &m_bTakePictureIsSupported, IDS_TAKEPICTURE }, { 3, IDC_SELECTALL, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, true, NULL, IDS_SELECTALL }, { 4, IDC_DELETE, TBSTATE_ENABLED, BTNS_AUTOSIZE|BTNS_BUTTON, false, NULL, IDS_DELETE } }; ToolbarHelper::CButtonDescriptor *pButtonDescriptors = aSingleSelModeButtons; int nButtonDescriptorCount = ARRAYSIZE(aSingleSelModeButtons); if (m_nDialogMode & MULTISEL_MODE) { pButtonDescriptors = aMultiSelModeButtons; nButtonDescriptorCount = ARRAYSIZE(aMultiSelModeButtons); } 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 ); } HRESULT CCameraAcquireDialog::EnumerateItems( CCameraItem *pCurrentParent, IEnumWiaItem *pIEnumWiaItem ) { WIA_PUSHFUNCTION(TEXT("CCameraItemList::EnumerateItems")); HRESULT hr = E_FAIL; if (pIEnumWiaItem != NULL) { hr = pIEnumWiaItem->Reset(); while (hr == S_OK) { CComPtr pIWiaItem; hr = pIEnumWiaItem->Next(1, &pIWiaItem, NULL); if (hr == S_OK) { CCameraItem *pNewCameraItem = new CCameraItem( pIWiaItem ); if (pNewCameraItem && pNewCameraItem->Item()) { LONG ItemType = 0; hr = pNewCameraItem->Item()->GetItemType(&ItemType); if (SUCCEEDED(hr)) { // // If it is an image, add it to the list // if (ItemType & WiaItemTypeImage) { // // Add it to the list // m_CameraItemList.Add( pCurrentParent, pNewCameraItem ); WIA_TRACE((TEXT("Found an image"))); } // // If it is a folder, enumerate its child items and recurse // else if (ItemType & WiaItemTypeFolder) { // // Add this folder to the list // m_CameraItemList.Add( pCurrentParent, pNewCameraItem ); // // Enumerate the child items // CComPtr pIEnumChildItem; if (S_OK == pIWiaItem->EnumChildItems(&pIEnumChildItem)) { EnumerateItems( pNewCameraItem, pIEnumChildItem ); } } else { // // Delete this item, since we didn't add it to the list // delete pNewCameraItem; WIA_TRACE((TEXT("Found something that is NOT an image"))); } } } } } } return hr; } HRESULT CCameraAcquireDialog::EnumerateAllCameraItems(void) { CComPtr pIEnumItem; HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->EnumChildItems(&pIEnumItem); if (hr == S_OK) { hr = EnumerateItems( NULL, pIEnumItem ); } return(hr); } void CCameraAcquireDialog::OnItemCreatedEvent( CGenericWiaEventHandler::CEventMessage *pEventMessage ) { // // Get the listview, which we'll need later // HWND hwndListview = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndListview) { // // Get the image list // HIMAGELIST hImageList = ListView_GetImageList( hwndListview, LVSIL_NORMAL ); if (hImageList) { // // Make sure we don't already have this item // CCameraItem *pCreatedItem = m_CameraItemList.Find(CSimpleBStr(pEventMessage->FullItemName())); if (!pCreatedItem) { // // Get the IWiaItem* for this item // CComPtr pWiaItem; HRESULT hr = m_pDeviceDialogData->pIWiaItemRoot->FindItemByName(0,CSimpleBStr(pEventMessage->FullItemName()).BString(),&pWiaItem); if (SUCCEEDED(hr) && pWiaItem.p) { // // Create an item wrapper // CCameraItem *pNewCameraItem = new CCameraItem( pWiaItem ); if (pNewCameraItem && pNewCameraItem->Item()) { // // Add it to the list // m_CameraItemList.Add( NULL, pNewCameraItem ); // // Generate a thumbnail // CreateThumbnail( pNewCameraItem, hImageList, false ); // // If this item is in the current folder, add it to the listview // if (m_pCurrentParentItem == pNewCameraItem->Parent()) { int nListViewCount = ListView_GetItemCount(hwndListview); // // Add the item // LVITEM lvItem = {0}; lvItem.iItem = nListViewCount; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = pNewCameraItem->ImageListIndex(); lvItem.lParam = reinterpret_cast(pNewCameraItem); int nIndex = ListView_InsertItem( hwndListview, &lvItem ); // // Make sure the new item is visible // if (nIndex >= 0) { ListView_EnsureVisible( hwndListview, nIndex, FALSE ); } } // // Request a thumbnail from the background thread // m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pNewCameraItem->GlobalInterfaceTableCookie(), m_sizeThumbnails ) ); } } } } } } bool CCameraAcquireDialog::PopulateList( CCameraItem *pOldParent ) { // // Which item should be selected? // int nSelItem = 0; // // Get the list view control // HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { // // Empty the list // ListView_DeleteAllItems( hwndList ); // // Where to insert the current item // int nCurrentItem = 0; CCameraItem *pCurr; // // If this is a child directory... // if (m_pCurrentParentItem) { // // Start adding children // pCurr = m_pCurrentParentItem->Children(); // // Insert a dummy item that the user can use to switch to the parent directory // LVITEM lvItem; ZeroMemory( &lvItem, sizeof(lvItem) ); lvItem.iItem = nCurrentItem++; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = m_nParentFolderImageListIndex; lvItem.lParam = 0; ListView_InsertItem( hwndList, &lvItem ); } // // Otherwise, we are at the root // else pCurr = m_CameraItemList.Root(); // // Iterate through this list of images, and add each one // while (pCurr) { // // If this is the last parent directory, we want it to be selected instead of the first image // if (pOldParent && *pCurr == *pOldParent) { nSelItem = nCurrentItem; } // // If this image hasn't been deleted // if (pCurr->DeleteState() != CCameraItem::Delete_Deleted) { // // Add the item // LVITEM lvItem = {0}; lvItem.iItem = nCurrentItem++; lvItem.mask = LVIF_IMAGE|LVIF_PARAM; lvItem.iImage = pCurr->ImageListIndex(); lvItem.lParam = reinterpret_cast(pCurr); int nIndex = ListView_InsertItem( hwndList, &lvItem ); if (nIndex >= 0 && pCurr->DeleteState() == CCameraItem::Delete_Pending) { MarkItemDeletePending(nIndex,true); } } // // Advance // pCurr = pCurr->Next(); } } // // If we've not calculated the width of the list in preview mode, attempt to do it // if (!m_nListViewWidth) { RECT rcItem; if (ListView_GetItemRect( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), 0, &rcItem, LVIR_ICON )) { m_nListViewWidth = (rcItem.right-rcItem.left) + rcItem.left * 2 + GetSystemMetrics(SM_CXHSCROLL) + c_nAdditionalMarginX; } } // // Set the selected item to either the previous directory, or the first image // SetSelectedListItem(nSelItem); return(true); } void CCameraAcquireDialog::CreateThumbnail( CCameraItem *pCurr, HIMAGELIST hImageList, bool bForce ) { // // Make sure we have a valid item // if (pCurr && (pCurr->ImageListIndex()<0 || bForce)) { // // Get the item name // CSimpleStringWide strItemName; PropStorageHelpers::GetProperty( pCurr->Item(), WIA_IPA_ITEM_NAME, strItemName ); // // Create the title for the icon // CSimpleString strIconTitle; if (pCurr->IsFolder()) { strIconTitle = CSimpleStringConvert::NaturalString(strItemName); } else if (strItemName.Length()) { strIconTitle.Format( IDS_DOWNLOADINGTHUMBNAIL, g_hInstance, CSimpleStringConvert::NaturalString(strItemName).String() ); } // // Create the thumbnail // HBITMAP hBmp = WiaUiUtil::CreateIconThumbnail( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, pCurr->IsImage()?IDI_UNAVAILABLE:IDI_FOLDER, strIconTitle ); if (hBmp) { // // If we don't have an image yet, add it // if (pCurr->ImageListIndex()<0) { pCurr->ImageListIndex(ImageList_Add( hImageList, hBmp, NULL )); } // // Otherwise, replace it // else { pCurr->ImageListIndex(ImageList_Replace( hImageList, pCurr->ImageListIndex(), hBmp, NULL )); } // // Delete it, since the imagelist makes a copy // DeleteObject(hBmp); } } } void CCameraAcquireDialog::CreateThumbnails( CCameraItem *pRoot, HIMAGELIST hImageList, bool bForce ) { CCameraItem *pCurr = pRoot; while (pCurr) { // // Create the thumbnail // CreateThumbnail( pCurr, hImageList, bForce ); // // If there are children, recurse into that list // CreateThumbnails( pCurr->Children(), hImageList, bForce ); // // Advance // pCurr = pCurr->Next(); } } void CCameraAcquireDialog::RequestThumbnails( CCameraItem *pRoot ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::RequestThumbnails")); CCameraItem *pCurr = pRoot; while (pCurr) { if (pCurr->IsImage()) { m_pThreadMessageQueue->Enqueue( new CThumbnailThreadMessage( m_hWnd, pCurr->GlobalInterfaceTableCookie(), m_sizeThumbnails ) ); } if (pCurr->Children()) { RequestThumbnails( pCurr->Children() ); } pCurr = pCurr->Next(); } } void CCameraAcquireDialog::CreateThumbnails( bool bForce ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { HIMAGELIST hImageList = ListView_GetImageList( hwndList, LVSIL_NORMAL ); if (hImageList) { // // Create the parent folder image // HBITMAP hParentBitmap = WiaUiUtil::CreateIconThumbnail( hwndList, m_sizeThumbnails.cx, m_sizeThumbnails.cy, g_hInstance, IDI_PARENTFOLDER, TEXT("(..)") ); if (hParentBitmap) { m_nParentFolderImageListIndex = ImageList_Add( hImageList, hParentBitmap, NULL ); DeleteObject(hParentBitmap); } CCameraAcquireDialog::CreateThumbnails( m_CameraItemList.Root(), hImageList, bForce ); } } } bool CCameraAcquireDialog::FindMaximumThumbnailSize(void) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::FindMaximumThumbnailSize")); bool bResult = false; if (m_pDeviceDialogData && m_pDeviceDialogData->pIWiaItemRoot) { LONG nWidth, nHeight; if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nWidth ) && PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DPC_THUMB_WIDTH, nHeight )) { m_sizeThumbnails.cx = max(c_nMinThumbnailWidth,min(nWidth,c_nMaxThumbnailWidth)); m_sizeThumbnails.cy = max(c_nMinThumbnailHeight,min(nHeight,c_nMaxThumbnailHeight)); } else WIA_TRACE((TEXT("FindMaximumThumbnailSize: Unable to retrieve thumbnail size for device"))); } return(bResult && m_sizeThumbnails.cx && m_sizeThumbnails.cy); } // // Hook procedure and static variables used to handle accelerators // LRESULT CALLBACK CCameraAcquireDialog::DialogHookProc( int nCode, WPARAM wParam, LPARAM lParam ) { if (nCode < 0) return CallNextHookEx( s_hMessageHook, nCode, wParam, lParam ); if (nCode == MSGF_DIALOGBOX) { MSG *pMsg = reinterpret_cast(lParam); if (pMsg) { if (pMsg->hwnd == s_hWndDialog || (s_hWndDialog && IsChild(s_hWndDialog,pMsg->hwnd))) { CCameraAcquireDialog *pCameraAcquireDialog = reinterpret_cast(GetWindowLongPtr(s_hWndDialog,DWLP_USER)); if (pCameraAcquireDialog && pCameraAcquireDialog->m_hAccelTable) { if (TranslateAccelerator(s_hWndDialog,pCameraAcquireDialog->m_hAccelTable,pMsg)) return 1; // Ensure the window won't process the message } } } } return CallNextHookEx( s_hMessageHook, nCode, wParam, lParam ); } LRESULT CCameraAcquireDialog::OnInitDialog( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnInitDialog")); CWaitCursor wc; // // Make sure the background queue was successfully created // if (!m_pThreadMessageQueue) { WIA_ERROR((TEXT("CAMDLG: unable to start background queue"))); EndDialog( m_hWnd, E_OUTOFMEMORY ); return(0); } m_pDeviceDialogData = (PDEVICEDIALOGDATA)lParam; // Save the window handle for the hook s_hWndDialog = m_hWnd; // Install the message hook, which we use for accelerator support s_hMessageHook = SetWindowsHookEx( WH_MSGFILTER, DialogHookProc, g_hInstance, GetCurrentThreadId() ); if (!s_hMessageHook) { WIA_ERROR((TEXT("CAMDLG: Unable to set thread msg hook"))); EndDialog( m_hWnd, HRESULT_FROM_WIN32(GetLastError())); return(0); } // Make sure we have valid arguments if (!m_pDeviceDialogData) { WIA_ERROR((TEXT("CAMDLG: Invalid paramater: PDEVICEDIALOGDATA"))); EndDialog( m_hWnd, E_INVALIDARG ); return(0); } // Initialialize our return stuff if (m_pDeviceDialogData) { m_pDeviceDialogData->lItemCount = 0; m_pDeviceDialogData->ppWiaItems = NULL; } // Make sure we have valid a valid device if (!m_pDeviceDialogData->pIWiaItemRoot) { WIA_ERROR((TEXT("CAMDLG: Invalid paramaters: pIWiaItem"))); EndDialog( m_hWnd, E_INVALIDARG ); return(0); } // // Find out if Take Picture is supported // m_bTakePictureIsSupported = WiaUiUtil::IsDeviceCommandSupported( m_pDeviceDialogData->pIWiaItemRoot, WIA_CMD_TAKE_PICTURE ); // Prevent multiple selection if (m_pDeviceDialogData->dwFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE) { LONG_PTR lStyle = GetWindowLongPtr( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), GWL_STYLE ); SetWindowLongPtr( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), GWL_STYLE, lStyle | LVS_SINGLESEL ); // Set the single sel titles CSimpleString( IDS_TITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ) ); CSimpleString( IDS_SUBTITLE_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ) ); CSimpleString( IDS_OK_SINGLE_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) ); m_nDialogMode = SINGLESEL_MODE; } else { // Set the multi sel subtitle CSimpleString( IDS_TITLE_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ) ); CSimpleString( IDS_SUBTITLE_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ) ); CSimpleString( IDS_OK_MULTI_SEL, g_hInstance ).SetWindowText( GetDlgItem( m_hWnd, IDOK ) ); m_nDialogMode = MULTISEL_MODE; } // Make the lovely font m_hBigFont = WiaUiUtil::CreateFontWithPointSizeFromWindow( GetDlgItem(m_hWnd,IDC_CAMDLG_BIG_TITLE), 14, false, false ); if (m_hBigFont) SendDlgItemMessage( m_hWnd, IDC_CAMDLG_BIG_TITLE, WM_SETFONT, reinterpret_cast(m_hBigFont), MAKELPARAM(TRUE,0)); // Create the Tool Bar and resize the dialog to accommodate it (void)CreateCameraDialogToolbar(); // Get the minimum size of the dialog RECT rcWindow; GetWindowRect( m_hWnd, &rcWindow ); m_sizeMinimumWindow.cx = rcWindow.right - rcWindow.left; m_sizeMinimumWindow.cy = rcWindow.bottom - rcWindow.top; // Initialize the preview control WiaPreviewControl_AllowNullSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE ); WiaPreviewControl_ClearSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ) ); WiaPreviewControl_DisableSelection( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE ); WiaPreviewControl_SetBorderSize( GetDlgItem( m_hWnd, IDC_PREVIEW ), FALSE, FALSE, 0 ); WiaPreviewControl_SetBgAlpha( GetDlgItem( m_hWnd, IDC_PREVIEW ), FALSE, 0xFF ); // Set the lovely title CSimpleStringWide strwDeviceName; if (PropStorageHelpers::GetProperty( m_pDeviceDialogData->pIWiaItemRoot, WIA_DIP_DEV_NAME, strwDeviceName )) { CSimpleString().Format( IDS_CAMERADLG_TITLE, g_hInstance, strwDeviceName.String() ).SetWindowText( m_hWnd ); } // Create the sizing control (void)CreateWindowEx( 0, TEXT("scrollbar"), TEXT(""), WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP|WS_CLIPSIBLINGS|SBS_SIZEBOXBOTTOMRIGHTALIGN|SBS_BOTTOMALIGN|WS_GROUP, CSimpleRect(m_hWnd).Width()-GetSystemMetrics(SM_CXVSCROLL), CSimpleRect(m_hWnd).Height()-GetSystemMetrics(SM_CYHSCROLL), GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL), m_hWnd, reinterpret_cast(IDC_SIZEBOX), g_hInstance, NULL ); // Reposition all the controls ResizeAll(); // Center the window over its parent WiaUiUtil::CenterWindow( m_hWnd, GetParent(m_hWnd) ); // Get the device icons and set the window icons CSimpleStringWide strwDeviceId, strwClassId; LONG nDeviceType; if (PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_UI_CLSID,strwClassId) && PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_ID,strwDeviceId) && PropStorageHelpers::GetProperty(m_pDeviceDialogData->pIWiaItemRoot,WIA_DIP_DEV_TYPE,nDeviceType)) { // // Register for disconnect event // CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_DEVICE_DISCONNECTED, &m_DisconnectEvent, m_hWnd, PWM_WIAEVENT ); CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_ITEM_DELETED, &m_DeleteItemEvent, m_hWnd, PWM_WIAEVENT ); CGenericWiaEventHandler::RegisterForWiaEvent( strwDeviceId.String(), WIA_EVENT_ITEM_CREATED, &m_CreateItemEvent, m_hWnd, PWM_WIAEVENT ); if (SUCCEEDED(WiaUiExtensionHelper::GetDeviceIcons( CSimpleBStr(strwClassId), nDeviceType, &m_hIconSmall, &m_hIconLarge ))) { if (m_hIconSmall) { SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, reinterpret_cast(m_hIconSmall) ); } if (m_hIconLarge) { SendMessage( m_hWnd, WM_SETICON, ICON_BIG, reinterpret_cast(m_hIconLarge) ); } } } int nAcceleratorCount = 0; ACCEL Accelerators[10]; // // Load the accelerator table resource and convert it to an ACCEL array // HACCEL hAccel = LoadAccelerators( g_hInstance, MAKEINTRESOURCE(IDR_CAMERA_ACCEL) ); if (hAccel) { // // Copy the accelerator table to an array of ACCEL // nAcceleratorCount = CopyAcceleratorTable( hAccel, Accelerators, ARRAYSIZE(Accelerators) ); // // Free the accelerator table // DestroyAcceleratorTable( hAccel ); } // // Create the accelerator table for the toolbar // nAcceleratorCount += ToolbarHelper::GetButtonBarAccelerators( GetDlgItem( m_hWnd, IDC_TOOLBAR ), Accelerators+nAcceleratorCount, ARRAYSIZE(Accelerators)-nAcceleratorCount ); if (nAcceleratorCount) { m_hAccelTable = CreateAcceleratorTable( Accelerators, nAcceleratorCount ); if (!m_hAccelTable) { WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreateAcceleratorTable failed"))); } } SetForegroundWindow(m_hWnd); // // Make sure the listview has the focus // SetFocus( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) ); return (TRUE); } VOID CCameraAcquireDialog::ResizeAll(VOID) { CSimpleRect rcClient(m_hWnd); CMoveWindow mw; CDialogUnits dialogUnits(m_hWnd); // Resize the big title mw.Size( GetDlgItem( m_hWnd, IDC_CAMDLG_BIG_TITLE ), rcClient.Width() - dialogUnits.StandardMargin().cx * 2, 0, CMoveWindow::NO_SIZEY ); // Resize the subtitle mw.Size( GetDlgItem( m_hWnd, IDC_CAMDLG_SUBTITLE ), rcClient.Width() - dialogUnits.StandardMargin().cx * 2, 0, CMoveWindow::NO_SIZEY ); int nToolBarHeight = (int)(HIWORD((DWORD)(SendMessage(GetDlgItem( m_hWnd, IDC_TOOLBAR ), TB_GETBUTTONSIZE, 0,0)))); // Resize the toolbar frame mw.Size( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME), rcClient.Width() - dialogUnits.StandardMargin().cx * 2, nToolBarHeight + 4, 0 ); // Get the dialog's client coordinates of the toolbar frame's client rect CSimpleRect rcToolbarFrameInside( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME), CSimpleRect::ClientRect ); rcToolbarFrameInside = rcToolbarFrameInside.ClientToScreen(GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME)); rcToolbarFrameInside = rcToolbarFrameInside.ScreenToClient(m_hWnd); // Move and resize the toolbar mw.SizeMove( GetDlgItem( m_hWnd, IDC_TOOLBAR ), rcToolbarFrameInside.left + 2, rcToolbarFrameInside.top + 2, rcClient.Width() - dialogUnits.StandardMargin().cx * 2 - 4, nToolBarHeight, 0 ); // Save the bottom of this control for later int nBottomOfToolbarFrame = CSimpleRect( GetDlgItem(m_hWnd,IDC_TOOLBAR_FRAME), CSimpleRect::WindowRect ).ScreenToClient(m_hWnd).top + nToolBarHeight + 4; // Move the Properties control mw.SizeMove( GetDlgItem( m_hWnd, IDC_CAMDLG_PROPERTIES ), 0, rcClient.Height() - dialogUnits.StandardMargin().cy - dialogUnits.Y(8) + 2, dialogUnits.StandardMargin().cx, dialogUnits.Y(8) + 2, CMoveWindow::NO_MOVEX|CMoveWindow::NO_SIZEX ); // Move the static text above it mw.Move( GetDlgItem( m_hWnd, IDC_YOU_CAN_ALSO ), dialogUnits.StandardMargin().cx, rcClient.Height() - dialogUnits.StandardMargin().cy - dialogUnits.Y(8) - 2 - dialogUnits.Y(8) ); CSimpleRect rcOK( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect ); CSimpleRect rcCancel( GetDlgItem( m_hWnd, IDOK ), CSimpleRect::WindowRect ); // Move the OK button mw.Move( GetDlgItem( m_hWnd, IDOK ), rcClient.Width() - dialogUnits.StandardMargin().cx - dialogUnits.StandardButtonMargin().cx - rcCancel.Width() - rcOK.Width(), rcClient.Height() - dialogUnits.StandardMargin().cy - rcOK.Height(), 0 ); // Move the cancel button mw.Move( GetDlgItem( m_hWnd, IDCANCEL ), rcClient.Width() - dialogUnits.StandardMargin().cx - rcCancel.Width(), rcClient.Height() - dialogUnits.StandardMargin().cy - rcCancel.Height(), 0 ); // Move the resizing handle mw.Move( GetDlgItem( m_hWnd, IDC_SIZEBOX ), rcClient.Width() - GetSystemMetrics(SM_CXVSCROLL), rcClient.Height() - GetSystemMetrics(SM_CYHSCROLL) ); int nHeightOfBottomControls = dialogUnits.Y(8) + 2 + // Highlight control dialogUnits.Y(8) + // Static description text dialogUnits.StandardMargin().cy; // Top of these controls CSimpleRect rcAvailableArea( dialogUnits.StandardMargin().cx, nBottomOfToolbarFrame + dialogUnits.StandardMargin().cy, rcClient.right - dialogUnits.StandardMargin().cx, rcClient.bottom - nHeightOfBottomControls - dialogUnits.StandardMargin().cy ); if (m_bPreviewActive) { // If we've already calculated the actual width of the preview mode list, use it, otherwise use the default int nListViewWidth = m_nListViewWidth ? m_nListViewWidth : c_nDefaultListViewWidth; // Move the thumbnail list mw.SizeMove( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), rcAvailableArea.left, rcAvailableArea.top, nListViewWidth, rcAvailableArea.Height() ); // Remove the rect of the list view from the preview area rcAvailableArea.left += nListViewWidth + dialogUnits.StandardMargin().cx; // Use up the remaining area mw.SizeMove( GetDlgItem( m_hWnd, IDC_PREVIEW ), rcAvailableArea.left, rcAvailableArea.top, rcAvailableArea.Width(), rcAvailableArea.Height() ); } else { // Move the thumbnail list mw.SizeMove( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), rcAvailableArea.left, rcAvailableArea.top, rcAvailableArea.Width(), rcAvailableArea.Height() ); } // Explicitly apply the moves, because the toolbar frame doesn't get painted properly mw.Apply(); if (m_bPreviewActive) { // Show the preview in case it isn't visible mw.Show( GetDlgItem( m_hWnd, IDC_PREVIEW ) ); } else { // Hide the preview in case it is visible mw.Hide( GetDlgItem( m_hWnd, IDC_PREVIEW ) ); } // // Update the dialog's background to remove any weird stuff left behind // InvalidateRect( m_hWnd, NULL, FALSE ); UpdateWindow( m_hWnd ); } LRESULT CCameraAcquireDialog::OnItemDeleted( WPARAM wParam, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnItemDeleted")); CCameraItem *pDeletedItem = m_CameraItemList.Find((DWORD)wParam); if (pDeletedItem) { BOOL bSuccess = (BOOL)lParam; pDeletedItem->DeleteState( bSuccess ? CCameraItem::Delete_Deleted : CCameraItem::Delete_Visible ); if (pDeletedItem == m_pCurrentParentItem) { ChangeFolder(m_pCurrentParentItem->Parent()); } int nIndex = FindItemInList(pDeletedItem); if (nIndex >= 0) { if (bSuccess) { // Remove the item from the list ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),nIndex); // Make sure we leave something selected if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ))) { int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST )); if (nItemCount) { if (nIndex >= nItemCount) nIndex = nItemCount-1; SetSelectedListItem(nIndex); } } else { // Make sure we update control's state when the list is empty HandleSelectionChange(); } } else { // If the delete failed, remove the deleted state MarkItemDeletePending(nIndex,false); // Tell the user MessageBeep( MB_ICONASTERISK ); } } } return (0); } LRESULT CCameraAcquireDialog::OnWiaEvent( WPARAM, LPARAM lParam ) { WIA_PUSHFUNCTION(TEXT("CCameraAcquireDialog::OnWiaEvent")); CGenericWiaEventHandler::CEventMessage *pEventMessage = reinterpret_cast(lParam); if (pEventMessage) { if (pEventMessage->EventId() == WIA_EVENT_DEVICE_DISCONNECTED) { WIA_TRACE((TEXT("Received disconnect event"))); EndDialog( m_hWnd, WIA_ERROR_OFFLINE ); } else if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED) { OnItemCreatedEvent( pEventMessage ); } else if (pEventMessage->EventId() == WIA_EVENT_ITEM_DELETED) { WIA_TRACE((TEXT("Received deleted item event"))); CCameraItem *pDeletedItem = m_CameraItemList.Find(CSimpleBStr(pEventMessage->FullItemName())); if (pDeletedItem) { // // If we're deleting the current parent item, // select a new one. // if (pDeletedItem == m_pCurrentParentItem) { ChangeFolder(m_pCurrentParentItem->Parent()); } int nIndex = FindItemInList(pDeletedItem); if (nIndex >= 0) { // // Remove the item from the listview // ListView_DeleteItem(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ),nIndex); // // Make sure we leave something selected // if (!ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ))) { int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST )); if (nItemCount) { if (nIndex >= nItemCount) { nIndex = nItemCount-1; } SetSelectedListItem(nIndex); } } else { // // Make sure we update control's state when the list is empty // HandleSelectionChange(); } } else { WIA_ERROR((TEXT("FindItemInList coulnd't find the item"))); } // // Mark the item as deleted. // pDeletedItem->DeleteState( CCameraItem::Delete_Deleted ); } else { WIA_ERROR((TEXT("The item could not be found in m_CameraItemList"))); } } delete pEventMessage; } return HANDLED_EVENT_MESSAGE; } LRESULT CCameraAcquireDialog::OnEnterSizeMove( WPARAM, LPARAM ) { SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_ENTERSIZEMOVE, 0, 0 ); return(0); } LRESULT CCameraAcquireDialog::OnExitSizeMove( WPARAM, LPARAM ) { SendDlgItemMessage( m_hWnd, IDC_PREVIEW, WM_EXITSIZEMOVE, 0, 0 ); return(0); } LRESULT CCameraAcquireDialog::OnSize( WPARAM, LPARAM ) { ResizeAll(); return(0); } LRESULT CCameraAcquireDialog::OnShow( WPARAM, LPARAM ) { if (m_bFirstTime) { PostMessage( m_hWnd, PWM_POSTINIT, 0, 0 ); m_bFirstTime = false; } return(0); } LRESULT CCameraAcquireDialog::OnGetMinMaxInfo( WPARAM, LPARAM lParam ) { LPMINMAXINFO pMinMaxInfo = (LPMINMAXINFO)lParam; pMinMaxInfo->ptMinTrackSize.x = m_sizeMinimumWindow.cx; pMinMaxInfo->ptMinTrackSize.y = m_sizeMinimumWindow.cy; return(0); } LRESULT CCameraAcquireDialog::OnDestroy( WPARAM, LPARAM ) { // // Get rid of all preview requests // CancelAllPreviewRequests( m_CameraItemList.Root() ); // // Tell the background thread to destroy itself // m_pThreadMessageQueue->Enqueue( new CThreadMessage(TQ_DESTROY),CThreadMessageQueue::PriorityUrgent); // // Set the window icon to NULL // SendMessage( m_hWnd, WM_SETICON, ICON_BIG, 0 ); SendMessage( m_hWnd, WM_SETICON, ICON_SMALL, 0 ); // // Clear the image list and list view. This should be unnecessary, but BoundsChecker // complains if I don't do it. // HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { ListView_DeleteAllItems(hwndList); HIMAGELIST hImgList = ListView_SetImageList( hwndList, NULL, LVSIL_NORMAL ); if (hImgList) { ImageList_Destroy(hImgList); } } // // Delete resources // if (m_hBigFont) { DeleteObject(m_hBigFont); m_hBigFont = NULL; } if (m_hImageList) { m_hImageList = NULL; } if (m_hAccelTable) { DestroyAcceleratorTable(m_hAccelTable); m_hAccelTable = NULL; } if (s_hMessageHook) { UnhookWindowsHookEx(s_hMessageHook); s_hMessageHook = NULL; } if (m_hIconLarge) { DestroyIcon(m_hIconLarge); m_hIconLarge = NULL; } if (m_hIconSmall) { DestroyIcon(m_hIconSmall); m_hIconSmall = NULL; } if (m_hBackgroundThread) { CloseHandle(m_hBackgroundThread); m_hBackgroundThread = NULL; } return(0); } VOID CCameraAcquireDialog::OnPreviewMode( WPARAM, LPARAM ) { m_bPreviewActive = true; SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PREVIEWMODE, MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0) ); SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_ICONMODE, MAKELONG(TBSTATE_ENABLED,0) ); ResizeAll(); UpdatePreview(); } VOID CCameraAcquireDialog::OnTakePicture( WPARAM, LPARAM ) { // // Tell the device to snap a picture // if (m_pDeviceDialogData->pIWiaItemRoot && m_bTakePictureIsSupported) { CWaitCursor wc; CComPtr pNewWiaItem; m_pDeviceDialogData->pIWiaItemRoot->DeviceCommand(0,&WIA_CMD_TAKE_PICTURE,&pNewWiaItem); } } VOID CCameraAcquireDialog::OnIconMode( WPARAM, LPARAM ) { m_bPreviewActive = false; SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_ICONMODE, MAKELONG(TBSTATE_ENABLED|TBSTATE_CHECKED,0) ); SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, TB_SETSTATE, IDC_PREVIEWMODE, MAKELONG(TBSTATE_ENABLED,0) ); ResizeAll(); UpdatePreview(); } LRESULT CCameraAcquireDialog::OnPostInit( WPARAM, LPARAM ) { // // Create the progress dialog // CComPtr pWiaProgressDialog; HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaProgressDialog, (void**)&pWiaProgressDialog ); if (SUCCEEDED(hr)) { // // Initialize the progress dialog // pWiaProgressDialog->Create( m_hWnd, WIA_PROGRESSDLG_ANIM_CAMERA_COMMUNICATE|WIA_PROGRESSDLG_NO_PROGRESS|WIA_PROGRESSDLG_NO_CANCEL|WIA_PROGRESSDLG_NO_TITLE ); pWiaProgressDialog->SetTitle( CSimpleStringConvert::WideString(CSimpleString(IDS_CAMDLG_PROGDLG_TITLE,g_hInstance))); pWiaProgressDialog->SetMessage( CSimpleStringConvert::WideString(CSimpleString(IDS_CAMDLG_PROGDLG_MESSAGE,g_hInstance))); // // Show the progress dialog // pWiaProgressDialog->Show(); // // Find all of the images in the camera // EnumerateAllCameraItems(); // // Find the largest possible thumbnail // FindMaximumThumbnailSize(); // // Initialize Thumbnail Listview control // HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { // // Get rid of the border and icon labels // ListView_SetExtendedListViewStyleEx( hwndList, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_DOUBLEBUFFER, LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_DOUBLEBUFFER ); // // Create the large image list // m_hImageList = ImageList_Create( m_sizeThumbnails.cx, m_sizeThumbnails.cy, ILC_COLOR24|ILC_MIRROR, 50, 50 ); if (m_hImageList) { // // Set the image list // ListView_SetImageList( hwndList, m_hImageList, LVSIL_NORMAL ); } // // Set the icon spacing // ListView_SetIconSpacing( hwndList, m_sizeThumbnails.cx + c_nAdditionalMarginX, m_sizeThumbnails.cy + c_nAdditionalMarginY ); } // // Create all of the initial thumbnails // CreateThumbnails(); // // This causes the list to be populated // ChangeFolder(NULL); // // Force a selection change // HandleSelectionChange(); // // Download all of the thumbnails // RequestThumbnails( m_CameraItemList.Root() ); // // Close the progress dialog // pWiaProgressDialog->Destroy(); } return(0); } LRESULT CCameraAcquireDialog::OnChangeToParent( WPARAM, LPARAM ) { if (m_pCurrentParentItem) ChangeFolder(m_pCurrentParentItem->Parent()); return(0); } VOID CCameraAcquireDialog::OnParentDir( WPARAM, LPARAM ) { if (m_pCurrentParentItem && m_pCurrentParentItem->Parent()) ChangeFolder(m_pCurrentParentItem->Parent()); else ChangeFolder(NULL); } void CCameraAcquireDialog::MarkItemDeletePending( int nIndex, bool bSet ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (hwndList) { ListView_SetItemState( hwndList, nIndex, bSet ? LVIS_CUT : 0, LVIS_CUT ); } } // Recursively delete items void CCameraAcquireDialog::DeleteItem( CCameraItem *pItemNode ) { if (pItemNode) { CCameraItem *pChild = pItemNode->Children(); while (pChild) { DeleteItem(pChild); pChild = pChild->Next(); } if (pItemNode->DeleteState() == CCameraItem::Delete_Visible) { int nIndex = FindItemInList( pItemNode ); if (nIndex >= 0) { // // Mark it pending in the UI // MarkItemDeletePending(nIndex,true); } // // Mark it pending // pItemNode->DeleteState( CCameraItem::Delete_Pending ); // // Fire off the request // m_pThreadMessageQueue->Enqueue( new CDeleteThreadMessage(m_hWnd, pItemNode->GlobalInterfaceTableCookie()), CThreadMessageQueue::PriorityHigh ); } } } VOID CCameraAcquireDialog::OnDelete( WPARAM, LPARAM ) { CSimpleDynamicArray aSelIndices; if (GetSelectionIndices( aSelIndices )) { // // We only want to show the confirm dialog once // bool bShowConfirmDialog = true; for (int i=0;iDeleteState() == CCameraItem::Delete_Visible && pItemNode->ItemRights() & WIA_ITEM_CAN_BE_DELETED) { if (bShowConfirmDialog) { bShowConfirmDialog = false; if (IDYES!=MessageBox( m_hWnd, CSimpleString( IDS_DELETE_CONFIRM, g_hInstance ), CSimpleString( IDS_DELETE_CONFIRM_TITLE, g_hInstance ), MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 )) { break; } } DeleteItem( pItemNode ); } } } } int CCameraAcquireDialog::GetSelectionIndices( CSimpleDynamicArray &aIndices ) { HWND hwndList = GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ); if (!hwndList) return(0); int iCount = ListView_GetItemCount(hwndList); for (int i=0;i aSelIndices; if (GetSelectionIndices(aSelIndices)) { // // Find out if only folders are selected // bool bOnlyFoldersSelected = true; for (int i=0;iIsFolder()) { bOnlyFoldersSelected = false; break; } } WIA_TRACE((TEXT("bOnlyFoldersSelected = %d"),bOnlyFoldersSelected)); // // If only folders are selected, switch to the first selected folder // if (bOnlyFoldersSelected && aSelIndices.Size()) { CCameraItem *pItemNode = GetListItemNode(aSelIndices[0]); if (!pItemNode) { // // NULL item node == parent folder // SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 ); return(true); } if (pItemNode && pItemNode->IsFolder() && pItemNode->DeleteState() == CCameraItem::Delete_Visible) { if (ChangeFolder(pItemNode)) { return(true); } } } } return(false); } VOID CCameraAcquireDialog::OnOK( WPARAM, LPARAM ) { if (!ChangeToSelectedFolder()) { HRESULT hr = S_OK; m_pDeviceDialogData->lItemCount = 0; m_pDeviceDialogData->ppWiaItems = NULL; CSimpleDynamicArray aIndices; GetSelectionIndices( aIndices ); if (aIndices.Size()) { int nArraySizeInBytes = sizeof(IWiaItem*) * aIndices.Size(); m_pDeviceDialogData->ppWiaItems = (IWiaItem**)CoTaskMemAlloc(nArraySizeInBytes); if (m_pDeviceDialogData->ppWiaItems) { ZeroMemory( m_pDeviceDialogData->ppWiaItems, nArraySizeInBytes ); int nCurrItem = 0; for (int i=0;iItem() && pItem->IsImage() && pItem->DeleteState() == CCameraItem::Delete_Visible) { m_pDeviceDialogData->ppWiaItems[nCurrItem] = pItem->Item(); m_pDeviceDialogData->ppWiaItems[nCurrItem]->AddRef(); nCurrItem++; } } m_pDeviceDialogData->lItemCount = nCurrItem; } else { // Unable to alloc mem hr = E_OUTOFMEMORY; } } else { return; } EndDialog( m_hWnd, hr ); } } VOID CCameraAcquireDialog::OnCancel( WPARAM, LPARAM ) { EndDialog( m_hWnd, S_FALSE ); } VOID CCameraAcquireDialog::OnSelectAll( WPARAM, LPARAM ) { ListView_SetItemState( GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ), -1, LVIS_SELECTED, LVIS_SELECTED ); } VOID CCameraAcquireDialog::OnProperties( WPARAM, LPARAM ) { CSimpleDynamicArray aSelIndices; if (GetSelectionIndices( aSelIndices )) { if (aSelIndices.Size() == 1) { CCameraItem *pItemNode = GetListItemNode(aSelIndices[0]); if (pItemNode && pItemNode->Item()) { m_pThreadMessageQueue->Pause(); HRESULT hr = WiaUiUtil::SystemPropertySheet( g_hInstance, m_hWnd, pItemNode->Item(), CSimpleString( IDS_CAMDLG_PROPERTIES_TITLE, g_hInstance ) ); if (!SUCCEEDED(hr)) { if (PROP_SHEET_ERROR_NO_PAGES == hr) { MessageBox( m_hWnd, CSimpleString( IDS_CAMDLG_PROPSHEETNOPAGES, g_hInstance ), CSimpleString( IDS_CAMDLG_ERROR_TITLE, g_hInstance ), MB_ICONINFORMATION ); } else { MessageBox( m_hWnd, CSimpleString( IDS_CAMDLG_PROPSHEETERROR, g_hInstance ), CSimpleString( IDS_CAMDLG_ERROR_TITLE, g_hInstance ), MB_ICONINFORMATION ); } WIA_PRINTHRESULT((hr,TEXT("SystemPropertySheet failed"))); } m_pThreadMessageQueue->Resume(); } } } } LRESULT CCameraAcquireDialog::OnDblClkImageList( WPARAM, LPARAM ) { SendMessage( m_hWnd, WM_COMMAND, MAKEWPARAM(IDOK,0), 0 ); return(0); } void CCameraAcquireDialog::CancelAllPreviewRequests( CCameraItem *pRoot ) { CCameraItem *pCurr = pRoot; while (pCurr) { if (pCurr->PreviewRequestPending()) pCurr->SetCancelEvent(); if (pCurr->Children()) CancelAllPreviewRequests( pCurr->Children() ); pCurr = pCurr->Next(); } } void CCameraAcquireDialog::UpdatePreview(void) { if (m_bPreviewActive) { CCameraItem *pCurrPreviewItem = GetCurrentPreviewItem(); if (pCurrPreviewItem && pCurrPreviewItem->IsImage()) { // If we're not already downloading this preview image... if (!pCurrPreviewItem->PreviewRequestPending()) { // Cancel all other preview requests CancelAllPreviewRequests( m_CameraItemList.Root() ); if (pCurrPreviewItem->PreviewFileName().Length()) { // Set the preview if we've got it cached SetCurrentPreviewImage( pCurrPreviewItem->PreviewFileName() ); } else { CSimpleString strPct; strPct.Format( IDS_DOWNLOADINGPREVIEW, g_hInstance, 0 ); // Clear the preview window SetCurrentPreviewImage( TEXT(""), strPct ); // Create our cancel event pCurrPreviewItem->CreateCancelEvent(); // Reset it, just in case pCurrPreviewItem->ResetCancelEvent(); // Make the request m_pThreadMessageQueue->Enqueue( new CPreviewThreadMessage( m_hWnd, pCurrPreviewItem->GlobalInterfaceTableCookie(), pCurrPreviewItem->CancelQueueEvent().Event() ), CThreadMessageQueue::PriorityHigh ); } } else { CSimpleString strPct; strPct.Format( IDS_DOWNLOADINGPREVIEW, g_hInstance, pCurrPreviewItem->CurrentPreviewPercentage() ); SetCurrentPreviewImage( TEXT(""), strPct ); } } else { SetCurrentPreviewImage( TEXT("") ); CancelAllPreviewRequests( m_CameraItemList.Root() ); } } else { CancelAllPreviewRequests( m_CameraItemList.Root() ); SetCurrentPreviewImage( TEXT("") ); } } LRESULT CCameraAcquireDialog::OnTimer( WPARAM wParam, LPARAM ) { switch (wParam) { case IDT_UPDATEPREVIEW: { KillTimer( m_hWnd, IDT_UPDATEPREVIEW ); UpdatePreview(); } break; } return(0); } // Avoids unnecessary state changes static inline void MyEnableWindow( HWND hWnd, BOOL bEnable ) { if (bEnable && !IsWindowEnabled(hWnd)) EnableWindow(hWnd,TRUE); else if (!bEnable && IsWindowEnabled(hWnd)) EnableWindow(hWnd,FALSE); } // Avoids unnecessary state changes static inline void MyEnableToolbarButton( HWND hWnd, int nId, BOOL bEnable ) { LRESULT nState = SendMessage( hWnd, TB_GETSTATE, nId, 0 ); if (nState < 0) return; if ((nState & TBSTATE_ENABLED) && !bEnable) SendMessage( hWnd, TB_ENABLEBUTTON, nId, nState & ~TBSTATE_ENABLED); else if (!(nState & TBSTATE_ENABLED) && bEnable) SendMessage( hWnd, TB_ENABLEBUTTON, nId, nState | TBSTATE_ENABLED ); } void CCameraAcquireDialog::HandleSelectionChange(void) { CWaitCursor wc; int nSelCount = ListView_GetSelectedCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) ); int nItemCount = ListView_GetItemCount(GetDlgItem( m_hWnd, IDC_THUMBNAILLIST ) ); // // Properties should be disabled for multiple items // and parent folder icons // bool bDisableProperties = true; if (nSelCount == 1) { CSimpleDynamicArray aIndices; if (CCameraAcquireDialog::GetSelectionIndices( aIndices )) { if (CCameraAcquireDialog::GetListItemNode( aIndices[0] )) { bDisableProperties = false; } } } MyEnableWindow( GetDlgItem(m_hWnd,IDC_CAMDLG_PROPERTIES), !bDisableProperties ); // OK should be disabled for 0 items MyEnableWindow( GetDlgItem(m_hWnd,IDOK), nSelCount != 0 ); // Select all should be disabled for 0 items MyEnableToolbarButton( GetDlgItem(m_hWnd,IDC_TOOLBAR), IDC_SELECTALL, nItemCount != 0 ); // // Decide whether or not delete should be enabled // If any of the selected items are deletable, then delete is enabled // bool bEnableDelete = false; // // Get the selected items // CSimpleDynamicArray aSelIndices; if (GetSelectionIndices( aSelIndices )) { // // Loop through all of the selected items. Break out if we find a reason // to enable delete. // for (int i=0;iItemRights() & WIA_ITEM_CAN_BE_DELETED) { // // Found one, so we are done. // bEnableDelete = true; break; } } } } MyEnableToolbarButton( GetDlgItem(m_hWnd,IDC_TOOLBAR), IDC_DELETE, bEnableDelete ); KillTimer( m_hWnd, IDT_UPDATEPREVIEW ); SetTimer( m_hWnd, IDT_UPDATEPREVIEW, UPDATE_PREVIEW_DELAY, NULL ); } LRESULT CCameraAcquireDialog::OnImageListItemChanged( WPARAM, LPARAM ) { HandleSelectionChange(); return(0); } LRESULT CCameraAcquireDialog::OnImageListKeyDown( WPARAM, LPARAM lParam ) { LPNMLVKEYDOWN pnkd = reinterpret_cast(lParam); if (pnkd) { bool bAlt = ((GetKeyState(VK_MENU) & 0x8000) != 0); bool bControl = ((GetKeyState(VK_CONTROL) & 0x8000) != 0); bool bShift = ((GetKeyState(VK_SHIFT) & 0x8000) != 0); if (VK_LEFT == pnkd->wVKey && bAlt && !bControl && !bShift) { SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 ); } else if (VK_BACK == pnkd->wVKey && !bAlt && !bControl && !bShift) { SendMessage( m_hWnd, PWM_CHANGETOPARENT, 0, 0 ); } else if (VK_DELETE == pnkd->wVKey) { SendMessage( m_hWnd, WM_COMMAND, IDC_DELETE, 0 ); } } return (0); } LRESULT CCameraAcquireDialog::OnHelp( WPARAM wParam, LPARAM lParam ) { return WiaHelp::HandleWmHelp( wParam, lParam, g_HelpIDs ); } LRESULT CCameraAcquireDialog::OnContextMenu( WPARAM wParam, LPARAM lParam ) { return WiaHelp::HandleWmContextMenu( wParam, lParam, g_HelpIDs ); } LRESULT CCameraAcquireDialog::OnSysColorChange( WPARAM wParam, LPARAM lParam ) { WiaPreviewControl_SetBkColor( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE, TRUE, GetSysColor(COLOR_WINDOW) ); WiaPreviewControl_SetBkColor( GetDlgItem( m_hWnd, IDC_PREVIEW ), TRUE, FALSE, GetSysColor(COLOR_WINDOW) ); SendDlgItemMessage( m_hWnd, IDC_THUMBNAILLIST, WM_SYSCOLORCHANGE, wParam, lParam ); SendDlgItemMessage( m_hWnd, IDC_TOOLBAR, WM_SYSCOLORCHANGE, wParam, lParam ); SendDlgItemMessage( m_hWnd, IDC_CAMDLG_PROPERTIES, WM_SYSCOLORCHANGE, wParam, lParam ); m_ToolbarBitmapInfo.ReloadAndReplaceBitmap(); return 0; } LRESULT CCameraAcquireDialog::OnNotify( WPARAM wParam, LPARAM lParam ) { SC_BEGIN_NOTIFY_MESSAGE_HANDLERS() { SC_HANDLE_NOTIFY_MESSAGE_CONTROL( NM_DBLCLK, IDC_THUMBNAILLIST, OnDblClkImageList ); SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_ITEMCHANGED, IDC_THUMBNAILLIST, OnImageListItemChanged ); SC_HANDLE_NOTIFY_MESSAGE_CONTROL( LVN_KEYDOWN, IDC_THUMBNAILLIST, OnImageListKeyDown ); } SC_END_NOTIFY_MESSAGE_HANDLERS(); } // WM_COMMAND Handler LRESULT CCameraAcquireDialog::OnCommand( WPARAM wParam, LPARAM lParam ) { SC_BEGIN_COMMAND_HANDLERS() { SC_HANDLE_COMMAND(IDOK,OnOK); SC_HANDLE_COMMAND(IDCANCEL,OnCancel); SC_HANDLE_COMMAND(IDC_CAMDLG_PROPERTIES,OnProperties); SC_HANDLE_COMMAND(IDC_PREVIEWMODE,OnPreviewMode); SC_HANDLE_COMMAND(IDC_TAKEPICTURE,OnTakePicture); SC_HANDLE_COMMAND(IDC_ICONMODE,OnIconMode); SC_HANDLE_COMMAND(IDC_DELETE,OnDelete); SC_HANDLE_COMMAND(IDC_SELECTALL,OnSelectAll); } SC_END_COMMAND_HANDLERS(); } INT_PTR CALLBACK CCameraAcquireDialog::DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { SC_BEGIN_DIALOG_MESSAGE_HANDLERS(CCameraAcquireDialog) { SC_HANDLE_DIALOG_MESSAGE( WM_INITDIALOG, OnInitDialog ); SC_HANDLE_DIALOG_MESSAGE( WM_SIZE, OnSize ); SC_HANDLE_DIALOG_MESSAGE( WM_SHOWWINDOW, OnShow ); SC_HANDLE_DIALOG_MESSAGE( WM_ENTERSIZEMOVE, OnEnterSizeMove ); SC_HANDLE_DIALOG_MESSAGE( WM_EXITSIZEMOVE, OnExitSizeMove ); SC_HANDLE_DIALOG_MESSAGE( WM_COMMAND, OnCommand ); SC_HANDLE_DIALOG_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo ); SC_HANDLE_DIALOG_MESSAGE( WM_NOTIFY, OnNotify ); SC_HANDLE_DIALOG_MESSAGE( WM_DESTROY, OnDestroy ); SC_HANDLE_DIALOG_MESSAGE( PWM_POSTINIT, OnPostInit ); SC_HANDLE_DIALOG_MESSAGE( PWM_CHANGETOPARENT, OnChangeToParent ); SC_HANDLE_DIALOG_MESSAGE( PWM_THUMBNAILSTATUS, OnThumbnailStatus ); SC_HANDLE_DIALOG_MESSAGE( PWM_PREVIEWSTATUS, OnPreviewStatus ); SC_HANDLE_DIALOG_MESSAGE( PWM_PREVIEWPERCENT, OnPreviewPercent ); SC_HANDLE_DIALOG_MESSAGE( PWM_ITEMDELETED, OnItemDeleted ); SC_HANDLE_DIALOG_MESSAGE( PWM_WIAEVENT, OnWiaEvent ); SC_HANDLE_DIALOG_MESSAGE( WM_TIMER, OnTimer ); SC_HANDLE_DIALOG_MESSAGE( WM_HELP, OnHelp ); SC_HANDLE_DIALOG_MESSAGE( WM_CONTEXTMENU, OnContextMenu ); SC_HANDLE_DIALOG_MESSAGE( WM_SYSCOLORCHANGE, OnSysColorChange ); } SC_END_DIALOG_MESSAGE_HANDLERS(); } // Static hook-related data HWND CCameraAcquireDialog::s_hWndDialog = NULL; HHOOK CCameraAcquireDialog::s_hMessageHook = NULL;