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.

1456 lines
32 KiB

  1. //
  2. // Copyright 2001 - Microsoft Corporation
  3. //
  4. //
  5. // Created By:
  6. // Geoff Pease (GPease) 23-JAN-2001
  7. //
  8. // Maintained By:
  9. // Geoff Pease (GPease) 23-JAN-2001
  10. //
  11. #include "pch.h"
  12. #include "DocProp.h"
  13. #include "DefProp.h"
  14. #include "IEditVariantsInPlace.h"
  15. #include "PropertyCacheItem.h"
  16. #include "PropertyCache.h"
  17. #include "AdvancedDlg.h"
  18. #include "shutils.h"
  19. #include "WMUser.h"
  20. #include "IEditVariantsInPlace.h"
  21. #include "EditTypeItem.h"
  22. #pragma hdrstop
  23. DEFINE_THISCLASS( "CAdvancedDlg" )
  24. //
  25. // This value is the offset of images in the bitmap representing the
  26. // icons when multiple documents have been selected.
  27. //
  28. #define MULTIDOC_IMAGE_OFFSET_VALUE 2
  29. // ************************************************************************
  30. //
  31. // Constructor / Destructor
  32. //
  33. // ************************************************************************
  34. //
  35. // Return Values:
  36. // S_OK
  37. // A new CAdvancedDlg was created successfully.
  38. //
  39. // E_OUTOFMEMORY
  40. // Out of memory.
  41. //
  42. // other HRESULTs.
  43. //
  44. HRESULT
  45. CAdvancedDlg::CreateInstance(
  46. CAdvancedDlg ** pAdvDlgOut
  47. , HWND hwndParentIn
  48. )
  49. {
  50. TraceFunc( "" );
  51. HRESULT hr;
  52. Assert( pAdvDlgOut != NULL );
  53. CAdvancedDlg * pthis = new CAdvancedDlg;
  54. if ( pthis != NULL )
  55. {
  56. hr = THR( pthis->Init( hwndParentIn ) );
  57. if ( SUCCEEDED( hr ) )
  58. {
  59. *pAdvDlgOut = pthis;
  60. (*pAdvDlgOut)->AddRef( );
  61. }
  62. pthis->Release( );
  63. }
  64. else
  65. {
  66. hr = E_OUTOFMEMORY;
  67. }
  68. HRETURN( hr );
  69. }
  70. //
  71. // Constructor
  72. //
  73. CAdvancedDlg::CAdvancedDlg( void )
  74. : _cRef( 1 )
  75. {
  76. TraceFunc( "" );
  77. Assert( 1 == _cRef );
  78. Assert( NULL == _hwndParent );
  79. Assert( NULL == _hdlg );
  80. Assert( NULL == _hwndList );
  81. Assert( NULL == _pEdit );
  82. Assert( NULL == _pItem );
  83. InterlockedIncrement( &g_cObjects );
  84. TraceFuncExit();
  85. }
  86. //
  87. // Description:
  88. // Intializes the instance of the class. Put things that can
  89. // fail into this method.
  90. //
  91. HRESULT
  92. CAdvancedDlg::Init(
  93. HWND hwndParentIn
  94. )
  95. {
  96. TraceFunc( "" );
  97. HRESULT hr = S_OK;
  98. _hwndParent = hwndParentIn;
  99. // IUnknown stuff
  100. Assert( _cRef == 1 );
  101. //
  102. // Initialize the common controls
  103. //
  104. INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX)
  105. , ICC_LISTVIEW_CLASSES | ICC_USEREX_CLASSES | ICC_DATE_CLASSES
  106. };
  107. BOOL b = TBOOL( InitCommonControlsEx( &iccx ) );
  108. if ( !b )
  109. goto ErrorGLE;
  110. //
  111. // Create the dialog
  112. //
  113. _hdlg = CreateDialogParam( g_hInstance
  114. , MAKEINTRESOURCE(IDD_ADVANCEDVIEW)
  115. , _hwndParent
  116. , DlgProc
  117. , (LPARAM) this
  118. );
  119. if ( NULL == _hdlg )
  120. goto ErrorGLE;
  121. Cleanup:
  122. HRETURN( hr );
  123. ErrorGLE:
  124. {
  125. DWORD dwErr = TW32( GetLastError( ) );
  126. hr = HRESULT_FROM_WIN32( dwErr );
  127. }
  128. goto Cleanup;
  129. }
  130. //
  131. // Destructor
  132. //
  133. CAdvancedDlg::~CAdvancedDlg( )
  134. {
  135. TraceFunc( "" );
  136. if ( NULL != _pEdit )
  137. {
  138. _pEdit->Release( );
  139. }
  140. if ( NULL != _hdlg )
  141. {
  142. DestroyWindow( _hdlg );
  143. }
  144. Assert( 0 != g_cObjects );
  145. InterlockedDecrement( &g_cObjects );
  146. TraceFuncExit();
  147. }
  148. // ************************************************************************
  149. //
  150. // IUnknown
  151. //
  152. // ************************************************************************
  153. //
  154. // QueryInterface
  155. //
  156. STDMETHODIMP
  157. CAdvancedDlg::QueryInterface(
  158. REFIID riid,
  159. LPVOID *ppv
  160. )
  161. {
  162. TraceQIFunc( riid, ppv );
  163. HRESULT hr = E_NOINTERFACE;
  164. if ( IsEqualIID( riid, __uuidof(IUnknown) ) )
  165. {
  166. *ppv = static_cast< IUnknown * >( this );
  167. hr = S_OK;
  168. }
  169. #if 0
  170. else if ( IsEqualIID( riid, __uuidof(IShellExtInit) ) )
  171. {
  172. *ppv = TraceInterface( __THISCLASS__, IShellExtInit, this, 0 );
  173. hr = S_OK;
  174. }
  175. #endif
  176. if ( SUCCEEDED( hr ) )
  177. {
  178. ((IUnknown*) *ppv)->AddRef( );
  179. }
  180. QIRETURN( hr, riid );
  181. }
  182. //
  183. // AddRef
  184. //
  185. STDMETHODIMP_(ULONG)
  186. CAdvancedDlg::AddRef( void )
  187. {
  188. TraceFunc( "[IUnknown]" );
  189. _cRef ++; // apartment
  190. RETURN( _cRef );
  191. }
  192. //
  193. // Release
  194. //
  195. STDMETHODIMP_(ULONG)
  196. CAdvancedDlg::Release( void )
  197. {
  198. TraceFunc( "[IUnknown]" );
  199. _cRef --; // apartment
  200. if ( 0 != _cRef )
  201. RETURN( _cRef );
  202. delete this;
  203. RETURN( 0 );
  204. }
  205. // ***************************************************************************
  206. //
  207. // Dialog Proc and Property Sheet Callback
  208. //
  209. // ***************************************************************************
  210. //
  211. // DlgProc
  212. //
  213. INT_PTR CALLBACK
  214. CAdvancedDlg::DlgProc(
  215. HWND hDlgIn
  216. , UINT uMsgIn
  217. , WPARAM wParam
  218. , LPARAM lParam
  219. )
  220. {
  221. // Don't do TraceFunc because every mouse movement will cause this function to be called.
  222. WndMsg( hDlgIn, uMsgIn, wParam, lParam );
  223. LRESULT lr = FALSE;
  224. CAdvancedDlg * pPage = (CAdvancedDlg *) GetWindowLongPtr( hDlgIn, DWLP_USER );
  225. if ( uMsgIn == WM_INITDIALOG )
  226. {
  227. SetWindowLongPtr( hDlgIn, DWLP_USER, lParam );
  228. pPage = (CAdvancedDlg *) lParam ;
  229. pPage->_hdlg = hDlgIn;
  230. }
  231. if ( pPage != NULL )
  232. {
  233. Assert( hDlgIn == pPage->_hdlg );
  234. switch( uMsgIn )
  235. {
  236. case WM_INITDIALOG:
  237. lr = pPage->OnInitDialog( );
  238. break;
  239. case WM_COMMAND:
  240. lr = pPage->OnCommand( HIWORD(wParam), LOWORD(wParam), LPARAM(lParam) );
  241. break;
  242. case WM_NOTIFY:
  243. lr = pPage->OnNotify( (int) wParam, (LPNMHDR) lParam );
  244. break;
  245. case WM_SETFOCUS:
  246. lr = SendMessage( pPage->_hwndList, WM_SETFOCUS, wParam, lParam );
  247. break;
  248. case WM_DESTROY:
  249. SetWindowLongPtr( hDlgIn, DWLP_USER, NULL );
  250. lr = pPage->OnDestroy( );
  251. break;
  252. case WM_HELP:
  253. lr = pPage->OnHelp( (LPHELPINFO) lParam );
  254. break;
  255. case WM_CONTEXTMENU:
  256. lr = pPage->OnContextMenu( (HWND) wParam, LOWORD(lParam), HIWORD(lParam) );
  257. break;
  258. }
  259. }
  260. return lr;
  261. }
  262. //
  263. // ListViewSubProc
  264. //
  265. LRESULT CALLBACK
  266. CAdvancedDlg::ListViewSubclassProc(
  267. HWND hwndIn
  268. , UINT uMsgIn
  269. , WPARAM wParam
  270. , LPARAM lParam
  271. , UINT_PTR uIdSubclassIn
  272. , DWORD_PTR dwRefDataIn
  273. )
  274. {
  275. // Don't do TraceFunc because every mouse movement will cause this function to be called.
  276. WndMsg( hwndIn, uMsgIn, wParam, lParam );
  277. LRESULT lr = FALSE;
  278. CAdvancedDlg * pPage = (CAdvancedDlg *) dwRefDataIn;
  279. Assert( NULL != pPage );
  280. Assert( hwndIn == pPage->_hwndList );
  281. Assert( IDC_PROPERTIES == uIdSubclassIn );
  282. switch( uMsgIn )
  283. {
  284. case WM_COMMAND:
  285. return pPage->List_OnCommand( LOWORD(wParam), HIWORD(wParam), lParam );
  286. case WM_NOTIFY:
  287. return pPage->List_OnNotify( (int) wParam, (LPNMHDR) lParam );
  288. case WM_VSCROLL:
  289. return pPage->List_OnVertScroll( LOWORD(wParam), HIWORD(wParam), (HWND) lParam );
  290. case WM_HSCROLL:
  291. return pPage->List_OnHornScroll( LOWORD(wParam), HIWORD(wParam), (HWND) lParam );
  292. case WM_CHAR:
  293. return pPage->List_OnChar( (UINT) wParam, lParam );
  294. case WM_KEYDOWN:
  295. return pPage->List_OnKeyDown( (UINT) wParam, lParam );
  296. }
  297. return DefSubclassProc( hwndIn, uMsgIn, wParam, lParam );
  298. }
  299. // ***************************************************************************
  300. //
  301. // Private methods
  302. //
  303. // ***************************************************************************
  304. //
  305. // WM_INITDIALOG handler
  306. //
  307. LRESULT
  308. CAdvancedDlg::OnInitDialog( void )
  309. {
  310. TraceFunc( "" );
  311. int iSize;
  312. LVCOLUMN lvc;
  313. TCHAR szTitle[ 64 ]; // random
  314. ULONG idxFolder;
  315. HIMAGELIST hil;
  316. LRESULT lr = TRUE; // set the focus
  317. Assert( NULL != _hdlg ); // this should have been initialized in the DlgProc.
  318. _hwndList = GetDlgItem( _hdlg, IDC_PROPERTIES );
  319. TBOOL( NULL != _hwndList );
  320. //
  321. // Enable ListView for Grouping mode.
  322. //
  323. SetWindowLongPtr( _hwndList, GWL_STYLE, GetWindowLongPtr( _hwndList, GWL_STYLE ) | LVS_AUTOARRANGE | LVS_SHOWSELALWAYS);
  324. ListView_SetExtendedListViewStyle( _hwndList, LVS_EX_FULLROWSELECT );
  325. ListView_EnableGroupView( _hwndList, TRUE );
  326. //
  327. // Add the image list
  328. //
  329. hil = ImageList_LoadImage( g_hInstance
  330. , MAKEINTRESOURCE(IDB_TREE_IMAGELIST)
  331. , 16
  332. , 0
  333. , RGB(255,0,255)
  334. , IMAGE_BITMAP
  335. , LR_SHARED
  336. );
  337. hil = ListView_SetImageList( _hwndList
  338. , hil
  339. , LVSIL_SMALL
  340. );
  341. Assert( NULL == hil ); // there shouldn't have been a previous image list.
  342. //
  343. // Setup up common values.
  344. //
  345. lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
  346. lvc.fmt = LVCFMT_LEFT;
  347. lvc.pszText = szTitle;
  348. //
  349. // Add Column 0
  350. //
  351. lvc.iSubItem = 0;
  352. iSize = LoadString( g_hInstance, IDS_PROPERTY_HEADER_ITEM, szTitle, ARRAYSIZE(szTitle) );
  353. AssertMsg( 0 != iSize, "Missing string resource?" );
  354. ListView_InsertColumn( _hwndList, 0, &lvc );
  355. //
  356. // Add Column 1
  357. //
  358. lvc.iSubItem = 1;
  359. iSize = LoadString( g_hInstance, IDS_VALUE_HEADER_ITEM, szTitle, ARRAYSIZE(szTitle) );
  360. AssertMsg( 0 != iSize, "Missing string resource?" );
  361. ListView_InsertColumn( _hwndList, 1, &lvc );
  362. //
  363. // Add the groups - In the end, if a group contains no items, the group
  364. // header will not be shown.
  365. //
  366. for ( idxFolder = 0; NULL != g_rgTopLevelFolders[ idxFolder ].pPFID; idxFolder ++ )
  367. {
  368. //
  369. // Add the property folder as a group item.
  370. //
  371. int iRet;
  372. WCHAR szBuf[ 256 ]; // random
  373. iRet = LoadString( g_hInstance, g_rgTopLevelFolders[ idxFolder ].nIDStringRes, szBuf, ARRAYSIZE(szBuf) );
  374. AssertMsg( 0 != iRet, "Missing resource?" );
  375. if ( 0 == iRet )
  376. continue;
  377. LVGROUP lvg;
  378. lvg.cbSize = sizeof(LVGROUP);
  379. lvg.mask = LVGF_HEADER | LVGF_GROUPID;
  380. lvg.iGroupId = idxFolder;
  381. lvg.pszHeader = szBuf;
  382. LRESULT iItem = ListView_InsertGroup( _hwndList, -1, &lvg );
  383. TBOOL( -1 != iItem );
  384. }
  385. //
  386. // Subclass the listview
  387. //
  388. TBOOL( SetWindowSubclass( _hwndList, ListViewSubclassProc, IDC_PROPERTIES, (DWORD_PTR) this ) );
  389. RETURN( lr );
  390. }
  391. //
  392. // WM_COMMAND handler
  393. //
  394. LRESULT
  395. CAdvancedDlg::OnCommand(
  396. WORD wCodeIn
  397. , WORD wCtlIn
  398. , LPARAM lParam
  399. )
  400. {
  401. TraceFunc( "" );
  402. LRESULT lr = FALSE;
  403. switch ( wCtlIn )
  404. {
  405. case IDC_SIMPLE:
  406. if ( BN_CLICKED == wCodeIn )
  407. {
  408. THR( (HRESULT) SendMessage( _hwndParent, WMU_TOGGLE, 0, 0 ) );
  409. }
  410. break;
  411. }
  412. RETURN( lr );
  413. }
  414. //
  415. // WM_NOTIFY handler
  416. //
  417. LRESULT
  418. CAdvancedDlg::OnNotify(
  419. int iCtlIdIn
  420. , LPNMHDR pnmhIn
  421. )
  422. {
  423. TraceFunc( "" );
  424. LRESULT lr = FALSE;
  425. switch( pnmhIn->code )
  426. {
  427. case NM_CLICK:
  428. lr = OnNotifyClick( (LPNMITEMACTIVATE) pnmhIn );
  429. break;
  430. }
  431. RETURN( lr );
  432. }
  433. //
  434. // NM_CLICK handler
  435. //
  436. LRESULT
  437. CAdvancedDlg::OnNotifyClick(
  438. LPNMITEMACTIVATE pnmIn
  439. )
  440. {
  441. TraceFunc( "" );
  442. LRESULT lr = S_FALSE;
  443. INT iItem;
  444. Assert( NULL != pnmIn );
  445. if ( -1 == pnmIn->iItem )
  446. {
  447. LVHITTESTINFO lvhti;
  448. lvhti.pt = pnmIn->ptAction;
  449. iItem = ListView_SubItemHitTest( _hwndList, &lvhti );
  450. if ( -1 == iItem )
  451. goto Cleanup;
  452. if ( 1 != lvhti.iSubItem )
  453. goto Cleanup;
  454. }
  455. else
  456. {
  457. if ( 1 != pnmIn->iSubItem )
  458. goto Cleanup;
  459. iItem = pnmIn->iItem;
  460. }
  461. STHR( CreateControlForProperty( iItem ) );
  462. Cleanup:
  463. RETURN( lr );
  464. }
  465. //
  466. // WM_NOTIFY handler for the ListView Subclass
  467. //
  468. LRESULT
  469. CAdvancedDlg::List_OnNotify(
  470. int iCtlIdIn
  471. , LPNMHDR pnmhIn
  472. )
  473. {
  474. TraceFunc( "" );
  475. LRESULT lr;
  476. switch( pnmhIn->code )
  477. {
  478. case NM_KILLFOCUS:
  479. if ( NULL != _pEdit )
  480. {
  481. STHR( PersistControlInProperty( ) );
  482. _pEdit->Release( );
  483. _pEdit = NULL;
  484. }
  485. break;
  486. }
  487. lr = DefSubclassProc( _hwndList, WM_NOTIFY, (WPARAM) iCtlIdIn, (LPARAM) pnmhIn );
  488. RETURN( lr );
  489. }
  490. //
  491. // WM_COMMAND handler for the ListView Subclass
  492. //
  493. LRESULT
  494. CAdvancedDlg::List_OnCommand(
  495. WORD wCtlIn
  496. , WORD wCodeIn
  497. , LPARAM lParam
  498. )
  499. {
  500. TraceFunc( "" );
  501. LRESULT lr = FALSE;
  502. switch ( wCtlIn )
  503. {
  504. case IDC_INPLACEEDIT:
  505. if ( EN_KILLFOCUS == wCodeIn || CBN_KILLFOCUS == wCodeIn )
  506. {
  507. if ( NULL != _pEdit )
  508. {
  509. STHR( PersistControlInProperty( ) );
  510. _pEdit->Release( );
  511. _pEdit = NULL;
  512. }
  513. }
  514. break;
  515. }
  516. lr = DefSubclassProc( _hwndList, WM_COMMAND, MAKEWPARAM( wCtlIn, wCodeIn ), lParam );
  517. RETURN( lr );
  518. }
  519. //
  520. // WM_CHAR handler for ListView Subclass
  521. //
  522. LRESULT
  523. CAdvancedDlg::List_OnChar(
  524. UINT uKeyCodeIn
  525. , LPARAM lParam
  526. )
  527. {
  528. TraceFunc( "" );
  529. HRESULT hr;
  530. LRESULT lr = FALSE;
  531. #if 0
  532. SHORT sRepeatCount = ( lParam & 0xFFFF );
  533. SHORT sScanCode = ( lParam & 0xF0000 ) >> 16;
  534. BOOL fExtended = ( lParam & 0x100000 ) != 0;
  535. BOOL fContext = ( lParam & 0x40000000 ) != 0;
  536. BOOL fTransition = ( lParam & 0x80000000 ) != 0;
  537. #endif
  538. INT iItem = ListView_GetSelectionMark( _hwndList );
  539. if ( -1 == iItem )
  540. return DefSubclassProc( _hwndList, WM_KEYDOWN, uKeyCodeIn, lParam );
  541. hr = STHR( CreateControlForProperty( iItem ) );
  542. if ( S_OK == hr )
  543. {
  544. HWND hwnd = GetFocus( );
  545. if ( _hwndList != hwnd )
  546. {
  547. lr = SendMessage( hwnd, WM_CHAR, (WPARAM) uKeyCodeIn, lParam );
  548. }
  549. }
  550. RETURN( lr );
  551. }
  552. //
  553. // WM_KEYDOWN handler for ListView Subclass
  554. //
  555. LRESULT
  556. CAdvancedDlg::List_OnKeyDown(
  557. UINT uKeyCodeIn
  558. , LPARAM lParam
  559. )
  560. {
  561. TraceFunc( "" );
  562. LRESULT lr = FALSE;
  563. #if 0
  564. SHORT sRepeatCount = ( lParam & 0xFFFF );
  565. SHORT sScanCode = ( lParam & 0xF0000 ) >> 16;
  566. BOOL fExtended = ( lParam & 0x100000 ) != 0;
  567. BOOL fContext = ( lParam & 0x40000000 ) != 0;
  568. BOOL fTransition = ( lParam & 0x80000000 ) != 0;
  569. #endif
  570. switch ( uKeyCodeIn )
  571. {
  572. case VK_F2:
  573. {
  574. INT iItem = ListView_GetSelectionMark( _hwndList );
  575. if ( -1 != iItem )
  576. {
  577. STHR( CreateControlForProperty( iItem ) );
  578. }
  579. }
  580. // fall thru
  581. default:
  582. lr = DefSubclassProc( _hwndList, WM_KEYDOWN, (WPARAM) uKeyCodeIn, lParam );
  583. break;
  584. }
  585. RETURN( lr );
  586. }
  587. //
  588. // WM_VSCROLL handler
  589. //
  590. LRESULT
  591. CAdvancedDlg::List_OnVertScroll(
  592. WORD wCodeIn
  593. , WORD wPosIn
  594. , HWND hwndFromIn
  595. )
  596. {
  597. TraceFunc( "" );
  598. //
  599. // Cancel any editting that's going on. This matches the behavior of
  600. // DefView.
  601. //
  602. if ( NULL != _pEdit )
  603. {
  604. _pEdit->Release( );
  605. _pEdit = NULL;
  606. }
  607. LRESULT lr = DefSubclassProc( _hwndList, WM_VSCROLL, MAKEWPARAM( wCodeIn, wPosIn ), (LPARAM) hwndFromIn );
  608. RETURN( lr );
  609. }
  610. //
  611. // WM_HCSCROLL handler
  612. //
  613. LRESULT
  614. CAdvancedDlg::List_OnHornScroll(
  615. WORD wCodeIn
  616. , WORD wPosIn
  617. , HWND hwndFromIn
  618. )
  619. {
  620. TraceFunc( "" );
  621. //
  622. // Cancel any editting that's going on. This matches the behavior of
  623. // DefView.
  624. //
  625. if ( NULL != _pEdit )
  626. {
  627. _pEdit->Release( );
  628. _pEdit = NULL;
  629. }
  630. LRESULT lr = DefSubclassProc( _hwndList, WM_HSCROLL, MAKEWPARAM( wCodeIn, wPosIn ), (LPARAM) hwndFromIn );
  631. RETURN( lr );
  632. }
  633. //
  634. // WM_DESTROY handler
  635. //
  636. LRESULT
  637. CAdvancedDlg::OnDestroy( void )
  638. {
  639. TraceFunc( "" );
  640. LRESULT lr = FALSE;
  641. RETURN( lr );
  642. }
  643. //
  644. // Description:
  645. // Creates and initializes the control to edit the property selected.
  646. //
  647. // Return Values:
  648. // S_OK
  649. // Successfully created and initialized control.
  650. //
  651. // S_FALSE
  652. // Read-only property - no control created.
  653. //
  654. // E_FAIL
  655. // Failed to create control.
  656. //
  657. // other HRESULTs
  658. //
  659. HRESULT
  660. CAdvancedDlg::CreateControlForProperty(
  661. INT iItemIn
  662. )
  663. {
  664. TraceFunc( "" );
  665. HRESULT hr;
  666. BOOL bRet;
  667. CLSID clsidControl;
  668. RECT rectItem;
  669. RECT rectList;
  670. UINT uCodePage;
  671. LVITEM lvi;
  672. DEFVAL * pDefVals;
  673. int iImage;
  674. PROPVARIANT * ppropvar;
  675. IPropertyUI * ppui = NULL;
  676. lvi.iItem = iItemIn;
  677. lvi.mask = LVIF_PARAM;
  678. lvi.iSubItem = 0;
  679. bRet = TBOOL( ListView_GetItem( _hwndList, &lvi ) );
  680. if ( !bRet )
  681. goto ControlFailed;
  682. _pItem = (CPropertyCacheItem *) lvi.lParam;
  683. AssertMsg( NULL != _pItem, "Programming error - how did this item get added?" );
  684. hr = THR( _pItem->GetImageIndex( &iImage ) );
  685. if ( S_OK != hr )
  686. goto Cleanup;
  687. //
  688. // Don't invoke the "Edit control" if the property is read-only.
  689. //
  690. if ( PTI_PROP_READONLY == iImage )
  691. {
  692. hr = S_FALSE;
  693. goto Cleanup;
  694. }
  695. hr = STHR( _pItem->GetControlCLSID( &clsidControl ) );
  696. if ( S_OK != hr )
  697. goto Cleanup;
  698. hr = THR( _pItem->GetCodePage( &uCodePage ) );
  699. if ( FAILED( hr ) )
  700. goto Cleanup;
  701. hr = STHR( _pItem->GetPropertyUIHelper( &ppui ) );
  702. if ( S_OK != hr )
  703. goto Cleanup;
  704. hr = THR( _pItem->GetPropertyValue( &ppropvar ) );
  705. if ( FAILED( hr ) )
  706. goto Cleanup;
  707. hr = STHR( _pItem->GetStateStrings( &pDefVals ) );
  708. if ( FAILED( hr ) )
  709. goto Cleanup;
  710. Assert( NULL == _pEdit );
  711. hr = THR( CoCreateInstance( clsidControl, NULL, CLSCTX_INPROC, TYPESAFEPARAMS(_pEdit) ) );
  712. if ( FAILED( hr ) )
  713. goto Cleanup;
  714. bRet = TBOOL( ListView_GetSubItemRect( _hwndList, lvi.iItem, 1, LVIR_BOUNDS , &rectItem) );
  715. if ( !bRet )
  716. goto ControlFailed;
  717. //
  718. // Make sure the rect is only in the visible region of the list view.
  719. //
  720. bRet = TBOOL( GetWindowRect( _hwndList, &rectList ) );
  721. if ( !bRet )
  722. goto ControlFailed;
  723. if ( rectItem.right > rectList.right - rectList.left )
  724. {
  725. rectItem.right = rectList.right - rectList.left;
  726. }
  727. if ( rectItem.left < 0 )
  728. {
  729. rectItem.left = 0;
  730. }
  731. hr = THR( _pEdit->Initialize( _hwndList, uCodePage, &rectItem, ppui, ppropvar, pDefVals ) );
  732. if ( FAILED( hr ) )
  733. {
  734. _pEdit->Release( );
  735. _pEdit = NULL;
  736. goto Cleanup;
  737. }
  738. Cleanup:
  739. if ( NULL != ppui )
  740. {
  741. ppui->Release( );
  742. }
  743. HRETURN( hr );
  744. ControlFailed:
  745. if ( NULL != _pEdit )
  746. {
  747. _pEdit->Release( );
  748. _pEdit = NULL;
  749. }
  750. hr = THR( E_FAIL );
  751. goto Cleanup;
  752. }
  753. //
  754. // Description:
  755. // Informs the control, _pEdit, to persist its value into the variant.
  756. //
  757. // Return Value:
  758. // S_OK
  759. // Success! Property value updated.
  760. //
  761. // S_FALSE
  762. // _pEdit was NULL.
  763. //
  764. // other HRESULTs.
  765. //
  766. HRESULT
  767. CAdvancedDlg::PersistControlInProperty( void )
  768. {
  769. TraceFunc( "" );
  770. HRESULT hr;
  771. LVITEM lvi;
  772. LVFINDINFO lvfi;
  773. VARTYPE vt;
  774. PROPVARIANT * ppropvar;
  775. if ( NULL == _pEdit )
  776. goto NoEditControlEditting;
  777. lvfi.flags = LVFI_PARAM;
  778. lvfi.lParam = (LPARAM) _pItem;
  779. lvfi.vkDirection = VK_DOWN;
  780. lvi.iItem = ListView_FindItem( _hwndList, -1, &lvfi );
  781. if ( -1 == lvi.iItem )
  782. goto NoEditControlEditting;
  783. hr = THR( _pItem->GetPropertyValue( &ppropvar ) );
  784. if ( FAILED( hr ) )
  785. goto Cleanup;
  786. switch( ppropvar->vt )
  787. {
  788. case VT_EMPTY:
  789. case VT_NULL:
  790. {
  791. hr = THR( _pItem->GetDefaultVarType( &vt ) );
  792. if ( FAILED( hr ) )
  793. goto Cleanup;
  794. }
  795. break;
  796. default:
  797. vt = ppropvar->vt;
  798. break;
  799. }
  800. PropVariantInit( ppropvar );
  801. hr = STHR( _pEdit->Persist( vt, ppropvar ) );
  802. if ( FAILED( hr ) )
  803. goto Cleanup;
  804. if ( S_OK == hr )
  805. {
  806. hr = THR( _pItem->MarkDirty( ) );
  807. if ( FAILED( hr ) )
  808. goto Cleanup;
  809. hr = THR( _pItem->GetPropertyStringValue( (LPCWSTR *) &lvi.pszText ) );
  810. if ( FAILED( hr ) )
  811. goto Cleanup;
  812. lvi.mask = LVIF_TEXT;
  813. lvi.iSubItem = 1;
  814. BOOL bRet = TBOOL( ListView_SetItem( _hwndList, &lvi ) );
  815. if ( !bRet )
  816. goto NoEditControlEditting;
  817. //
  818. // Tell the property sheet to activate the "Apply" button.
  819. //
  820. PropSheet_Changed( GetParent( _hwndParent ), _hwndParent );
  821. }
  822. Cleanup:
  823. HRETURN( hr );
  824. NoEditControlEditting:
  825. hr = THR( S_FALSE );
  826. goto Cleanup;
  827. }
  828. //
  829. // WM_HELP handler
  830. //
  831. LRESULT
  832. CAdvancedDlg::OnHelp(
  833. LPHELPINFO pHelpInfoIn
  834. )
  835. {
  836. TraceFunc( "" );
  837. LRESULT lr = FALSE;
  838. THR( DoHelp( (HWND) pHelpInfoIn->hItemHandle, pHelpInfoIn->MousePos.x, pHelpInfoIn->MousePos.y, HELP_WM_HELP ) );
  839. RETURN( lr );
  840. }
  841. //
  842. // WM_CONTEXTMENU handler
  843. //
  844. LRESULT
  845. CAdvancedDlg::OnContextMenu(
  846. HWND hwndIn
  847. , int iXIn
  848. , int iYIn
  849. )
  850. {
  851. TraceFunc( "" );
  852. LRESULT lr = FALSE;
  853. THR( DoHelp( hwndIn, iXIn, iYIn, HELP_CONTEXTMENU ) );
  854. RETURN( lr );
  855. }
  856. //
  857. // Description:
  858. // Handles locating the item within the list view and construct
  859. // a fake IDC to IDH to display the correct help text for the
  860. // item.
  861. //
  862. // Return Values:
  863. // S_OK
  864. // Success.
  865. //
  866. HRESULT
  867. CAdvancedDlg::DoHelp(
  868. HWND hwndIn
  869. , int iXIn
  870. , int iYIn
  871. , UINT uCommandIn
  872. )
  873. {
  874. TraceFunc( "" );
  875. HRESULT hr = S_OK;
  876. HWND hwndList = GetDlgItem( _hdlg, IDC_PROPERTIES );
  877. if ( hwndList == hwndIn )
  878. {
  879. BOOL bRet;
  880. HRESULT hr;
  881. int iItem;
  882. RECT rcList;
  883. LVITEM lvi;
  884. LPCWSTR pszHelpFile; // don't free
  885. UINT uHelpId;
  886. CPropertyCacheItem * pItem;
  887. LVHITTESTINFO lvhti;
  888. DWORD mapIDStoIDH[ ] = { IDC_PROPERTIES, 0, 0, 0 };
  889. bRet = TBOOL( GetWindowRect( hwndList, &rcList ) );
  890. if ( !bRet )
  891. goto Cleanup;
  892. lvhti.pt.x = iXIn - rcList.left;
  893. lvhti.pt.y = iYIn - rcList.top;
  894. lvhti.flags = LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON;
  895. iItem = ListView_HitTest( hwndList, &lvhti );
  896. if ( -1 == iItem )
  897. goto Cleanup; // item not found.
  898. lvi.iItem = iItem;
  899. lvi.mask = LVIF_PARAM;
  900. lvi.iSubItem = 0;
  901. bRet = TBOOL( ListView_GetItem( _hwndList, &lvi ) );
  902. if ( !bRet )
  903. goto Cleanup;
  904. pItem = (CPropertyCacheItem *) lvi.lParam;
  905. AssertMsg( NULL != pItem, "Programming error - how did this item get added?" );
  906. hr = THR( pItem->GetPropertyHelpInfo( &pszHelpFile, &uHelpId ) );
  907. if ( FAILED( hr ) )
  908. goto Cleanup;
  909. mapIDStoIDH[ 1 ] = uHelpId;
  910. TBOOL( WinHelp( hwndIn, pszHelpFile, uCommandIn, (DWORD_PTR)(LPSTR) mapIDStoIDH ) );
  911. }
  912. Cleanup:
  913. HRETURN( hr );
  914. }
  915. // ***************************************************************************
  916. //
  917. // Public methods
  918. //
  919. // ***************************************************************************
  920. //
  921. // Description:
  922. // Hides the dialog.
  923. //
  924. // Return Value:
  925. // S_OK
  926. // Success!
  927. //
  928. HRESULT
  929. CAdvancedDlg::Hide( void )
  930. {
  931. TraceFunc( "" );
  932. HRESULT hr;
  933. ShowWindow( _hdlg, SW_HIDE );
  934. hr = S_OK;
  935. HRETURN( hr );
  936. }
  937. //
  938. // Description:
  939. // Shows the dialog.
  940. //
  941. // Return Values:
  942. // S_OK
  943. // Success!
  944. //
  945. HRESULT
  946. CAdvancedDlg::Show( void )
  947. {
  948. TraceFunc( "" );
  949. HRESULT hr = S_OK;
  950. ShowWindow( _hdlg, SW_SHOW );
  951. SetFocus( _hdlg );
  952. HRETURN( hr );
  953. }
  954. //
  955. // Description:
  956. // Populates the properties of the dialog.
  957. //
  958. // Return Values:
  959. // S_OK
  960. // Success!
  961. //
  962. // E_INVALIDARG
  963. // ppcIn is NULL.
  964. //
  965. // other HRESULTs.
  966. //
  967. HRESULT
  968. CAdvancedDlg::PopulateProperties(
  969. CPropertyCache * ppcIn
  970. , DWORD dwDocTypeIn
  971. , BOOL fMultipleIn
  972. )
  973. {
  974. TraceFunc( "" );
  975. HRESULT hr;
  976. RECT rect;
  977. LVCOLUMN lvc;
  978. BOOL bRet;
  979. LVITEM lvi;
  980. ULONG idxFolder;
  981. ULONG idxProperty;
  982. CPropertyCacheItem * pItem;
  983. int iItem = 0;
  984. //
  985. // Check parameters
  986. //
  987. if ( NULL == ppcIn )
  988. {
  989. ReplaceListViewWithString( IDS_NOPROPERTIES_CAPTION );
  990. hr = S_OK;
  991. goto Cleanup;
  992. }
  993. _fMultipleSources = fMultipleIn;
  994. //
  995. // Clear out the previous list view contents.
  996. //
  997. TBOOL( ListView_DeleteAllItems( _hwndList ) );
  998. //
  999. // See if we have any properties to show.
  1000. //
  1001. hr = STHR( ppcIn->GetNextItem( NULL, &pItem ) );
  1002. if ( S_OK == hr )
  1003. {
  1004. //
  1005. // Walk the default property list and add items that match this property
  1006. // folder to listview.
  1007. //
  1008. // If the SHIFT key is down, all properties retrieved and added will be
  1009. // shown (if possible).
  1010. //
  1011. for ( idxProperty = 0; NULL != g_rgDefPropertyItems[ idxProperty ].pszName; idxProperty ++ )
  1012. {
  1013. if ( !( g_rgDefPropertyItems[ idxProperty ].dwSrcType & dwDocTypeIn )
  1014. && !( GetKeyState( VK_SHIFT ) < 0 )
  1015. )
  1016. {
  1017. continue; // property doesn't apply
  1018. }
  1019. //
  1020. // Search the property cache for the entry.
  1021. //
  1022. hr = STHR( ppcIn->FindItemEntry( g_rgDefPropertyItems[ idxProperty ].pFmtID
  1023. , g_rgDefPropertyItems[ idxProperty ].propID
  1024. , &pItem
  1025. ) );
  1026. if ( S_OK != hr )
  1027. continue; // property not found... skip it
  1028. Assert ( NULL != pItem ); // paranoid
  1029. //
  1030. // Find the group that the property belongs too.
  1031. //
  1032. for ( idxFolder = 0; NULL != g_rgTopLevelFolders[ idxFolder ].pPFID; idxFolder ++ )
  1033. {
  1034. if ( *g_rgDefPropertyItems[ idxProperty ].ppfid == *g_rgTopLevelFolders[ idxFolder ].pPFID )
  1035. {
  1036. break;
  1037. }
  1038. }
  1039. AssertMsg( NULL != g_rgTopLevelFolders[ idxFolder ].pPFID, "Missing folder for listed property. Check DOCPROP.CPP." );
  1040. //
  1041. // Add the property name below the group
  1042. //
  1043. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_GROUPID;
  1044. lvi.iSubItem = 0;
  1045. lvi.iItem = iItem;
  1046. lvi.iGroupId = idxFolder;
  1047. lvi.lParam = (LPARAM) pItem;
  1048. hr = THR( pItem->GetImageIndex( &lvi.iImage ) );
  1049. if ( FAILED( hr ) )
  1050. {
  1051. lvi.iImage = 0;
  1052. }
  1053. else
  1054. {
  1055. if ( _fMultipleSources )
  1056. {
  1057. lvi.iImage += MULTIDOC_IMAGE_OFFSET_VALUE;
  1058. }
  1059. }
  1060. hr = THR( pItem->GetPropertyTitle( (LPCWSTR *) &lvi.pszText ) );
  1061. if ( FAILED( hr ) )
  1062. continue;
  1063. iItem = ListView_InsertItem( _hwndList, &lvi );
  1064. if ( -1 == iItem )
  1065. continue;
  1066. //
  1067. // Now add the property value.
  1068. //
  1069. lvi.mask = LVIF_TEXT;
  1070. lvi.iItem = iItem;
  1071. lvi.iSubItem = 1;
  1072. hr = THR( pItem->GetPropertyStringValue( (LPCWSTR *) &lvi.pszText ) );
  1073. if ( FAILED( hr ) )
  1074. continue;
  1075. bRet = TBOOL( ListView_SetItem( _hwndList, &lvi ) );
  1076. if ( !bRet )
  1077. continue;
  1078. iItem ++;
  1079. }
  1080. //
  1081. // Give the first item focus
  1082. //
  1083. ListView_SetItemState( _hwndList, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED );
  1084. }
  1085. if ( 0 == iItem )
  1086. {
  1087. if ( _fMultipleSources )
  1088. {
  1089. ReplaceListViewWithString( IDS_NOCOMMONS_CAPTION );
  1090. }
  1091. else
  1092. {
  1093. ReplaceListViewWithString( IDS_NOPROPERTIES_CAPTION );
  1094. }
  1095. }
  1096. //
  1097. // Auto-adjust the column widths making sure that the first column doesn't
  1098. // make itself too big.
  1099. //
  1100. TBOOL( ListView_SetColumnWidth( _hwndList, 0, LVSCW_AUTOSIZE_USEHEADER ) );
  1101. bRet = TBOOL( GetClientRect( _hwndList, &rect ) );
  1102. if ( bRet )
  1103. {
  1104. lvc.mask = LVCF_WIDTH;
  1105. bRet = TBOOL( ListView_GetColumn( _hwndList, 0, &lvc ) );
  1106. if ( bRet )
  1107. {
  1108. int iSize = rect.right / 2;
  1109. if ( lvc.cx > iSize )
  1110. {
  1111. TBOOL( ListView_SetColumnWidth( _hwndList, 0, iSize ) );
  1112. TBOOL( ListView_SetColumnWidth( _hwndList, 1, iSize ) );
  1113. }
  1114. else
  1115. {
  1116. TBOOL( ListView_SetColumnWidth( _hwndList, 1, rect.right - lvc.cx ) );
  1117. }
  1118. }
  1119. }
  1120. if ( !bRet )
  1121. {
  1122. TBOOL( ListView_SetColumnWidth( _hwndList, 1, LVSCW_AUTOSIZE_USEHEADER ) );
  1123. }
  1124. hr = S_OK;
  1125. Cleanup:
  1126. HRETURN( hr );
  1127. }
  1128. //
  1129. // Description:
  1130. // Hides the list view control and displays a STATIC window with
  1131. // the text found in the string resource idsIn.
  1132. //
  1133. void
  1134. CAdvancedDlg::ReplaceListViewWithString( int idsIn )
  1135. {
  1136. TraceFunc( "" );
  1137. int iRet;
  1138. RECT rc;
  1139. WCHAR szCaption[ 255 ]; // random
  1140. iRet = LoadString( g_hInstance, idsIn, szCaption, ARRAYSIZE(szCaption) );
  1141. AssertMsg( iRet, "Missing string resource?" );
  1142. ShowWindow( _hwndList, SW_HIDE );
  1143. TBOOL( GetWindowRect( _hwndList, &rc ) );
  1144. iRet = MapWindowRect( HWND_DESKTOP, _hdlg, &rc );
  1145. TBOOL( 0 != iRet );
  1146. HWND hwnd = CreateWindow( WC_STATIC
  1147. , szCaption
  1148. , WS_CHILD | WS_VISIBLE
  1149. , rc.left
  1150. , rc.top
  1151. , rc.right - rc.left
  1152. , rc.bottom - rc.top
  1153. , _hdlg
  1154. , (HMENU) -1
  1155. , g_hInstance
  1156. , NULL
  1157. );
  1158. TBOOL( NULL != hwnd );
  1159. HFONT hFont = (HFONT) SendMessage( _hdlg, WM_GETFONT, 0, 0 );
  1160. SendMessage( hwnd, WM_SETFONT, (WPARAM) hFont, 0 );
  1161. TraceFuncExit( );
  1162. }