Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1114 lines
33 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: photosel.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: RickTu
  10. *
  11. * DATE: 10/18/00
  12. *
  13. * DESCRIPTION: Implements code for the photo selection page of the
  14. * print photos wizard...
  15. *
  16. *****************************************************************************/
  17. #include <precomp.h>
  18. #pragma hdrstop
  19. //
  20. // Quickly check a listview state flag to see if it is checked or not
  21. //
  22. static inline bool IsStateChecked( UINT nState )
  23. {
  24. //
  25. // State image indices are stored in bits 12 through 15 of the listview
  26. // item state, so we shift the state right 12 bits. We subtract 1, because
  27. // the checked image is stored as index 2, an unchecked image is stored as index 1.
  28. //
  29. return (((nState >> 12) - 1) != 0);
  30. }
  31. // Thumbnail whitespace: the space in between images and their selection rectangles
  32. // These values were discovered by trail and error. For instance, if you reduce
  33. // c_nAdditionalMarginY to 20, you get really bizarre spacing problems in the list view
  34. // in vertical mode. These values could become invalid in future versions of the listview.
  35. static const int c_nAdditionalMarginX = 8;
  36. static const int c_nAdditionalMarginY = 21;
  37. #define LVS_EX_FLAGS (LVS_EX_DOUBLEBUFFER|LVS_EX_BORDERSELECT|LVS_EX_HIDELABELS|LVS_EX_SIMPLESELECT|LVS_EX_CHECKBOXES)
  38. /*****************************************************************************
  39. CPhotoSelectionPage -- constructor/desctructor
  40. <Notes>
  41. *****************************************************************************/
  42. CPhotoSelectionPage::CPhotoSelectionPage( CWizardInfoBlob * pBlob )
  43. : _hDlg(NULL),
  44. _bActive(FALSE),
  45. _hThumbnailThread(NULL)
  46. {
  47. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::CPhotoSelectionPage()")));
  48. _pWizInfo = pBlob;
  49. _pWizInfo->AddRef();
  50. }
  51. CPhotoSelectionPage::~CPhotoSelectionPage()
  52. {
  53. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::~CPhotoSelectionPage()")));
  54. if (_pWizInfo)
  55. {
  56. _pWizInfo->Release();
  57. _pWizInfo = NULL;
  58. }
  59. }
  60. VOID CPhotoSelectionPage::ShutDownBackgroundThreads()
  61. {
  62. //
  63. // Wait for the thumbnail thread to complete...
  64. //
  65. if (_hThumbnailThread)
  66. {
  67. WiaUiUtil::MsgWaitForSingleObject( _hThumbnailThread, INFINITE );
  68. CloseHandle( _hThumbnailThread );
  69. _hThumbnailThread = NULL;
  70. }
  71. //
  72. // Notify _pWizInfo that we've shut down
  73. //
  74. if (_pWizInfo)
  75. {
  76. _pWizInfo->PhotoSelIsShutDown();
  77. }
  78. }
  79. /*****************************************************************************
  80. _AddThumbnailToListViewImageList
  81. Creates a thumbnail for the given item and then adds it to the
  82. listview's image list.
  83. *****************************************************************************/
  84. INT _AddThumbnailToListViewImageList( CWizardInfoBlob * _pWizInfo, HWND hDlg, HWND hwndList, HIMAGELIST hImageList, CListItem *pItem, int nIndex, BOOL bIconInstead )
  85. {
  86. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("_AddThumbnailToListViewImageList")));
  87. if (!_pWizInfo)
  88. {
  89. WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
  90. return -1;
  91. }
  92. //
  93. // Assume we have the default thumbnail. If there are any problems, this is what we will use.
  94. //
  95. int nImageListIndex = _pWizInfo->_nDefaultThumbnailImageListIndex;
  96. //
  97. // Make sure we have a valid item
  98. //
  99. if (pItem)
  100. {
  101. //
  102. // We only have the default thumbnail, so create and use the
  103. // real thumbnail...
  104. //
  105. HBITMAP hThumbnail = NULL;
  106. if (!_pWizInfo->IsWizardShuttingDown())
  107. {
  108. if (bIconInstead)
  109. {
  110. WIA_TRACE((TEXT("retreiving class icon...")));
  111. hThumbnail = pItem->GetClassBitmap( _pWizInfo->_sizeThumbnails );
  112. }
  113. else
  114. {
  115. WIA_TRACE((TEXT("retreiving thumbnail...")));
  116. hThumbnail = pItem->GetThumbnailBitmap( _pWizInfo->_sizeThumbnails );
  117. }
  118. }
  119. if (hThumbnail)
  120. {
  121. if (!_pWizInfo->IsWizardShuttingDown())
  122. {
  123. //
  124. // Add this thumbnail to the listview
  125. //
  126. if (hImageList)
  127. {
  128. nImageListIndex = ImageList_Add( hImageList, hThumbnail, NULL );
  129. }
  130. }
  131. DeleteObject((HGDIOBJ)hThumbnail);
  132. }
  133. else
  134. {
  135. WIA_ERROR((TEXT("FATAL: hThumbnail was NULL!")));
  136. }
  137. }
  138. else
  139. {
  140. WIA_ERROR((TEXT("FATAL: pItem is NULL, not creating thumbnail")));
  141. }
  142. return nImageListIndex;
  143. }
  144. typedef struct {
  145. CPhotoSelectionPage * that;
  146. HWND hDlg;
  147. HWND hwndList;
  148. HIMAGELIST hImageList;
  149. CWizardInfoBlob * pWizInfo;
  150. } THUMB_PROC_INFO;
  151. VOID _AddItemToListView( CWizardInfoBlob * pWizInfo, HWND hwndList, INT iIndexOfItem, INT nImageListIndex )
  152. {
  153. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_AddItemToListView( iIndexOfItem = %d, nImageListIndex = %d)"),iIndexOfItem,nImageListIndex));
  154. //
  155. // Verify Params
  156. //
  157. if (!pWizInfo || !hwndList)
  158. {
  159. return;
  160. }
  161. //
  162. // Get item from master item list...
  163. //
  164. CListItem * pItem = pWizInfo->GetListItem(iIndexOfItem,FALSE);
  165. if (pItem)
  166. {
  167. //
  168. // Add a new listview item for this photo...
  169. //
  170. LVITEM lvItem = {0};
  171. lvItem.iItem = iIndexOfItem;
  172. lvItem.mask = LVIF_IMAGE|LVIF_PARAM|LVIF_STATE;
  173. lvItem.iImage = nImageListIndex;
  174. lvItem.lParam = reinterpret_cast<LPARAM>(pItem);
  175. //
  176. // If we're in force select all, the do select all
  177. //
  178. // ...else...
  179. //
  180. // If we only had one item in the initial selection,
  181. // and we're on the first item, then select it.
  182. //
  183. // ...else...
  184. //
  185. // Otherwise, do select all
  186. //
  187. if (pWizInfo->GetForceSelectAll())
  188. {
  189. pItem->SetSelectionState( TRUE );
  190. }
  191. else if (pWizInfo->ItemsInInitialSelection() == 1)
  192. {
  193. if (iIndexOfItem==0)
  194. {
  195. //
  196. // It's the first item, and there was only
  197. // one selected, so select this item.
  198. //
  199. pItem->SetSelectionState( TRUE );
  200. }
  201. else
  202. {
  203. //
  204. // There was only one item selected, but
  205. // these are the rest of the items from the
  206. // folder, so don't select them.
  207. //
  208. pItem->SetSelectionState( FALSE );
  209. }
  210. }
  211. else
  212. {
  213. //
  214. // Except the the one item selection case, everything else
  215. // defaults to all items selected in the wizard to begin with.
  216. //
  217. pItem->SetSelectionState( TRUE );
  218. }
  219. INT nResult = ListView_InsertItem( hwndList, &lvItem );
  220. if (nResult == -1)
  221. {
  222. WIA_ERROR((TEXT("Couldn't add item %d to ListView"),iIndexOfItem));
  223. pItem->SetSelectionState( FALSE );
  224. }
  225. else
  226. {
  227. ListView_SetCheckState( hwndList, nResult, pItem->SelectedForPrinting() );
  228. }
  229. }
  230. }
  231. /*****************************************************************************
  232. CPhotoSelectionPage::s_UpdateThumbnailThreadProc
  233. Thread which will go through and generate thumbnails for all the items
  234. in the listview...
  235. *****************************************************************************/
  236. DWORD CPhotoSelectionPage::s_UpdateThumbnailThreadProc(VOID *pv)
  237. {
  238. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::s_UpdateThumbnailThreadProc()")));
  239. //
  240. // Okay -- we can't have any code that calls back into the main UI
  241. // thread synchronously. That means no SendMessage calls in
  242. // particular. This is so that we can clean up nicely when the
  243. // user cancels and, of course, that message comes in on the main
  244. // UI thread, and we don't want to return until we know we've cleaned
  245. // up...
  246. //
  247. THUMB_PROC_INFO * pTPI = (THUMB_PROC_INFO *)pv;
  248. if (pTPI && pTPI->pWizInfo)
  249. {
  250. //
  251. // First thing -- addref our dll so we don't get unloaded...
  252. //
  253. HINSTANCE hDll = GetThreadHMODULE( s_UpdateThumbnailThreadProc );
  254. //
  255. // Initialize COM for this thread...
  256. //
  257. HRESULT hrCo = PPWCoInitialize();
  258. //
  259. // Add items to listview
  260. //
  261. if (pTPI->hwndList)
  262. {
  263. //
  264. // Tell the window not to redraw while we add these items
  265. //
  266. PostMessage( pTPI->hwndList, WM_SETREDRAW, FALSE, 0 );
  267. //
  268. // Wait until all items have been processed by pWizInfo
  269. //
  270. while ((!pTPI->pWizInfo->IsWizardShuttingDown()) && (!pTPI->pWizInfo->AllPicturesAdded()))
  271. {
  272. //
  273. // The items are not there yet for adding, wait another 1/2 second
  274. //
  275. Sleep( 500 );
  276. }
  277. //
  278. // Get the number of items
  279. //
  280. LONG nItemCount = pTPI->pWizInfo->CountOfPhotos(FALSE);
  281. WIA_TRACE((TEXT("There are %d photos to add to the listview"),nItemCount));
  282. //
  283. // Loop through all the photos and add them...
  284. //
  285. CListItem * pItem = NULL;
  286. INT nImageListIndex = -1;
  287. for (INT i=0; (!pTPI->pWizInfo->IsWizardShuttingDown()) && (i < nItemCount); i++)
  288. {
  289. //
  290. // Tell the user what's going on...
  291. //
  292. PostMessage( pTPI->hDlg, PSP_MSG_UPDATE_ITEM_COUNT, i+1, nItemCount );
  293. pItem = pTPI->pWizInfo->GetListItem(i,FALSE);
  294. if (pItem)
  295. {
  296. //
  297. // Get class icon for this image...
  298. //
  299. nImageListIndex = _AddThumbnailToListViewImageList( pTPI->pWizInfo, pTPI->hDlg, pTPI->hwndList, pTPI->hImageList, pItem, i, TRUE );
  300. //
  301. // Tell main UI thread to add this item to the listview...
  302. //
  303. PostMessage( pTPI->hDlg, PSP_MSG_ADD_ITEM, i, nImageListIndex );
  304. }
  305. }
  306. //
  307. // Make sure the first item is selected and has the focus
  308. //
  309. PostMessage( pTPI->hDlg, PSP_MSG_SELECT_ITEM, 0, 0 );
  310. //
  311. // Tell the window to redraw now, because we are done. Invalidate the window, in case it is visible
  312. //
  313. PostMessage( pTPI->hwndList, WM_SETREDRAW, TRUE, 0 );
  314. PostMessage( pTPI->hDlg, PSP_MSG_INVALIDATE_LISTVIEW, 0, 0 );
  315. //
  316. // If there were items rejected, say so...
  317. //
  318. if (pTPI->pWizInfo->ItemsWereRejected())
  319. {
  320. WIA_TRACE((TEXT("ItemsWereRejected is TRUE, setting message...")));
  321. PostMessage( pTPI->hDlg, PSP_MSG_NOT_ALL_LOADED, 0, 0 );
  322. }
  323. else
  324. {
  325. //
  326. // otherwise, clear temporary status area...
  327. //
  328. WIA_TRACE((TEXT("ItemsWereRejected is FALSE, resetting message area...")));
  329. PostMessage( pTPI->hDlg, PSP_MSG_CLEAR_STATUS, 0, 0 );
  330. }
  331. //
  332. // If there are 0 items, then let's disable the "Select All" and "Clear All" buttons
  333. //
  334. PostMessage( pTPI->hDlg, PSP_MSG_ENABLE_BUTTONS, (WPARAM)nItemCount, 0 );
  335. //
  336. // Now, loop through and update all the thumbnails with the correct images...
  337. //
  338. pItem = NULL;
  339. nImageListIndex = -1;
  340. for (INT i=0; (!pTPI->pWizInfo->IsWizardShuttingDown()) && (i < nItemCount); i++)
  341. {
  342. pItem = pTPI->pWizInfo->GetListItem(i,FALSE);
  343. if (pItem)
  344. {
  345. nImageListIndex = _AddThumbnailToListViewImageList( pTPI->pWizInfo, pTPI->hDlg, pTPI->hwndList, pTPI->hImageList, pItem, i, FALSE );
  346. if (nImageListIndex >= 0)
  347. {
  348. WIA_TRACE((TEXT("Updating thumbnail for listview item %d"),i));
  349. PostMessage( pTPI->hDlg, PSP_MSG_UPDATE_THUMBNAIL, i, nImageListIndex );
  350. }
  351. }
  352. }
  353. }
  354. else
  355. {
  356. WIA_ERROR((TEXT("FATAL: Couldn't get hwndList")));
  357. }
  358. pTPI->pWizInfo->Release();
  359. delete [] pTPI;
  360. //
  361. // Unitialize COM
  362. //
  363. PPWCoUninitialize(hrCo);
  364. //
  365. // Exit the thread
  366. //
  367. if (hDll)
  368. {
  369. FreeLibraryAndExitThread( hDll, 0 );
  370. }
  371. }
  372. return 0;
  373. }
  374. /*****************************************************************************
  375. CPhotoSelectionPage::_PopulateListView
  376. Gets thumbnails for each of the items in the list view...
  377. *****************************************************************************/
  378. VOID CPhotoSelectionPage::_PopulateListView()
  379. {
  380. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_PopulateListView()")));
  381. if (!_pWizInfo)
  382. {
  383. WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
  384. return;
  385. }
  386. //
  387. // Do all the population on the background thread...
  388. //
  389. THUMB_PROC_INFO * pTPI = (THUMB_PROC_INFO *) new BYTE[sizeof(THUMB_PROC_INFO)];
  390. if (pTPI)
  391. {
  392. pTPI->that = this;
  393. pTPI->hDlg = _hDlg;
  394. pTPI->hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
  395. pTPI->hImageList = ListView_GetImageList( pTPI->hwndList, LVSIL_NORMAL );
  396. _pWizInfo->AddRef(); // make sure it doesn't go away while the thread is running...
  397. pTPI->pWizInfo = _pWizInfo;
  398. //
  399. // Create the thumbnail update thread...
  400. //
  401. _hThumbnailThread = CreateThread( NULL, 0, s_UpdateThumbnailThreadProc, (LPVOID)pTPI, CREATE_SUSPENDED, NULL );
  402. if (!_hThumbnailThread)
  403. {
  404. WIA_ERROR((TEXT("CreateThread( s_UpdateThumbnailThreadProc ) failed!")));
  405. _pWizInfo->Release();
  406. delete [] pTPI;
  407. }
  408. else
  409. {
  410. SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_BELOW_NORMAL );
  411. ResumeThread( _hThumbnailThread );
  412. }
  413. }
  414. }
  415. /*****************************************************************************
  416. CPhotoSelectionPage::OnInitDialog
  417. Handle initializing the wizard page...
  418. *****************************************************************************/
  419. LRESULT CPhotoSelectionPage::_OnInitDialog()
  420. {
  421. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnInitDialog()")));
  422. if (!_pWizInfo)
  423. {
  424. WIA_ERROR((TEXT("FATAL: _pWizInfo is NULL, exiting early")));
  425. return FALSE;
  426. }
  427. //
  428. // Register ourselves with _pWizInfo
  429. //
  430. _pWizInfo->SetPhotoSelectionPageClass( this );
  431. //
  432. // Initialize Thumbnail Listview control
  433. //
  434. HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
  435. if (hwndList)
  436. {
  437. //
  438. // Get the number of items
  439. //
  440. LONG nItemCount = _pWizInfo->CountOfPhotos(FALSE);
  441. WIA_TRACE((TEXT("There are %d photos to add to the listview"),nItemCount));
  442. //
  443. // If there are 0 items, then let's disable the "Select All" and "Clear All" buttons
  444. //
  445. EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (nItemCount > 0) );
  446. EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), (nItemCount > 0) );
  447. //
  448. // Hide the labels and use border selection
  449. //
  450. ListView_SetExtendedListViewStyleEx( hwndList, LVS_EX_FLAGS, LVS_EX_FLAGS );
  451. //
  452. // Create the image list
  453. //
  454. HIMAGELIST hImageList = ImageList_Create( _pWizInfo->_sizeThumbnails.cx, _pWizInfo->_sizeThumbnails.cy, ILC_COLOR32|ILC_MIRROR, nItemCount, 50 );
  455. if (hImageList)
  456. {
  457. //
  458. // Set the background color
  459. //
  460. COLORREF dw = (COLORREF)GetSysColor( COLOR_WINDOW );
  461. ImageList_SetBkColor( hImageList, dw );
  462. //
  463. // Create the default thumbnail
  464. //
  465. HBITMAP hBmpDefaultThumbnail = WiaUiUtil::CreateIconThumbnail( hwndList, _pWizInfo->_sizeThumbnails.cx, _pWizInfo->_sizeThumbnails.cy, g_hInst, IDI_UNAVAILABLE, CSimpleString( IDS_DOWNLOADINGTHUMBNAIL, g_hInst) );
  466. if (hBmpDefaultThumbnail)
  467. {
  468. _pWizInfo->_nDefaultThumbnailImageListIndex = ImageList_Add( hImageList, hBmpDefaultThumbnail, NULL );
  469. DeleteObject( hBmpDefaultThumbnail );
  470. }
  471. //
  472. // Set the image list
  473. //
  474. ListView_SetImageList( hwndList, hImageList, LVSIL_NORMAL );
  475. //
  476. // Set the spacing
  477. //
  478. ListView_SetIconSpacing( hwndList, _pWizInfo->_sizeThumbnails.cx + c_nAdditionalMarginX, _pWizInfo->_sizeThumbnails.cy + c_nAdditionalMarginY );
  479. //
  480. // Set the item count, to minimize recomputing the list size
  481. //
  482. ListView_SetItemCount( hwndList, nItemCount );
  483. //
  484. // Create a small image list, to prevent the checkbox state images from being resized in WM_SYSCOLORCHANGE
  485. //
  486. HIMAGELIST hImageListSmall = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 1, 1 );
  487. if (hImageListSmall)
  488. {
  489. ListView_SetImageList( hwndList, hImageListSmall, LVSIL_SMALL );
  490. }
  491. }
  492. else
  493. {
  494. WIA_ERROR((TEXT("FATAL: Creation of the imagelist failed!")));
  495. return FALSE;
  496. }
  497. }
  498. else
  499. {
  500. WIA_ERROR((TEXT("FATAL: Couldn't get listview")));
  501. }
  502. //
  503. // Populate the list view
  504. //
  505. _PopulateListView();
  506. return TRUE;
  507. }
  508. /*****************************************************************************
  509. CPhotoSelectionPage::OnCommand
  510. Handle WM_COMMAND for this dlg page
  511. *****************************************************************************/
  512. LRESULT CPhotoSelectionPage::_OnCommand( WPARAM wParam, LPARAM lParam )
  513. {
  514. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnCommand()")));
  515. WORD wNotifyCode = HIWORD(wParam);
  516. WORD wID = LOWORD(wParam);
  517. HWND hwndCtrl = (HWND)lParam;
  518. switch (wID)
  519. {
  520. case IDC_SELECTALL:
  521. if (_pWizInfo)
  522. {
  523. HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
  524. if (hwndList)
  525. {
  526. CListItem * pItem = NULL;
  527. for (INT i=0; i < _pWizInfo->CountOfPhotos(FALSE); i++)
  528. {
  529. pItem = _pWizInfo->GetListItem(i,FALSE);
  530. if (pItem)
  531. {
  532. pItem->SetSelectionState(TRUE);
  533. ListView_SetCheckState( hwndList, i, TRUE );
  534. }
  535. }
  536. //
  537. // Now mark for all copies as well...
  538. //
  539. for (INT i=0; i < _pWizInfo->CountOfPhotos(TRUE); i++)
  540. {
  541. pItem = _pWizInfo->GetListItem(i,TRUE);
  542. if (pItem)
  543. {
  544. pItem->SetSelectionState(TRUE);
  545. }
  546. }
  547. }
  548. _pWizInfo->SetPreviewsAreDirty(TRUE);
  549. }
  550. break;
  551. case IDC_CLEARALL:
  552. if (_pWizInfo)
  553. {
  554. HWND hwndList = GetDlgItem( _hDlg, IDC_THUMBNAILS );
  555. if (hwndList)
  556. {
  557. CListItem * pItem = NULL;
  558. for (INT i=0; i < _pWizInfo->CountOfPhotos(FALSE); i++)
  559. {
  560. pItem = _pWizInfo->GetListItem(i,FALSE);
  561. if (pItem)
  562. {
  563. pItem->SetSelectionState(FALSE);
  564. ListView_SetCheckState( hwndList, i, FALSE );
  565. }
  566. }
  567. //
  568. // Now mark for all copies as well...
  569. //
  570. for (INT i=0; i < _pWizInfo->CountOfPhotos(TRUE); i++)
  571. {
  572. pItem = _pWizInfo->GetListItem(i,TRUE);
  573. if (pItem)
  574. {
  575. pItem->SetSelectionState(FALSE);
  576. }
  577. }
  578. }
  579. _pWizInfo->SetPreviewsAreDirty(TRUE);
  580. }
  581. break;
  582. }
  583. return 0;
  584. }
  585. /*****************************************************************************
  586. CPhotoSelectionPage::OnDestroy
  587. Handle WM_DESTROY message for this wizard page...
  588. *****************************************************************************/
  589. LRESULT CPhotoSelectionPage::_OnDestroy()
  590. {
  591. WIA_PUSH_FUNCTION_MASK((TRACE_PAGE_PHOTO_SEL, TEXT("CPhotoSelectionPage::_OnDestroy()")));
  592. //
  593. // Nuke the large imagelist
  594. //
  595. HIMAGELIST hImageList = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, LVSIL_NORMAL );
  596. if (hImageList)
  597. {
  598. ImageList_Destroy(hImageList);
  599. }
  600. //
  601. // Nuke the small imagelist
  602. //
  603. hImageList = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, LVSIL_SMALL );
  604. if (hImageList)
  605. {
  606. ImageList_Destroy(hImageList);
  607. }
  608. return 0;
  609. }
  610. /*****************************************************************************
  611. CPhotoSelectionPage::_OnNotify
  612. Handles WM_NOTIFY messages...
  613. *****************************************************************************/
  614. LRESULT CPhotoSelectionPage::_OnNotify( WPARAM wParam, LPARAM lParam )
  615. {
  616. WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CPhotoSelectionPage::_OnNotify()")));
  617. LPNMHDR pnmh = (LPNMHDR)lParam;
  618. LONG_PTR lpRes = 0;
  619. switch (pnmh->code)
  620. {
  621. case PSN_SETACTIVE:
  622. WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_SETACTIVE")));
  623. {
  624. //
  625. // Set the thread priority of thumbnail generation thread
  626. // to be our normal (which is below normal) since we're
  627. // on this page...
  628. //
  629. if (_hThumbnailThread)
  630. {
  631. SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_BELOW_NORMAL );
  632. }
  633. lpRes = 0;
  634. DWORD dwFlags = PSWIZB_BACK;
  635. _bActive = TRUE;
  636. if (_pWizInfo)
  637. {
  638. if (_pWizInfo->CountOfSelectedPhotos(FALSE) > 0)
  639. dwFlags |= PSWIZB_NEXT;
  640. }
  641. PropSheet_SetWizButtons( GetParent(_hDlg), dwFlags );
  642. }
  643. break;
  644. case PSN_KILLACTIVE:
  645. WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_KILLACTIVE")));
  646. //
  647. // Since we're leaving this thread, set the priority of the
  648. // thread doing the listview thumbnail generation to even
  649. // lower than normal...
  650. //
  651. if (_hThumbnailThread)
  652. {
  653. SetThreadPriority( _hThumbnailThread, THREAD_PRIORITY_LOWEST );
  654. }
  655. _bActive = FALSE;
  656. lpRes = 0;
  657. break;
  658. case PSN_WIZNEXT:
  659. WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_WIZNEXT")));
  660. lpRes = IDD_PRINTING_OPTIONS;
  661. break;
  662. case PSN_WIZBACK:
  663. WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_WIZBACK")));
  664. lpRes = IDD_START_PAGE;
  665. break;
  666. case PSN_QUERYCANCEL:
  667. WIA_TRACE((TEXT("CPhotoSelectionPage: got PSN_QUERYCANCEL")));
  668. if (_pWizInfo)
  669. {
  670. lpRes = _pWizInfo->UserPressedCancel();
  671. }
  672. break;
  673. case LVN_ITEMCHANGED:
  674. {
  675. NMLISTVIEW *pNmListView = reinterpret_cast<NMLISTVIEW*>(lParam);
  676. if (pNmListView)
  677. {
  678. //
  679. // If this is a state change (check marks are stored as state image indices)
  680. //
  681. if ((pNmListView->uChanged & LVIF_STATE) && ((pNmListView->uOldState&LVIS_STATEIMAGEMASK) ^ (pNmListView->uNewState&LVIS_STATEIMAGEMASK)))
  682. {
  683. //
  684. // Get the item * from the LVITEM structure
  685. //
  686. CListItem *pItem = reinterpret_cast<CListItem *>(pNmListView->lParam);
  687. if (pItem)
  688. {
  689. //
  690. // If just added is true, ignore this notification, because
  691. // we unfortunately get two notifications for items with check
  692. // state set. The first time, it is not set, so if we process it,
  693. // it will clear the selection state.
  694. //
  695. if (pItem->JustAdded())
  696. {
  697. pItem->SetJustAdded(FALSE);
  698. }
  699. else
  700. {
  701. //
  702. // Set selected flag in the item
  703. //
  704. pItem->SetSelectionState( IsStateChecked(pNmListView->uNewState) );
  705. if (_pWizInfo)
  706. {
  707. //
  708. // toggle all copies as well..
  709. //
  710. _pWizInfo->ToggleSelectionStateOnCopies( pItem, IsStateChecked(pNmListView->uNewState) );
  711. //
  712. // The previews are wrong, mark them as such...
  713. //
  714. _pWizInfo->SetPreviewsAreDirty(TRUE);
  715. if (_bActive)
  716. {
  717. DWORD dwFlags = PSWIZB_BACK;
  718. if (_pWizInfo->CountOfSelectedPhotos(FALSE) > 0)
  719. {
  720. dwFlags |= PSWIZB_NEXT;
  721. EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), TRUE );
  722. }
  723. else
  724. {
  725. EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), FALSE );
  726. }
  727. EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (_pWizInfo->CountOfSelectedPhotos(FALSE) != _pWizInfo->CountOfPhotos(FALSE)) ? TRUE : FALSE );
  728. PropSheet_SetWizButtons( GetParent(_hDlg), dwFlags );
  729. }
  730. }
  731. }
  732. }
  733. }
  734. }
  735. }
  736. break;
  737. }
  738. SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, lpRes );
  739. return TRUE;
  740. }
  741. /*****************************************************************************
  742. CPhotoSelectionPage::DoHandleMessage
  743. Hanlder for messages sent to this page...
  744. *****************************************************************************/
  745. INT_PTR CPhotoSelectionPage::DoHandleMessage( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  746. {
  747. WIA_PUSH_FUNCTION_MASK((TRACE_DLGPROC, TEXT("CPhotoSelectionPage::DoHandleMessage( uMsg = 0x%x, wParam = 0x%x, lParam = 0x%x )"),uMsg,wParam,lParam));
  748. static CSimpleString strFormat( IDS_NUM_IMAGES_FORMAT, g_hInst );
  749. static CSimpleString strMessage;
  750. switch ( uMsg )
  751. {
  752. case WM_INITDIALOG:
  753. {
  754. _hDlg = hDlg;
  755. return _OnInitDialog();
  756. }
  757. case WM_COMMAND:
  758. return _OnCommand(wParam, lParam);
  759. case WM_DESTROY:
  760. return _OnDestroy();
  761. case WM_NOTIFY:
  762. return _OnNotify(wParam, lParam);
  763. case WM_SYSCOLORCHANGE:
  764. //
  765. // Forward the color change message, and send a bogus setting change message, just
  766. // to be sure the control repaints
  767. //
  768. SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SYSCOLORCHANGE, wParam, lParam );
  769. SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SETTINGCHANGE, 0, 0 );
  770. break;
  771. case WM_SETTINGCHANGE:
  772. {
  773. //
  774. // Create a small image list, to prevent the checkbox state images from being resized in WM_SYSCOLORCHANGE
  775. //
  776. HIMAGELIST hImageListSmall = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32|ILC_MASK, 1, 1 );
  777. if (hImageListSmall)
  778. {
  779. //
  780. // Set the new image list and destroy the old one
  781. //
  782. HIMAGELIST hImgListOld = ListView_SetImageList( GetDlgItem( _hDlg, IDC_THUMBNAILS ), hImageListSmall, LVSIL_SMALL );
  783. if (hImgListOld)
  784. {
  785. ImageList_Destroy(hImgListOld);
  786. }
  787. }
  788. //
  789. // Forward the setting change message, and send a bogus color change message, just
  790. // to be sure the control repaints
  791. //
  792. SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SETTINGCHANGE, wParam, lParam );
  793. SendDlgItemMessage( _hDlg, IDC_THUMBNAILS, WM_SYSCOLORCHANGE, 0, 0 );
  794. }
  795. break;
  796. case PSP_MSG_UPDATE_ITEM_COUNT:
  797. strMessage.Format( strFormat, wParam, lParam );
  798. strMessage.SetWindowText( GetDlgItem( _hDlg, IDC_NUM_IMAGES ) );
  799. break;
  800. case PSP_MSG_ADD_ITEM:
  801. _AddItemToListView( _pWizInfo, GetDlgItem( _hDlg, IDC_THUMBNAILS ), (INT)wParam, (INT)lParam );
  802. break;
  803. case PSP_MSG_SELECT_ITEM:
  804. ListView_SetItemState( GetDlgItem( _hDlg, IDC_THUMBNAILS ), wParam, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
  805. break;
  806. case PSP_MSG_NOT_ALL_LOADED:
  807. {
  808. CSimpleString strReject( IDS_NOT_ALL_IMAGES_WILL_PRINT, g_hInst );
  809. SetDlgItemText( _hDlg, IDC_NUM_IMAGES, strReject.String() );
  810. }
  811. break;
  812. case PSP_MSG_CLEAR_STATUS:
  813. SetDlgItemText( _hDlg, IDC_NUM_IMAGES, TEXT("") );
  814. break;
  815. case PSP_MSG_UPDATE_THUMBNAIL:
  816. {
  817. LVITEM lvItem = {0};
  818. lvItem.iItem = (INT)wParam;
  819. lvItem.mask = LVIF_IMAGE;
  820. lvItem.iImage = (INT)lParam;
  821. ListView_SetItem( GetDlgItem( _hDlg, IDC_THUMBNAILS ), &lvItem );
  822. }
  823. break;
  824. case PSP_MSG_ENABLE_BUTTONS:
  825. if (_pWizInfo)
  826. {
  827. EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), (((INT)wParam > 0) && (_pWizInfo->CountOfSelectedPhotos(FALSE) != _pWizInfo->CountOfPhotos(FALSE))) ? TRUE : FALSE );
  828. }
  829. else
  830. {
  831. EnableWindow( GetDlgItem( _hDlg, IDC_SELECTALL ), ((INT)wParam > 0) );
  832. }
  833. EnableWindow( GetDlgItem( _hDlg, IDC_CLEARALL ), ((INT)wParam > 0) );
  834. break;
  835. case PSP_MSG_INVALIDATE_LISTVIEW:
  836. InvalidateRect( GetDlgItem( _hDlg, IDC_THUMBNAILS ), NULL, FALSE );
  837. break;
  838. }
  839. return FALSE;
  840. }