/***************************************************************************** * * (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 #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 *****************************************************************************/ 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(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(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(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; }