1115 lines
32 KiB
C++
1115 lines
32 KiB
C++
/*****************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
|
|
*
|
|
* TITLE: photosel.cpp
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: RickTu
|
|
*
|
|
* DATE: 10/18/00
|
|
*
|
|
* DESCRIPTION: Implements code for the photo selection page of the
|
|
* print photos wizard...
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Quickly check a listview state flag to see if it is checked or not
|
|
//
|
|
static inline bool IsStateChecked( UINT nState )
|
|
{
|
|
//
|
|
// State image indices are stored in bits 12 through 15 of the listview
|
|
// item state, so we shift the state right 12 bits. We subtract 1, because
|
|
// the checked image is stored as index 2, an unchecked image is stored as index 1.
|
|
//
|
|
return (((nState >> 12) - 1) != 0);
|
|
}
|
|
|
|
// 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 = 8;
|
|
static const int c_nAdditionalMarginY = 21;
|
|
|
|
#define LVS_EX_FLAGS (LVS_EX_DOUBLEBUFFER|LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_SIMPLESELECT|LVS_EX_CHECKBOXES)
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage -- constructor/desctructor
|
|
|
|
<Notes>
|
|
|
|
*****************************************************************************/
|
|
|
|
CPhotoSelectionPage::CPhotoSelectionPage( CWizardInfoBlob * pBlob )
|
|
: _hDlg(NULL),
|
|
_bActive(FALSE),
|
|
_hThumbnailThread(NULL)
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::CPhotoSelectionPage()")));
|
|
_pWizInfo = pBlob;
|
|
_pWizInfo->AddRef();
|
|
}
|
|
|
|
CPhotoSelectionPage::~CPhotoSelectionPage()
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::~CPhotoSelectionPage()")));
|
|
|
|
if (_pWizInfo)
|
|
{
|
|
_pWizInfo->Release();
|
|
_pWizInfo = NULL;
|
|
}
|
|
}
|
|
|
|
VOID CPhotoSelectionPage::ShutDownBackgroundThreads()
|
|
{
|
|
//
|
|
// Wait for the thumbnail thread to complete...
|
|
//
|
|
|
|
if (_hThumbnailThread)
|
|
{
|
|
WiaUiUtil::MsgWaitForSingleObject( _hThumbnailThread, INFINITE );
|
|
CloseHandle( _hThumbnailThread );
|
|
_hThumbnailThread = NULL;
|
|
}
|
|
|
|
//
|
|
// Notify _pWizInfo that we've shut down
|
|
//
|
|
|
|
if (_pWizInfo)
|
|
{
|
|
_pWizInfo->PhotoSelIsShutDown();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
_AddThumbnailToListViewImageList
|
|
|
|
Creates a thumbnail for the given item and then adds it to the
|
|
listview's image list.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
INT _AddThumbnailToListViewImageList( CWizardInfoBlob * _pWizInfo, HWND hDlg, HWND hwndList, HIMAGELIST hImageList, CListItem *pItem, int nIndex, BOOL bIconInstead )
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("_AddThumbnailToListViewImageList")));
|
|
|
|
if (!_pWizInfo)
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Assume we have the default thumbnail. If there are any problems, this is what we will use.
|
|
//
|
|
|
|
int nImageListIndex = _pWizInfo->_nDefaultThumbnailImageListIndex;
|
|
|
|
//
|
|
// Make sure we have a valid item
|
|
//
|
|
if (pItem)
|
|
{
|
|
|
|
//
|
|
// We only have the default thumbnail, so create and use the
|
|
// real thumbnail...
|
|
//
|
|
|
|
HBITMAP hThumbnail = NULL;
|
|
|
|
if (!_pWizInfo->IsWizardShuttingDown())
|
|
{
|
|
if (bIconInstead)
|
|
{
|
|
WIA_TRACE((TEXT("retreiving class icon...")));
|
|
hThumbnail = pItem->GetClassBitmap( _pWizInfo->_sizeThumbnails );
|
|
}
|
|
else
|
|
{
|
|
WIA_TRACE((TEXT("retreiving thumbnail...")));
|
|
hThumbnail = pItem->GetThumbnailBitmap( _pWizInfo->_sizeThumbnails );
|
|
}
|
|
}
|
|
|
|
if (hThumbnail)
|
|
{
|
|
if (!_pWizInfo->IsWizardShuttingDown())
|
|
{
|
|
//
|
|
// Add this thumbnail to the listview
|
|
//
|
|
|
|
if (hImageList)
|
|
{
|
|
nImageListIndex = ImageList_Add( hImageList, hThumbnail, NULL );
|
|
}
|
|
}
|
|
|
|
DeleteObject((HGDIOBJ)hThumbnail);
|
|
}
|
|
else
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: hThumbnail was NULL!")));
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: pItem is NULL, not creating thumbnail")));
|
|
}
|
|
|
|
return nImageListIndex;
|
|
}
|
|
|
|
typedef struct {
|
|
CPhotoSelectionPage * that;
|
|
HWND hDlg;
|
|
HWND hwndList;
|
|
HIMAGELIST hImageList;
|
|
CWizardInfoBlob * pWizInfo;
|
|
} THUMB_PROC_INFO;
|
|
|
|
|
|
VOID _AddItemToListView( CWizardInfoBlob * pWizInfo, HWND hwndList, INT iIndexOfItem, INT nImageListIndex )
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_AddItemToListView( iIndexOfItem = %d, nImageListIndex = %d)"),iIndexOfItem,nImageListIndex));
|
|
|
|
//
|
|
// Verify Params
|
|
//
|
|
|
|
if (!pWizInfo || !hwndList)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get item from master item list...
|
|
//
|
|
|
|
CListItem * pItem = pWizInfo->GetListItem(iIndexOfItem,FALSE);
|
|
|
|
if (pItem)
|
|
{
|
|
|
|
//
|
|
// Add a new listview item for this photo...
|
|
//
|
|
|
|
LVITEM lvItem = {0};
|
|
lvItem.iItem = iIndexOfItem;
|
|
lvItem.mask = LVIF_IMAGE|LVIF_PARAM|LVIF_STATE;
|
|
lvItem.iImage = nImageListIndex;
|
|
lvItem.lParam = reinterpret_cast<LPARAM>(pItem);
|
|
|
|
//
|
|
// If we're in force select all, the do select all
|
|
//
|
|
// ...else...
|
|
//
|
|
// If we only had one item in the initial selection,
|
|
// and we're on the first item, then select it.
|
|
//
|
|
// ...else...
|
|
//
|
|
// Otherwise, do select all
|
|
//
|
|
|
|
|
|
if (pWizInfo->GetForceSelectAll())
|
|
{
|
|
pItem->SetSelectionState( TRUE );
|
|
}
|
|
else if (pWizInfo->ItemsInInitialSelection() == 1)
|
|
{
|
|
|
|
if (iIndexOfItem==0)
|
|
{
|
|
//
|
|
// It's the first item, and there was only
|
|
// one selected, so select this item.
|
|
//
|
|
|
|
pItem->SetSelectionState( TRUE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// There was only one item selected, but
|
|
// these are the rest of the items from the
|
|
// folder, so don't select them.
|
|
//
|
|
|
|
pItem->SetSelectionState( FALSE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Except the the one item selection case, everything else
|
|
// defaults to all items selected in the wizard to begin with.
|
|
//
|
|
|
|
pItem->SetSelectionState( TRUE );
|
|
}
|
|
|
|
INT nResult = ListView_InsertItem( hwndList, &lvItem );
|
|
|
|
if (nResult == -1)
|
|
{
|
|
WIA_ERROR((TEXT("Couldn't add item %d to ListView"),iIndexOfItem));
|
|
pItem->SetSelectionState( FALSE );
|
|
}
|
|
else
|
|
{
|
|
ListView_SetCheckState( hwndList, nResult, pItem->SelectedForPrinting() );
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::s_UpdateThumbnailThreadProc
|
|
|
|
Thread which will go through and generate thumbnails for all the items
|
|
in the listview...
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
DWORD CPhotoSelectionPage::s_UpdateThumbnailThreadProc(VOID *pv)
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::s_UpdateThumbnailThreadProc()")));
|
|
|
|
//
|
|
// Okay -- we can't have any code that calls back into the main UI
|
|
// thread synchronously. That means no SendMessage calls in
|
|
// particular. This is so that we can clean up nicely when the
|
|
// user cancels and, of course, that message comes in on the main
|
|
// UI thread, and we don't want to return until we know we've cleaned
|
|
// up...
|
|
//
|
|
|
|
THUMB_PROC_INFO * pTPI = (THUMB_PROC_INFO *)pv;
|
|
|
|
if (pTPI && pTPI->pWizInfo)
|
|
{
|
|
//
|
|
// First thing -- addref our dll so we don't get unloaded...
|
|
//
|
|
|
|
HINSTANCE hDll = GetThreadHMODULE( s_UpdateThumbnailThreadProc );
|
|
|
|
//
|
|
// Initialize COM for this thread...
|
|
//
|
|
|
|
HRESULT hrCo = PPWCoInitialize();
|
|
|
|
//
|
|
// Add items to listview
|
|
//
|
|
|
|
if (pTPI->hwndList)
|
|
{
|
|
|
|
//
|
|
// Tell the window not to redraw while we add these items
|
|
//
|
|
|
|
PostMessage( pTPI->hwndList, WM_SETREDRAW, FALSE, 0 );
|
|
|
|
//
|
|
// Wait until all items have been processed by pWizInfo
|
|
//
|
|
|
|
while ((!pTPI->pWizInfo->IsWizardShuttingDown()) && (!pTPI->pWizInfo->AllPicturesAdded()))
|
|
{
|
|
//
|
|
// The items are not there yet for adding, wait another 1/2 second
|
|
//
|
|
|
|
Sleep( 500 );
|
|
}
|
|
|
|
//
|
|
// Get the number of items
|
|
//
|
|
|
|
LONG nItemCount = pTPI->pWizInfo->CountOfPhotos(FALSE);
|
|
WIA_TRACE((TEXT("There are %d photos to add to the listview"),nItemCount));
|
|
|
|
//
|
|
// Loop through all the photos and add them...
|
|
//
|
|
|
|
CListItem * pItem = NULL;
|
|
INT nImageListIndex = -1;
|
|
for (INT i=0; (!pTPI->pWizInfo->IsWizardShuttingDown()) && (i < nItemCount); i++)
|
|
{
|
|
//
|
|
// Tell the user what's going on...
|
|
//
|
|
|
|
PostMessage( pTPI->hDlg, PSP_MSG_UPDATE_ITEM_COUNT, i+1, nItemCount );
|
|
|
|
pItem = pTPI->pWizInfo->GetListItem(i,FALSE);
|
|
if (pItem)
|
|
{
|
|
|
|
//
|
|
// Get class icon for this image...
|
|
//
|
|
|
|
nImageListIndex = _AddThumbnailToListViewImageList( pTPI->pWizInfo, pTPI->hDlg, pTPI->hwndList, pTPI->hImageList, pItem, i, TRUE );
|
|
|
|
//
|
|
// Tell main UI thread to add this item to the listview...
|
|
//
|
|
|
|
PostMessage( pTPI->hDlg, PSP_MSG_ADD_ITEM, i, nImageListIndex );
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Make sure the first item is selected and has the focus
|
|
//
|
|
|
|
PostMessage( pTPI->hDlg, PSP_MSG_SELECT_ITEM, 0, 0 );
|
|
|
|
|
|
//
|
|
// Tell the window to redraw now, because we are done. Invalidate the window, in case it is visible
|
|
//
|
|
|
|
PostMessage( pTPI->hwndList, WM_SETREDRAW, TRUE, 0 );
|
|
PostMessage( pTPI->hDlg, PSP_MSG_INVALIDATE_LISTVIEW, 0, 0 );
|
|
|
|
//
|
|
// If there were items rejected, say so...
|
|
//
|
|
|
|
if (pTPI->pWizInfo->ItemsWereRejected())
|
|
{
|
|
WIA_TRACE((TEXT("ItemsWereRejected is TRUE, setting message...")));
|
|
PostMessage( pTPI->hDlg, PSP_MSG_NOT_ALL_LOADED, 0, 0 );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// otherwise, clear temporary status area...
|
|
//
|
|
|
|
WIA_TRACE((TEXT("ItemsWereRejected is FALSE, resetting message area...")));
|
|
PostMessage( pTPI->hDlg, PSP_MSG_CLEAR_STATUS, 0, 0 );
|
|
}
|
|
|
|
//
|
|
// If there are 0 items, then let's disable the "Select All" and "Clear All" buttons
|
|
//
|
|
|
|
PostMessage( pTPI->hDlg, PSP_MSG_ENABLE_BUTTONS, (WPARAM)nItemCount, 0 );
|
|
|
|
//
|
|
// Now, loop through and update all the thumbnails with the correct images...
|
|
//
|
|
|
|
pItem = NULL;
|
|
nImageListIndex = -1;
|
|
|
|
for (INT i=0; (!pTPI->pWizInfo->IsWizardShuttingDown()) && (i < nItemCount); i++)
|
|
{
|
|
pItem = pTPI->pWizInfo->GetListItem(i,FALSE);
|
|
if (pItem)
|
|
{
|
|
nImageListIndex = _AddThumbnailToListViewImageList( pTPI->pWizInfo, pTPI->hDlg, pTPI->hwndList, pTPI->hImageList, pItem, i, FALSE );
|
|
if (nImageListIndex >= 0)
|
|
{
|
|
WIA_TRACE((TEXT("Updating thumbnail for listview item %d"),i));
|
|
|
|
PostMessage( pTPI->hDlg, PSP_MSG_UPDATE_THUMBNAIL, i, nImageListIndex );
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: Couldn't get hwndList")));
|
|
}
|
|
|
|
|
|
pTPI->pWizInfo->Release();
|
|
delete [] pTPI;
|
|
|
|
//
|
|
// Unitialize COM
|
|
//
|
|
|
|
PPWCoUninitialize(hrCo);
|
|
|
|
//
|
|
// Exit the thread
|
|
//
|
|
|
|
if (hDll)
|
|
{
|
|
FreeLibraryAndExitThread( hDll, 0 );
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::_PopulateListView
|
|
|
|
Gets thumbnails for each of the items in the list view...
|
|
|
|
*****************************************************************************/
|
|
|
|
VOID CPhotoSelectionPage::_PopulateListView()
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_PopulateListView()")));
|
|
|
|
if (!_pWizInfo)
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Do all the population on the background thread...
|
|
//
|
|
|
|
THUMB_PROC_INFO * pTPI = (THUMB_PROC_INFO *) new BYTE[sizeof(THUMB_PROC_INFO)];
|
|
if (pTPI)
|
|
{
|
|
pTPI->that = this;
|
|
pTPI->hDlg = _hDlg;
|
|
pTPI->hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
|
|
pTPI->hImageList = ListView_GetImageList( pTPI->hwndList, LVSIL_NORMAL );
|
|
_pWizInfo->AddRef(); // make sure it doesn't go away while the thread is running...
|
|
pTPI->pWizInfo = _pWizInfo;
|
|
|
|
|
|
//
|
|
// Create the thumbnail update thread...
|
|
//
|
|
|
|
_hThumbnailThread = CreateThread( NULL, 0, s_UpdateThumbnailThreadProc, (LPVOID)pTPI, CREATE_SUSPENDED, NULL );
|
|
|
|
if (!_hThumbnailThread)
|
|
{
|
|
WIA_ERROR((TEXT("CreateThread( s_UpdateThumbnailThreadProc ) failed!")));
|
|
_pWizInfo->Release();
|
|
delete [] pTPI;
|
|
}
|
|
else
|
|
{
|
|
SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_BELOW_NORMAL );
|
|
ResumeThread( _hThumbnailThread );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::OnInitDialog
|
|
|
|
Handle initializing the wizard page...
|
|
|
|
*****************************************************************************/
|
|
|
|
LRESULT CPhotoSelectionPage::_OnInitDialog()
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnInitDialog()")));
|
|
|
|
|
|
if (!_pWizInfo)
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Register ourselves with _pWizInfo
|
|
//
|
|
|
|
_pWizInfo->SetPhotoSelectionPageClass( this );
|
|
|
|
//
|
|
// Initialize Thumbnail Listview control
|
|
//
|
|
|
|
HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
|
|
if (hwndList)
|
|
{
|
|
//
|
|
// Get the number of items
|
|
//
|
|
|
|
LONG nItemCount = _pWizInfo->CountOfPhotos(FALSE);
|
|
WIA_TRACE((TEXT("There are %d photos to add to the listview"),nItemCount));
|
|
|
|
//
|
|
// If there are 0 items, then let's disable the "Select All" and "Clear All" buttons
|
|
//
|
|
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (nItemCount > 0) );
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), (nItemCount > 0) );
|
|
|
|
//
|
|
// Hide the labels and use border selection
|
|
//
|
|
|
|
ListView_SetExtendedListViewStyleEx( hwndList, LVS_EX_FLAGS, LVS_EX_FLAGS );
|
|
|
|
//
|
|
// Create the image list
|
|
//
|
|
|
|
HIMAGELIST hImageList = ImageList_Create( _pWizInfo->_sizeThumbnails.cx, _pWizInfo->_sizeThumbnails.cy, ILC_COLOR32|ILC_MIRROR, nItemCount, 50 );
|
|
if (hImageList)
|
|
{
|
|
//
|
|
// Set the background color
|
|
//
|
|
|
|
COLORREF dw = (COLORREF)GetSysColor( COLOR_WINDOW );
|
|
ImageList_SetBkColor( hImageList, dw );
|
|
|
|
//
|
|
// Create the default thumbnail
|
|
//
|
|
|
|
HBITMAP hBmpDefaultThumbnail = WiaUiUtil::CreateIconThumbnail( hwndList, _pWizInfo->_sizeThumbnails.cx, _pWizInfo->_sizeThumbnails.cy, g_hInst, IDI_UNAVAILABLE, CSimpleString( IDS_DOWNLOADINGTHUMBNAIL, g_hInst) );
|
|
if (hBmpDefaultThumbnail)
|
|
{
|
|
_pWizInfo->_nDefaultThumbnailImageListIndex = ImageList_Add( hImageList, hBmpDefaultThumbnail, NULL );
|
|
DeleteObject( hBmpDefaultThumbnail );
|
|
}
|
|
|
|
//
|
|
// Set the image list
|
|
//
|
|
|
|
ListView_SetImageList( hwndList, hImageList, LVSIL_NORMAL );
|
|
|
|
//
|
|
// Set the spacing
|
|
//
|
|
|
|
ListView_SetIconSpacing( hwndList, _pWizInfo->_sizeThumbnails.cx + c_nAdditionalMarginX, _pWizInfo->_sizeThumbnails.cy + c_nAdditionalMarginY );
|
|
|
|
//
|
|
// Set the item count, to minimize recomputing the list size
|
|
//
|
|
|
|
ListView_SetItemCount( hwndList, nItemCount );
|
|
|
|
//
|
|
// Create a small image list, to prevent the checkbox state images from being resized in WM_SYSCOLORCHANGE
|
|
//
|
|
|
|
HIMAGELIST hImageListSmall = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 1, 1 );
|
|
if (hImageListSmall)
|
|
{
|
|
ListView_SetImageList( hwndList, hImageListSmall, LVSIL_SMALL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: Creation of the imagelist failed!")));
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WIA_ERROR((TEXT("FATAL: Couldn't get listview")));
|
|
}
|
|
|
|
//
|
|
// Populate the list view
|
|
//
|
|
|
|
_PopulateListView();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::OnCommand
|
|
|
|
Handle WM_COMMAND for this dlg page
|
|
|
|
*****************************************************************************/
|
|
|
|
LRESULT CPhotoSelectionPage::_OnCommand( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnCommand()")));
|
|
|
|
WORD wNotifyCode = HIWORD(wParam);
|
|
WORD wID = LOWORD(wParam);
|
|
HWND hwndCtrl = (HWND)lParam;
|
|
|
|
switch (wID)
|
|
{
|
|
case IDC_SELECTALL:
|
|
if (_pWizInfo)
|
|
{
|
|
HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
|
|
if (hwndList)
|
|
{
|
|
CListItem * pItem = NULL;
|
|
for (INT i=0; i < _pWizInfo->CountOfPhotos(FALSE); i++)
|
|
{
|
|
pItem = _pWizInfo->GetListItem(i,FALSE);
|
|
if (pItem)
|
|
{
|
|
pItem->SetSelectionState(TRUE);
|
|
ListView_SetCheckState( hwndList, i, TRUE );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now mark for all copies as well...
|
|
//
|
|
|
|
for (INT i=0; i < _pWizInfo->CountOfPhotos(TRUE); i++)
|
|
{
|
|
pItem = _pWizInfo->GetListItem(i,TRUE);
|
|
if (pItem)
|
|
{
|
|
pItem->SetSelectionState(TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
_pWizInfo->SetPreviewsAreDirty(TRUE);
|
|
|
|
}
|
|
break;
|
|
case IDC_CLEARALL:
|
|
if (_pWizInfo)
|
|
{
|
|
HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
|
|
if (hwndList)
|
|
{
|
|
CListItem * pItem = NULL;
|
|
for (INT i=0; i < _pWizInfo->CountOfPhotos(FALSE); i++)
|
|
{
|
|
pItem = _pWizInfo->GetListItem(i,FALSE);
|
|
if (pItem)
|
|
{
|
|
pItem->SetSelectionState(FALSE);
|
|
ListView_SetCheckState( hwndList, i, FALSE );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now mark for all copies as well...
|
|
//
|
|
|
|
for (INT i=0; i < _pWizInfo->CountOfPhotos(TRUE); i++)
|
|
{
|
|
pItem = _pWizInfo->GetListItem(i,TRUE);
|
|
if (pItem)
|
|
{
|
|
pItem->SetSelectionState(FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
_pWizInfo->SetPreviewsAreDirty(TRUE);
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::OnDestroy
|
|
|
|
Handle WM_DESTROY message for this wizard page...
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
LRESULT CPhotoSelectionPage::_OnDestroy()
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnDestroy()")));
|
|
|
|
|
|
//
|
|
// Nuke the large imagelist
|
|
//
|
|
HIMAGELIST hImageList = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, LVSIL_NORMAL );
|
|
if (hImageList)
|
|
{
|
|
ImageList_Destroy(hImageList);
|
|
}
|
|
|
|
//
|
|
// Nuke the small imagelist
|
|
//
|
|
hImageList = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, LVSIL_SMALL );
|
|
if (hImageList)
|
|
{
|
|
ImageList_Destroy(hImageList);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::_OnNotify
|
|
|
|
Handles WM_NOTIFY messages...
|
|
|
|
*****************************************************************************/
|
|
|
|
LRESULT CPhotoSelectionPage::_OnNotify( WPARAM wParam, LPARAM lParam )
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CPhotoSelectionPage::_OnNotify()")));
|
|
|
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|
LONG_PTR lpRes = 0;
|
|
|
|
switch (pnmh->code)
|
|
{
|
|
|
|
case PSN_SETACTIVE:
|
|
WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_SETACTIVE")));
|
|
{
|
|
//
|
|
// Set the thread priority of thumbnail generation thread
|
|
// to be our normal (which is below normal) since we're
|
|
// on this page...
|
|
//
|
|
|
|
if (_hThumbnailThread)
|
|
{
|
|
SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_BELOW_NORMAL );
|
|
}
|
|
|
|
lpRes = 0;
|
|
DWORD dwFlags = PSWIZB_BACK;
|
|
_bActive = TRUE;
|
|
|
|
if (_pWizInfo)
|
|
{
|
|
if (_pWizInfo->CountOfSelectedPhotos(FALSE) > 0)
|
|
dwFlags |= PSWIZB_NEXT;
|
|
}
|
|
|
|
PropSheet_SetWizButtons( GetParent(_hDlg), dwFlags );
|
|
}
|
|
break;
|
|
|
|
case PSN_KILLACTIVE:
|
|
WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_KILLACTIVE")));
|
|
|
|
//
|
|
// Since we're leaving this thread, set the priority of the
|
|
// thread doing the listview thumbnail generation to even
|
|
// lower than normal...
|
|
//
|
|
|
|
if (_hThumbnailThread)
|
|
{
|
|
SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_LOWEST );
|
|
}
|
|
|
|
|
|
_bActive = FALSE;
|
|
lpRes = 0;
|
|
break;
|
|
|
|
case PSN_WIZNEXT:
|
|
WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_WIZNEXT")));
|
|
lpRes = IDD_PRINTING_OPTIONS;
|
|
break;
|
|
|
|
case PSN_WIZBACK:
|
|
WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_WIZBACK")));
|
|
lpRes = IDD_START_PAGE;
|
|
break;
|
|
|
|
case PSN_QUERYCANCEL:
|
|
WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_QUERYCANCEL")));
|
|
if (_pWizInfo)
|
|
{
|
|
lpRes = _pWizInfo->UserPressedCancel();
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
NMLISTVIEW *pNmListView = reinterpret_cast<NMLISTVIEW*>(lParam);
|
|
if (pNmListView)
|
|
{
|
|
//
|
|
// If this is a state change (check marks are stored as state image indices)
|
|
//
|
|
if ((pNmListView->uChanged & LVIF_STATE) && ((pNmListView->uOldState&LVIS_STATEIMAGEMASK) ^ (pNmListView->uNewState&LVIS_STATEIMAGEMASK)))
|
|
{
|
|
//
|
|
// Get the item * from the LVITEM structure
|
|
//
|
|
CListItem *pItem = reinterpret_cast<CListItem *>(pNmListView->lParam);
|
|
if (pItem)
|
|
{
|
|
//
|
|
// If just added is true, ignore this notification, because
|
|
// we unfortunately get two notifications for items with check
|
|
// state set. The first time, it is not set, so if we process it,
|
|
// it will clear the selection state.
|
|
//
|
|
if (pItem->JustAdded())
|
|
{
|
|
pItem->SetJustAdded(FALSE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set selected flag in the item
|
|
//
|
|
pItem->SetSelectionState( IsStateChecked(pNmListView->uNewState) );
|
|
|
|
if (_pWizInfo)
|
|
{
|
|
//
|
|
// toggle all copies as well..
|
|
//
|
|
|
|
_pWizInfo->ToggleSelectionStateOnCopies( pItem, IsStateChecked(pNmListView->uNewState) );
|
|
|
|
//
|
|
// The previews are wrong, mark them as such...
|
|
//
|
|
|
|
_pWizInfo->SetPreviewsAreDirty(TRUE);
|
|
|
|
if (_bActive)
|
|
{
|
|
DWORD dwFlags = PSWIZB_BACK;
|
|
|
|
if (_pWizInfo->CountOfSelectedPhotos(FALSE) > 0)
|
|
{
|
|
dwFlags |= PSWIZB_NEXT;
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), TRUE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), FALSE );
|
|
}
|
|
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (_pWizInfo->CountOfSelectedPhotos(FALSE) != _pWizInfo->CountOfPhotos(FALSE)) ? TRUE : FALSE );
|
|
|
|
PropSheet_SetWizButtons( GetParent(_hDlg), dwFlags );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, lpRes );
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
CPhotoSelectionPage::DoHandleMessage
|
|
|
|
Hanlder for messages sent to this page...
|
|
|
|
*****************************************************************************/
|
|
|
|
INT_PTR CPhotoSelectionPage::DoHandleMessage( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CPhotoSelectionPage::DoHandleMessage( uMsg = 0x%x, wParam = 0x%x, lParam = 0x%x )"),uMsg,wParam,lParam));
|
|
|
|
static CSimpleString strFormat( IDS_NUM_IMAGES_FORMAT, g_hInst );
|
|
static CSimpleString strMessage;
|
|
|
|
switch ( uMsg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
_hDlg = hDlg;
|
|
return _OnInitDialog();
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
return _OnCommand(wParam, lParam);
|
|
|
|
case WM_DESTROY:
|
|
return _OnDestroy();
|
|
|
|
case WM_NOTIFY:
|
|
return _OnNotify(wParam, lParam);
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
|
|
//
|
|
// Forward the color change message, and send a bogus setting change message, just
|
|
// to be sure the control repaints
|
|
//
|
|
|
|
SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SYSCOLORCHANGE, wParam, lParam );
|
|
SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SETTINGCHANGE, 0, 0 );
|
|
break;
|
|
|
|
case WM_SETTINGCHANGE:
|
|
{
|
|
|
|
//
|
|
// Create a small image list, to prevent the checkbox state images from being resized in WM_SYSCOLORCHANGE
|
|
//
|
|
|
|
HIMAGELIST hImageListSmall = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32|ILC_MASK, 1, 1 );
|
|
if (hImageListSmall)
|
|
{
|
|
//
|
|
// Set the new image list and destroy the old one
|
|
//
|
|
|
|
HIMAGELIST hImgListOld = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), hImageListSmall, LVSIL_SMALL );
|
|
if (hImgListOld)
|
|
{
|
|
ImageList_Destroy(hImgListOld);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Forward the setting change message, and send a bogus color change message, just
|
|
// to be sure the control repaints
|
|
//
|
|
|
|
SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SETTINGCHANGE, wParam, lParam );
|
|
SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SYSCOLORCHANGE, 0, 0 );
|
|
}
|
|
break;
|
|
|
|
case PSP_MSG_UPDATE_ITEM_COUNT:
|
|
strMessage.Format( strFormat, wParam, lParam );
|
|
strMessage.SetWindowText( GetDlgItem( _hDlg, IDC_NUM_IMAGES ) );
|
|
break;
|
|
|
|
case PSP_MSG_ADD_ITEM:
|
|
_AddItemToListView( _pWizInfo, GetDlgItem( _hDlg, IDC_THUMBNAILS ), (INT)wParam, (INT)lParam );
|
|
break;
|
|
|
|
case PSP_MSG_SELECT_ITEM:
|
|
ListView_SetItemState( GetDlgItem( _hDlg, IDC_THUMBNAILS ), wParam, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
|
|
break;
|
|
|
|
case PSP_MSG_NOT_ALL_LOADED:
|
|
{
|
|
CSimpleString strReject( IDS_NOT_ALL_IMAGES_WILL_PRINT, g_hInst );
|
|
SetDlgItemText( _hDlg, IDC_NUM_IMAGES, strReject.String() );
|
|
}
|
|
break;
|
|
|
|
case PSP_MSG_CLEAR_STATUS:
|
|
SetDlgItemText( _hDlg, IDC_NUM_IMAGES, TEXT("") );
|
|
break;
|
|
|
|
case PSP_MSG_UPDATE_THUMBNAIL:
|
|
{
|
|
LVITEM lvItem = {0};
|
|
lvItem.iItem = (INT)wParam;
|
|
lvItem.mask = LVIF_IMAGE;
|
|
lvItem.iImage = (INT)lParam;
|
|
ListView_SetItem( GetDlgItem( _hDlg, IDC_THUMBNAILS ), &lvItem );
|
|
}
|
|
break;
|
|
|
|
case PSP_MSG_ENABLE_BUTTONS:
|
|
if (_pWizInfo)
|
|
{
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (((INT)wParam > 0) && (_pWizInfo->CountOfSelectedPhotos(FALSE) != _pWizInfo->CountOfPhotos(FALSE))) ? TRUE : FALSE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), ((INT)wParam > 0) );
|
|
}
|
|
EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), ((INT)wParam > 0) );
|
|
break;
|
|
|
|
case PSP_MSG_INVALIDATE_LISTVIEW:
|
|
InvalidateRect( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, FALSE );
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|