Source code of Windows XP (NT5)
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.

1248 lines
36 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: view.cxx
  7. //
  8. // Contents:
  9. //
  10. // History: 15 Aug 1996 DLee Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "pch.cxx"
  14. #pragma hdrstop
  15. const int cpMargin = 2;
  16. const int cpInflate = 4;
  17. const int cpPaneMargin = 3;
  18. const int cpPaneSpacing = 5;
  19. const int cpPaneBottomSpacing = 0;
  20. const DBID colAttrib = { PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR) (ULONG_PTR) PID_STG_ATTRIBUTES };
  21. const DBID colFileIndex = { PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR) (ULONG_PTR) PID_STG_FILEINDEX };
  22. CSearchView::CSearchView(
  23. HWND hwndSearch,
  24. CSearchControl & control,
  25. CColumnList & columns )
  26. :
  27. _hwndSearch( hwndSearch ),
  28. _hwndQuery( 0 ),
  29. _hwndQueryTitle( 0 ),
  30. _hwndList( 0 ),
  31. _hwndHeader( 0 ),
  32. _hbrushWindow( 0 ),
  33. _hbrushHighlight( 0 ),
  34. _fHavePlacedTitles( FALSE ),
  35. _hfontShell( 0 ),
  36. _cLines( 0 ),
  37. _control( control ),
  38. _columns( columns ),
  39. _fMucked( FALSE ),
  40. _iColAttrib( 0xffffffff ),
  41. _iColFileIndex( 0xffffffff )
  42. {
  43. MakeFont();
  44. _cpFontHeight = ::GetLineHeight( hwndSearch, _hfontShell );
  45. _iLineHeightList = ::GetLineHeight( hwndSearch, App.AppFont() );
  46. SysColorChange ();
  47. } //CSearchView
  48. CSearchView::~CSearchView()
  49. {
  50. if (0 != _hfontShell)
  51. DeleteObject(_hfontShell);
  52. if (0 != _hbrushWindow)
  53. {
  54. DeleteObject(_hbrushWindow);
  55. DeleteObject(_hbrushHighlight);
  56. }
  57. } //~CSearchView
  58. unsigned CSearchView::ColumnWidth(
  59. unsigned x )
  60. {
  61. if ( 0 == x )
  62. return _aWidths[ 0 ] + cpInflate + _cpAvgWidth/2 + cpMargin;
  63. else
  64. return _aWidths[ x ] + _cpAvgWidth;
  65. } //ColumnWidth
  66. void CSearchView::SetColumnWidth(
  67. unsigned x,
  68. unsigned cpWidth )
  69. {
  70. unsigned w;
  71. if ( 0 == x )
  72. w = cpWidth - cpInflate - _cpAvgWidth/2 - cpMargin;
  73. else
  74. w = cpWidth - _cpAvgWidth;
  75. if ( _aWidths[ x ] > w )
  76. _fMucked = TRUE;
  77. _aWidths[ x ] = w;
  78. } //SetColumnWidth
  79. unsigned CSearchView::SetDefColumnWidth(
  80. unsigned iCol )
  81. {
  82. DBID *pdbid;
  83. unsigned cc;
  84. DBTYPE pt;
  85. IColumnMapper & colMap = _control.GetColumnMapper();
  86. SCODE sc = colMap.GetPropInfoFromName( _columns.GetColumn( iCol ),
  87. &pdbid,
  88. &pt,
  89. &cc );
  90. if ( FAILED( sc ) )
  91. THROW( CException( sc ) );
  92. _aPropTypes[ iCol ] = pt;
  93. if ( ( VT_FILETIME == pt ) || ( DBTYPE_DATE == pt ) )
  94. _aWidths[ iCol ] = _cpDateWidth + _cpTimeWidth;
  95. else if ( VT_CLSID == pt )
  96. _aWidths[ iCol ] = _cpGuidWidth;
  97. else if ( VT_BOOL == pt )
  98. _aWidths[ iCol ] = _cpBoolWidth;
  99. else if ( !memcmp( pdbid, &colAttrib, sizeof DBID ) )
  100. {
  101. _aWidths[ iCol ] = _cpAttribWidth;
  102. _iColAttrib = iCol;
  103. }
  104. else if ( !memcmp( pdbid, &colFileIndex, sizeof DBID ) )
  105. {
  106. _aWidths[ iCol ] = _cpFileIndexWidth;
  107. _iColFileIndex = iCol;
  108. }
  109. else
  110. _aWidths[ iCol ] = cc * _cpAvgWidth;
  111. // did the attrib column get redefined?
  112. if ( _iColAttrib == iCol && memcmp( pdbid, &colAttrib, sizeof DBID ) )
  113. _iColAttrib = 0xffffffff;
  114. // did the fileindex column get redefined?
  115. if ( _iColFileIndex == iCol && memcmp( pdbid, &colFileIndex, sizeof DBID ) )
  116. _iColFileIndex = 0xffffffff;
  117. return ColumnWidth( iCol );
  118. } //SetDefColumnWidth
  119. void CSearchView::ColumnsChanged()
  120. {
  121. _ComputeFieldWidths();
  122. for ( unsigned iCol = 0; iCol < _columns.NumberOfColumns(); iCol++ )
  123. SetDefColumnWidth( iCol );
  124. } //ColumnsChanged
  125. void CSearchView::MakeFont()
  126. {
  127. LOGFONT lf;
  128. memset( &lf, 0, sizeof LOGFONT );
  129. lf.lfHeight = -11;
  130. lf.lfWeight = FW_NORMAL;
  131. lf.lfCharSet = ANSI_CHARSET;
  132. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  133. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  134. lf.lfQuality = PROOF_QUALITY;
  135. lf.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
  136. wcscpy( lf.lfFaceName, L"MS SHELL DLG" );
  137. _hfontShell = CreateFontIndirect( &lf );
  138. } //MakeFont
  139. void CSearchView::SysColorChange()
  140. {
  141. if (0 != _hbrushWindow)
  142. {
  143. DeleteObject(_hbrushWindow);
  144. DeleteObject(_hbrushHighlight);
  145. }
  146. _colorHighlight = GetSysColor(COLOR_HIGHLIGHT);
  147. _colorHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  148. _colorWindow = GetSysColor(COLOR_WINDOW);
  149. _colorWindowText = GetSysColor(COLOR_WINDOWTEXT);
  150. _hbrushHighlight = CreateSolidBrush( _colorHighlight );
  151. _hbrushWindow = CreateSolidBrush( _colorWindow );
  152. } //SysColorChange
  153. void CSearchView::InitPanes (
  154. HWND hwndQueryTitle,
  155. HWND hwndQuery,
  156. HWND hwndList,
  157. HWND hwndHeader )
  158. {
  159. _hwndQueryTitle = hwndQueryTitle;
  160. _hwndQuery = hwndQuery;
  161. _hwndList = hwndList;
  162. _hwndHeader = hwndHeader;
  163. SendMessage( _hwndQueryTitle, WM_SETFONT, (WPARAM) _hfontShell, 1 );
  164. SendMessage( _hwndHeader, WM_SETFONT, (WPARAM) _hfontShell, 1 );
  165. SendMessage( _hwndQuery, WM_SETFONT, (WPARAM) App.AppFont(), 1 );
  166. SendMessage( _hwndList, WM_SETFONT, (WPARAM) App.AppFont(), 1 );
  167. } //InitPanes
  168. void CSearchView::PrimeItem(
  169. LPDRAWITEMSTRUCT & lpdis,
  170. RECT & rc )
  171. {
  172. CopyRect( &rc, &lpdis->rcItem );
  173. InflateRect( (LPRECT) &rc, 1, 0 );
  174. HBRUSH hbr;
  175. if ( lpdis->itemState & ODS_SELECTED )
  176. {
  177. SetBkColor( lpdis->hDC, _colorHighlight );
  178. SetTextColor( lpdis->hDC, _colorHighlightText );
  179. hbr = _hbrushHighlight;
  180. }
  181. else
  182. {
  183. SetBkColor( lpdis->hDC, _colorWindow );
  184. SetTextColor( lpdis->hDC, _colorWindowText );
  185. hbr = _hbrushWindow;
  186. }
  187. FillRect( lpdis->hDC, &rc, hbr );
  188. InflateRect( &rc, -cpInflate, 0 );
  189. } //PrimeItem
  190. inline void _drawText(
  191. HDC hdc,
  192. RECT & rc,
  193. unsigned cpWidth,
  194. WCHAR * pwc,
  195. int cwc,
  196. BOOL fClip )
  197. {
  198. RECT rctext = rc;
  199. rctext.right = rc.left + cpWidth;
  200. DrawText( hdc,
  201. pwc,
  202. cwc,
  203. &rctext,
  204. DT_VCENTER | DT_NOPREFIX | DT_RIGHT | DT_SINGLELINE |
  205. ( fClip ? 0 : DT_NOCLIP ) );
  206. } //_drawText
  207. template<class T> void _drawVectorItems(
  208. T * pVal,
  209. ULONG cVals,
  210. WCHAR * pwcFmt,
  211. HDC hdc,
  212. RECT & rc,
  213. unsigned width )
  214. {
  215. WCHAR awcBuf[ cwcBufSize ];
  216. unsigned ccUnused = cwcBufSize - 10;
  217. WCHAR *pwcEnd = awcBuf;
  218. *pwcEnd++ = L'{';
  219. for( unsigned iVal = 0;
  220. iVal < cVals && ccUnused > 0;
  221. iVal++ )
  222. {
  223. int ccPrinted = _snwprintf( pwcEnd,
  224. ccUnused,
  225. pwcFmt,
  226. iVal == 0 ? L' ': L',',
  227. *pVal++ );
  228. if ( ccPrinted == -1 )
  229. break;
  230. ccUnused -= ccPrinted;
  231. pwcEnd += ccPrinted;
  232. }
  233. if ( iVal != cVals )
  234. {
  235. *pwcEnd++ = L'.';
  236. *pwcEnd++ = L'.';
  237. *pwcEnd++ = L'.';
  238. }
  239. *pwcEnd++ = L' ';
  240. *pwcEnd++ = L'}';
  241. *pwcEnd = L'\0';
  242. _drawText( hdc, rc, width, awcBuf, -1, TRUE );
  243. } //_drawVectorItems
  244. void Append( CDynArrayInPlace<WCHAR> & xBuf, WCHAR const * pwc, unsigned cwc )
  245. {
  246. for ( unsigned i = 0; i < cwc; i++ )
  247. xBuf[ xBuf.Count() ] = pwc[ i ];
  248. } //Append
  249. void Append( CDynArrayInPlace<WCHAR> & xBuf, WCHAR const * pwc )
  250. {
  251. while ( 0 != *pwc )
  252. xBuf[ xBuf.Count() ] = *pwc++;
  253. } //Append
  254. void RenderSafeArray(
  255. WCHAR * pwc,
  256. unsigned cwcMax,
  257. VARTYPE vt,
  258. LPSAFEARRAY pa );
  259. void Render(
  260. CDynArrayInPlace<WCHAR> & xOut,
  261. VARTYPE vt,
  262. void * pv )
  263. {
  264. srchDebugOut(( DEB_ITRACE, "vt %#x, pv %#x\n", vt, pv ));
  265. __int64 i = 0;
  266. XArray<WCHAR> xBuf( cwcBufSize );
  267. WCHAR *awcBuf = xBuf.GetPointer();
  268. XArray<WCHAR> xTmp( cwcBufSize );
  269. WCHAR *awcTmp = xTmp.GetPointer();
  270. static WCHAR wszfmtU[] = L"%I64u";
  271. WCHAR *pwszfmt = L"%I64d";
  272. LCID lcid = App.GetLocale();
  273. if ( VT_ARRAY & vt )
  274. {
  275. SAFEARRAY *psa = *(SAFEARRAY **) pv;
  276. *awcBuf = 0;
  277. RenderSafeArray( awcBuf, cwcBufSize, vt - VT_ARRAY, psa );
  278. Append( xOut, awcBuf );
  279. return;
  280. }
  281. switch ( vt )
  282. {
  283. case VT_UI1:
  284. i = (unsigned __int64) *(BYTE *)pv;
  285. goto do_ui64;
  286. case VT_I1:
  287. i = *(CHAR *)pv;
  288. goto do_i64;
  289. case VT_UI2:
  290. i = (unsigned __int64) *(USHORT *)pv;
  291. goto do_ui64;
  292. case VT_I2:
  293. i = (unsigned __int64) *(SHORT *)pv;
  294. goto do_i64;
  295. case VT_UI4:
  296. case VT_UINT:
  297. i = (unsigned __int64) *(ULONG *)pv;
  298. goto do_ui64;
  299. case VT_I4:
  300. case VT_ERROR:
  301. case VT_INT:
  302. i = (unsigned __int64) *(LONG *)pv;
  303. goto do_i64;
  304. case VT_UI8:
  305. RtlCopyMemory( &i, pv, sizeof i );
  306. do_ui64:
  307. pwszfmt = wszfmtU;
  308. goto do_i64;
  309. case VT_I8:
  310. RtlCopyMemory( &i, pv, sizeof i );
  311. do_i64:
  312. {
  313. swprintf( awcTmp, pwszfmt, i );
  314. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  315. & App.NumberFormat(), awcBuf,
  316. cwcBufSize );
  317. Append( xOut, awcBuf, cwc - 1);
  318. break;
  319. }
  320. case VT_R4:
  321. {
  322. float f;
  323. RtlCopyMemory( &f, pv, sizeof f );
  324. swprintf( awcTmp, L"%f", f );
  325. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  326. & App.NumberFormatFloat(),
  327. awcBuf,
  328. cwcBufSize );
  329. Append( xOut, awcBuf, cwc - 1 );
  330. break;
  331. }
  332. case VT_R8:
  333. {
  334. double d;
  335. RtlCopyMemory( &d, pv, sizeof d );
  336. swprintf( awcTmp, L"%lf", d );
  337. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  338. & App.NumberFormatFloat(),
  339. awcBuf,
  340. cwcBufSize );
  341. Append( xOut, awcBuf, cwc - 1 );
  342. break;
  343. }
  344. case VT_DECIMAL:
  345. {
  346. double dbl;
  347. VarR8FromDec( (DECIMAL *) pv, &dbl );
  348. swprintf( awcTmp, L"%lf", dbl );
  349. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  350. & App.NumberFormatFloat(),
  351. awcBuf,
  352. cwcBufSize );
  353. Append( xOut, awcBuf, cwc - 1 );
  354. break;
  355. }
  356. case VT_CY:
  357. {
  358. double dbl;
  359. VarR8FromCy( * (CY *) pv, &dbl );
  360. swprintf( awcTmp, L"%lf", dbl );
  361. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  362. & App.NumberFormatFloat(),
  363. awcBuf,
  364. cwcBufSize );
  365. Append( xOut, awcBuf, cwc - 1 );
  366. break;
  367. }
  368. case VT_BOOL:
  369. {
  370. Append( xOut,
  371. *(VARIANT_BOOL *)pv ? App.GetTrue() : App.GetFalse() );
  372. break;
  373. }
  374. case VT_BSTR:
  375. {
  376. BSTR bstr = *(BSTR *) pv;
  377. Append( xOut, bstr );
  378. break;
  379. }
  380. case VT_VARIANT:
  381. {
  382. PROPVARIANT * pVar = (PROPVARIANT *) pv;
  383. Render( xOut, pVar->vt, & pVar->lVal );
  384. break;
  385. }
  386. case VT_DATE:
  387. {
  388. DATE date;
  389. RtlCopyMemory( &date, pv, sizeof date );
  390. awcBuf[0] = 0;
  391. // no timezone is expressed or implied in variant dates.
  392. SYSTEMTIME SysTime;
  393. RtlZeroMemory( &SysTime, sizeof SysTime );
  394. VariantTimeToSystemTime( date, &SysTime );
  395. // date
  396. int cwc = GetDateFormat( lcid, DATE_SHORTDATE, &SysTime,
  397. 0, awcBuf, cwcBufSize );
  398. if ( 0 != cwc )
  399. Append( xOut, awcBuf, cwc - 1 );
  400. Append( xOut, L" " );
  401. // time
  402. cwc = GetTimeFormat( lcid, 0, &SysTime, 0, awcBuf,
  403. cwcBufSize );
  404. if ( 0 != cwc )
  405. Append( xOut, awcBuf, cwc - 1 );
  406. break;
  407. }
  408. case VT_EMPTY:
  409. case VT_NULL:
  410. {
  411. break;
  412. }
  413. default :
  414. {
  415. swprintf( awcTmp, L"(vt 0x%x)", (int) vt );
  416. Append( xOut, awcTmp );
  417. break;
  418. }
  419. }
  420. } //Render
  421. void RenderSafeArray(
  422. WCHAR * pwc,
  423. unsigned cwcMax,
  424. VARTYPE vt,
  425. LPSAFEARRAY pa )
  426. {
  427. *pwc = 0;
  428. cwcMax -= 10; // leave room for formatting
  429. // Get the dimensions of the array
  430. CDynArrayInPlace<WCHAR> xOut;
  431. UINT cDim = SafeArrayGetDim( pa );
  432. if ( 0 == cDim )
  433. return;
  434. XArray<LONG> xDim( cDim );
  435. XArray<LONG> xLo( cDim );
  436. XArray<LONG> xUp( cDim );
  437. for ( UINT iDim = 0; iDim < cDim; iDim++ )
  438. {
  439. HRESULT hr = SafeArrayGetLBound( pa, iDim + 1, &xLo[iDim] );
  440. if ( FAILED( hr ) )
  441. return;
  442. xDim[ iDim ] = xLo[ iDim ];
  443. hr = SafeArrayGetUBound( pa, iDim + 1, &xUp[iDim] );
  444. if ( FAILED( hr ) )
  445. return;
  446. srchDebugOut(( DEB_ITRACE, "dim %d, lo %d, up %d\n",
  447. iDim, xLo[iDim], xUp[iDim] ));
  448. xOut[ xOut.Count() ] = L'{';
  449. }
  450. // slog through the array
  451. UINT iLastDim = cDim - 1;
  452. BOOL fDone = FALSE;
  453. while ( !fDone && ( xOut.Count() < cwcMax ) )
  454. {
  455. // inter-element formatting
  456. if ( xDim[ iLastDim ] != xLo[ iLastDim ] )
  457. xOut[ xOut.Count() ] = L',';
  458. // Get the element and render it
  459. void *pv;
  460. HRESULT hr = SafeArrayPtrOfIndex( pa, xDim.GetPointer(), &pv );
  461. Win4Assert( SUCCEEDED( hr ) );
  462. Render( xOut, vt, pv );
  463. // Move to the next element and carry if necessary
  464. ULONG cOpen = 0;
  465. for ( LONG iDim = iLastDim; iDim >= 0; iDim-- )
  466. {
  467. if ( xDim[ iDim ] < xUp[ iDim ] )
  468. {
  469. xDim[ iDim ] = 1 + xDim[ iDim ];
  470. break;
  471. }
  472. xOut[ xOut.Count() ] = L'}';
  473. if ( 0 == iDim )
  474. fDone = TRUE;
  475. else
  476. {
  477. cOpen++;
  478. xDim[ iDim ] = xLo[ iDim ];
  479. }
  480. }
  481. for ( ULONG i = 0; !fDone && i < cOpen; i++ )
  482. xOut[ xOut.Count() ] = L'{';
  483. }
  484. unsigned cwc = __min( cwcMax, xOut.Count() );
  485. RtlCopyMemory( pwc, xOut.GetPointer(), cwc * sizeof WCHAR );
  486. // If it wouldn't all fit, show ...
  487. if ( !fDone )
  488. {
  489. pwc[ cwc++ ] = '.';
  490. pwc[ cwc++ ] = '.';
  491. pwc[ cwc++ ] = '.';
  492. }
  493. pwc[ cwc ] = 0;
  494. } //RenderSafeArray
  495. void CSearchView::PaintItem (
  496. CSearchQuery * pSearch,
  497. HDC hdc,
  498. RECT & rc,
  499. DWORD iRow )
  500. {
  501. static WCHAR wszfmtU[] = L"%u"; // unsigned scalar
  502. static WCHAR wszfmtVU[] = L"%lc%u"; // vector of unsigned scalars
  503. PROPVARIANT * aProps[ maxBoundCols ];
  504. unsigned cColumns;
  505. if ( ! pSearch->GetRow( iRow, cColumns, aProps ) )
  506. return;
  507. //
  508. // These must be static for IceCap profiling to work. Declaring them on
  509. // stack causes __alloca_probe (alias: _chkstk) to be called. This
  510. // routine plays funny games with the stack that IceCap V3 doesn't understand.
  511. //
  512. static WCHAR awcBuf[cwcBufSize];
  513. static WCHAR awcTmp[cwcBufSize];
  514. LCID lcid = App.GetLocale();
  515. rc.left += cpMargin; // leave a margin
  516. for ( unsigned i = 0; i < cColumns; i++ )
  517. {
  518. PROPVARIANT & v = * aProps[ i ];
  519. unsigned width = _aWidths[ i ];
  520. WCHAR *pwszfmt = L"%d"; // signed scalar
  521. WCHAR *pwszfmtV = L"%lc%d"; // vector of signed scalars
  522. BOOL fHighPartValid;
  523. switch ( v.vt )
  524. {
  525. case VT_UI1:
  526. v.ulVal = v.bVal;
  527. goto doulong;
  528. case VT_I1:
  529. v.lVal = v.cVal;
  530. goto dolong;
  531. case VT_UI2:
  532. v.ulVal = v.uiVal;
  533. goto doulong;
  534. case VT_I2:
  535. v.lVal = v.iVal;
  536. goto dolong;
  537. case VT_UI4:
  538. case VT_UINT:
  539. doulong:
  540. pwszfmt = wszfmtU;
  541. case VT_I4:
  542. case VT_INT:
  543. case VT_ERROR:
  544. dolong:
  545. {
  546. int cwc;
  547. if ( i == _iColAttrib )
  548. {
  549. cwc = 0;
  550. WCHAR *pwc = App.GetAttrib();
  551. LONG l = v.lVal;
  552. if ( l & FILE_ATTRIBUTE_READONLY )
  553. awcBuf[ cwc++ ] = pwc[ 0 ];
  554. if ( l & FILE_ATTRIBUTE_HIDDEN )
  555. awcBuf[ cwc++ ] = pwc[ 1 ];
  556. if ( l & FILE_ATTRIBUTE_SYSTEM )
  557. awcBuf[ cwc++ ] = pwc[ 2 ];
  558. if ( l & FILE_ATTRIBUTE_DIRECTORY )
  559. awcBuf[ cwc++ ] = pwc[ 3 ];
  560. if ( l & FILE_ATTRIBUTE_ARCHIVE )
  561. awcBuf[ cwc++ ] = pwc[ 4 ];
  562. if ( l & FILE_ATTRIBUTE_ENCRYPTED )
  563. awcBuf[ cwc++ ] = pwc[ 5 ];
  564. if ( l & FILE_ATTRIBUTE_NORMAL )
  565. awcBuf[ cwc++ ] = pwc[ 6 ];
  566. if ( l & FILE_ATTRIBUTE_TEMPORARY )
  567. awcBuf[ cwc++ ] = pwc[ 7 ];
  568. if ( l & FILE_ATTRIBUTE_SPARSE_FILE )
  569. awcBuf[ cwc++ ] = pwc[ 8 ];
  570. if ( l & FILE_ATTRIBUTE_REPARSE_POINT )
  571. awcBuf[ cwc++ ] = pwc[ 9 ];
  572. if ( l & FILE_ATTRIBUTE_COMPRESSED )
  573. awcBuf[ cwc++ ] = pwc[ 10 ];
  574. if ( l & FILE_ATTRIBUTE_OFFLINE )
  575. awcBuf[ cwc++ ] = pwc[ 11 ];
  576. if ( l & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED )
  577. awcBuf[ cwc++ ] = pwc[ 12 ];
  578. awcBuf[ cwc ] = 0;
  579. }
  580. else
  581. {
  582. if ( pwszfmt == wszfmtU )
  583. _ultow( v.lVal, awcTmp, 10 );
  584. else
  585. _ltow( v.lVal, awcTmp, 10 );
  586. cwc = GetNumberFormat( lcid, 0, awcTmp,
  587. & App.NumberFormat(), awcBuf,
  588. cwcBufSize );
  589. cwc--;
  590. }
  591. _drawText( hdc, rc, width, awcBuf, cwc, _fMucked );
  592. break;
  593. }
  594. case VT_I8:
  595. {
  596. _i64tow( * (__int64 *) &v.hVal, awcTmp, 10 );
  597. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  598. & App.NumberFormat(), awcBuf,
  599. cwcBufSize );
  600. cwc--;
  601. _drawText( hdc, rc, width, awcBuf, cwc, _fMucked );
  602. break;
  603. }
  604. case VT_UI8:
  605. {
  606. if ( i == _iColFileIndex )
  607. {
  608. wcscpy( awcBuf, L"0x" );
  609. if ( 0 != v.hVal.HighPart )
  610. {
  611. wsprintf( awcTmp, L"%08x,", v.hVal.HighPart );
  612. wcscat( awcBuf, awcTmp );
  613. }
  614. wsprintf( awcTmp, L"%08x", v.hVal.LowPart );
  615. wcscat( awcBuf, awcTmp );
  616. _drawText( hdc, rc, width, awcBuf, -1, _fMucked );
  617. }
  618. else
  619. {
  620. _ui64tow( *(unsigned __int64 *) &v.hVal, awcTmp, 10 );
  621. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  622. & App.NumberFormat(), awcBuf,
  623. cwcBufSize );
  624. cwc--;
  625. _drawText( hdc, rc, width, awcBuf, cwc, _fMucked );
  626. }
  627. break;
  628. }
  629. case VT_FILETIME :
  630. {
  631. awcBuf[0] = 0;
  632. if ( 0 == v.filetime.dwLowDateTime &&
  633. 0 == v.filetime.dwHighDateTime )
  634. {
  635. _drawText( hdc, rc, width, L"0", -1, TRUE );
  636. }
  637. else
  638. {
  639. // convert the file time to local time, then to system time
  640. FILETIME LocalFTime;
  641. memset( &LocalFTime, 0, sizeof LocalFTime );
  642. FileTimeToLocalFileTime( &(v.filetime), &LocalFTime );
  643. SYSTEMTIME SysTime;
  644. memset( &SysTime, 0, sizeof SysTime );
  645. FileTimeToSystemTime( &LocalFTime, &SysTime );
  646. // date
  647. int cwc = GetDateFormat( lcid, DATE_SHORTDATE, &SysTime,
  648. 0, awcBuf, cwcBufSize );
  649. int dmin = __min( _cpDateWidth, (int) width );
  650. if ( 0 != cwc )
  651. _drawText( hdc, rc, dmin, awcBuf, cwc - 1, _fMucked );
  652. // time
  653. if ( (int) width > _cpDateWidth )
  654. {
  655. cwc = GetTimeFormat( lcid, 0, &SysTime, 0, awcBuf,
  656. cwcBufSize );
  657. int left = rc.left;
  658. rc.left += _cpDateWidth;
  659. int tmin = __min( _cpTimeWidth, (int) width - _cpDateWidth );
  660. if ( 0 != cwc )
  661. _drawText( hdc, rc, tmin, awcBuf, cwc - 1, _fMucked );
  662. rc.left = left;
  663. }
  664. }
  665. break;
  666. }
  667. case VT_LPWSTR :
  668. case DBTYPE_WSTR | DBTYPE_BYREF :
  669. case VT_LPSTR :
  670. case DBTYPE_STR | DBTYPE_BYREF :
  671. case VT_BSTR :
  672. {
  673. if ( 0 != v.pwszVal )
  674. {
  675. // don't clip if it's the last column
  676. UINT f = ( i == ( cColumns - 1 ) ) ? DT_NOCLIP : 0;
  677. RECT rctext;
  678. CopyRect( &rctext, &rc );
  679. rctext.right = rc.left + width;
  680. if ( ( VT_LPSTR == v.vt ) ||
  681. ( ( DBTYPE_STR | DBTYPE_BYREF ) == v.vt ) )
  682. DrawTextA( hdc,
  683. v.pszVal,
  684. -1,
  685. &rctext,
  686. DT_VCENTER | DT_LEFT | DT_NOPREFIX |
  687. DT_SINGLELINE | f );
  688. else
  689. DrawText( hdc,
  690. v.pwszVal,
  691. -1,
  692. &rctext,
  693. DT_VCENTER | DT_LEFT | DT_NOPREFIX |
  694. DT_SINGLELINE | f );
  695. }
  696. break;
  697. }
  698. case VT_R4:
  699. {
  700. swprintf( awcTmp, L"%f", v.fltVal );
  701. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  702. & App.NumberFormatFloat(),
  703. awcBuf,
  704. cwcBufSize );
  705. cwc--;
  706. _drawText( hdc, rc, width, awcBuf, cwc, _fMucked );
  707. break;
  708. }
  709. case VT_DATE:
  710. {
  711. awcBuf[0] = 0;
  712. SYSTEMTIME SysTime;
  713. RtlZeroMemory( &SysTime, sizeof SysTime );
  714. VariantTimeToSystemTime( v.date, &SysTime );
  715. // date
  716. int cwc = GetDateFormat( lcid, DATE_SHORTDATE, &SysTime,
  717. 0, awcBuf, cwcBufSize );
  718. int dmin = __min( _cpDateWidth, (int) width );
  719. if ( 0 != cwc )
  720. _drawText( hdc, rc, dmin, awcBuf, cwc - 1, _fMucked );
  721. // time
  722. if ( (int) width > _cpDateWidth )
  723. {
  724. cwc = GetTimeFormat( lcid, 0, &SysTime, 0, awcBuf,
  725. cwcBufSize );
  726. int left = rc.left;
  727. rc.left += _cpDateWidth;
  728. int tmin = __min( _cpTimeWidth, (int) width - _cpDateWidth );
  729. if ( 0 != cwc )
  730. _drawText( hdc, rc, tmin, awcBuf, cwc - 1, _fMucked );
  731. rc.left = left;
  732. }
  733. break;
  734. }
  735. case VT_R8:
  736. {
  737. swprintf( awcTmp, L"%lf", v.dblVal );
  738. int cwc = GetNumberFormat( lcid, 0, awcTmp,
  739. & App.NumberFormatFloat(),
  740. awcBuf,
  741. cwcBufSize );
  742. cwc--;
  743. _drawText( hdc, rc, width, awcBuf, cwc, _fMucked );
  744. break;
  745. }
  746. case VT_DECIMAL:
  747. {
  748. double dbl;
  749. VarR8FromDec( &v.decVal, &dbl );
  750. swprintf( awcBuf, L"%lf", dbl );
  751. _drawText( hdc, rc, width, awcBuf, -1, TRUE );
  752. break;
  753. }
  754. case VT_CY:
  755. {
  756. double dbl;
  757. VarR8FromCy( v.cyVal, &dbl );
  758. swprintf( awcTmp, L"$%lf", dbl );
  759. _drawText( hdc, rc, width, awcTmp, -1, _fMucked );
  760. break;
  761. }
  762. case VT_BOOL:
  763. {
  764. _drawText( hdc, rc, width,
  765. v.boolVal ? App.GetTrue() : App.GetFalse(), -1, _fMucked );
  766. break;
  767. }
  768. case VT_CLSID:
  769. {
  770. GUID * puuid = v.puuid;
  771. if ( 0 != puuid )
  772. swprintf( awcTmp,
  773. L"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
  774. puuid->Data1,
  775. puuid->Data2,
  776. puuid->Data3,
  777. puuid->Data4[0], puuid->Data4[1],
  778. puuid->Data4[2], puuid->Data4[3],
  779. puuid->Data4[4], puuid->Data4[5],
  780. puuid->Data4[6], puuid->Data4[7] );
  781. else
  782. awcTmp[0] = 0;
  783. _drawText( hdc, rc, width, awcTmp, -1, _fMucked );
  784. break;
  785. }
  786. case VT_BLOB:
  787. {
  788. swprintf( awcTmp,
  789. App.GetBlob(),
  790. v.blob.cbSize,
  791. v.blob.pBlobData );
  792. _drawText( hdc, rc, width, awcTmp, -1, TRUE );
  793. break;
  794. }
  795. case VT_CF:
  796. {
  797. if ( 0 != v.pclipdata )
  798. swprintf( awcTmp, L"vt_cf cb 0x%x, fmt 0x%x",
  799. v.pclipdata->cbSize,
  800. v.pclipdata->ulClipFmt );
  801. else
  802. swprintf( awcTmp, L"vt_cf (null)" );
  803. _drawText( hdc, rc, width, awcTmp, -1, TRUE );
  804. break;
  805. }
  806. case VT_VECTOR | VT_UI1:
  807. pwszfmtV = wszfmtVU;
  808. case VT_VECTOR | VT_I1:
  809. {
  810. _drawVectorItems( v.caub.pElems,
  811. v.caub.cElems,
  812. pwszfmtV,
  813. hdc,
  814. rc,
  815. width );
  816. break;
  817. }
  818. case VT_VECTOR | VT_BOOL:
  819. case VT_VECTOR | VT_UI2:
  820. pwszfmtV = wszfmtVU;
  821. case VT_VECTOR | VT_I2:
  822. {
  823. _drawVectorItems( v.cai.pElems,
  824. v.cai.cElems,
  825. pwszfmtV,
  826. hdc,
  827. rc,
  828. width );
  829. break;
  830. }
  831. case VT_VECTOR | VT_UI4:
  832. pwszfmtV = wszfmtVU;
  833. case VT_VECTOR | VT_I4:
  834. {
  835. _drawVectorItems( v.cal.pElems,
  836. v.cal.cElems,
  837. pwszfmtV,
  838. hdc,
  839. rc,
  840. width );
  841. break;
  842. }
  843. case VT_VECTOR | VT_LPSTR:
  844. case VT_VECTOR | VT_LPWSTR:
  845. case VT_VECTOR | VT_BSTR:
  846. {
  847. _drawVectorItems( v.calpwstr.pElems,
  848. v.calpwstr.cElems,
  849. ( ( VT_VECTOR | VT_LPSTR ) == v.vt ) ?
  850. L"%wc%S" : L"%wc%s",
  851. hdc,
  852. rc,
  853. width );
  854. break;
  855. }
  856. case VT_VECTOR | VT_R4:
  857. {
  858. _drawVectorItems( v.caflt.pElems,
  859. v.caflt.cElems,
  860. L"%wc%f",
  861. hdc,
  862. rc,
  863. width );
  864. break;
  865. }
  866. case VT_VECTOR | VT_R8:
  867. {
  868. _drawVectorItems( v.cadbl.pElems,
  869. v.cadbl.cElems,
  870. L"%wc%lf",
  871. hdc,
  872. rc,
  873. width );
  874. break;
  875. }
  876. case VT_VECTOR | VT_I8:
  877. case VT_VECTOR | VT_UI8:
  878. {
  879. _drawVectorItems( v.cah.pElems,
  880. v.cah.cElems,
  881. ( v.vt == ( VT_VECTOR | VT_I8 ) ) ?
  882. L"%wc%I64d" : L"%wc%I64u",
  883. hdc,
  884. rc,
  885. width );
  886. break;
  887. }
  888. //case VT_VECTOR | VT_DATE:
  889. //case VT_VECTOR | VT_FILETIME:
  890. //case VT_VECTOR | VT_CF:
  891. //case VT_VECTOR | VT_CY:
  892. //case VT_VECTOR | VT_VARIANT:
  893. case VT_NULL :
  894. case VT_EMPTY :
  895. {
  896. //_drawText( hdc, rc, width, L"-", -1, TRUE );
  897. break;
  898. }
  899. default :
  900. {
  901. if ( VT_ARRAY & v.vt )
  902. {
  903. RenderSafeArray( awcBuf,
  904. sizeof awcBuf / sizeof WCHAR,
  905. v.vt - VT_ARRAY,
  906. v.parray );
  907. _drawText( hdc, rc, width, awcBuf, -1, TRUE );
  908. break;
  909. }
  910. swprintf( awcTmp, L"(vt 0x%x)", (int) v.vt );
  911. _drawText( hdc, rc, width, awcTmp, -1, TRUE );
  912. break;
  913. }
  914. }
  915. rc.left += ( width + _cpAvgWidth );
  916. }
  917. } //PaintItem
  918. void CSearchView::Size(
  919. int cx,
  920. int cy )
  921. {
  922. HDWP hDefer = BeginDeferWindowPos( 4 );
  923. if ( 0 == hDefer )
  924. return;
  925. int iFontDY = _cpFontHeight;
  926. int dyQuery = _iLineHeightList + _cpFontHeight / 2;
  927. int iListHeight = cy - ( 2 * cpPaneSpacing ) - dyQuery;
  928. int iX = cpPaneMargin;
  929. int iDX = cx - cpPaneMargin * 2;
  930. int iY = cpPaneSpacing;
  931. int iDY = iFontDY;
  932. int iTitleDX = iFontDY * 3;
  933. if (!_fHavePlacedTitles)
  934. hDefer = DeferWindowPos( hDefer,
  935. _hwndQueryTitle,
  936. 0,
  937. iX, iY + iFontDY / 4,
  938. iTitleDX, iDY,
  939. SWP_NOZORDER );
  940. hDefer = DeferWindowPos( hDefer,
  941. _hwndQuery,
  942. 0,
  943. iX + iTitleDX, iY,
  944. iDX - iTitleDX, dyQuery,
  945. SWP_NOZORDER );
  946. if (iListHeight > 0)
  947. {
  948. HD_LAYOUT hdl;
  949. RECT rc = { 0, 0, cx, cy };
  950. hdl.prc = &rc;
  951. WINDOWPOS wp;
  952. hdl.pwpos = &wp;
  953. Header_Layout( _hwndHeader, &hdl );
  954. iY += ( dyQuery + cpPaneSpacing );
  955. hDefer = DeferWindowPos( hDefer,
  956. _hwndHeader,
  957. 0,
  958. iX, iY,
  959. iDX, wp.cy,
  960. SWP_NOZORDER );
  961. int iListY = iY + wp.cy;
  962. iListY--; // too many black lines...
  963. iListHeight = cy - iListY - cpPaneBottomSpacing;
  964. // fit integral number of lines in listview
  965. int cyBorder2x = 2 * GetSystemMetrics( SM_CYBORDER );
  966. _cLines = ( iListHeight - cyBorder2x ) / GetLineHeight();
  967. hDefer = DeferWindowPos( hDefer,
  968. _hwndList,
  969. 0,
  970. iX, iListY,
  971. iDX, _cLines * GetLineHeight() + cyBorder2x,
  972. SWP_NOZORDER );
  973. }
  974. EndDeferWindowPos( hDefer );
  975. _fHavePlacedTitles = TRUE;
  976. } //Size
  977. void CSearchView::FontChanged(
  978. HFONT hfontNew )
  979. {
  980. HDC hdc = GetDC (_hwndList);
  981. if (hdc)
  982. {
  983. HFONT hfOld = (HFONT) SelectObject( hdc, hfontNew );
  984. TEXTMETRIC tm;
  985. GetTextMetrics (hdc, &tm);
  986. _iLineHeightList = (tm.tmHeight + 2 * tm.tmExternalLeading);
  987. SelectObject( hdc, hfOld );
  988. RECT rc;
  989. GetWindowRect(_hwndList,(LPRECT) &rc);
  990. _cLines = (rc.bottom - rc.top) / GetLineHeight();
  991. ReleaseDC( _hwndList, hdc );
  992. }
  993. } //FontChanged
  994. void CSearchView::ResizeQueryCB()
  995. {
  996. RECT rect;
  997. ShowWindow( _hwndQuery, SW_HIDE );
  998. if ( GetClientRect( _hwndQuery, &rect ) )
  999. {
  1000. SetWindowPos( _hwndQuery,
  1001. 0,
  1002. 0,
  1003. 0,
  1004. rect.right,
  1005. 5 * ( _cpFontHeight * 3 ) / 2,
  1006. SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW | SWP_DEFERERASE |
  1007. SWP_NOACTIVATE );
  1008. }
  1009. ShowWindow( _hwndQuery, SW_SHOWNOACTIVATE );
  1010. }
  1011. inline int CSearchView::_MeasureString(
  1012. HDC hdc,
  1013. WCHAR * pwcMeasure,
  1014. RECT & rc,
  1015. int cwc)
  1016. {
  1017. RECT rcMeasure;
  1018. CopyRect( &rcMeasure, &rc );
  1019. DrawText( hdc, pwcMeasure, cwc, &rcMeasure,
  1020. DT_CALCRECT | DT_SINGLELINE | DT_BOTTOM | DT_LEFT );
  1021. return rcMeasure.right - rcMeasure.left;
  1022. } //_MeasureString
  1023. void CSearchView::_ComputeFieldWidths()
  1024. {
  1025. HDC hdc = GetDC( _hwndList );
  1026. if ( 0 == hdc )
  1027. return;
  1028. HFONT hfOld = (HFONT) SelectObject( hdc, (HGDIOBJ) App.AppFont() );
  1029. TEXTMETRIC tm;
  1030. GetTextMetrics( hdc, &tm );
  1031. _cpAvgWidth = tm.tmAveCharWidth;
  1032. RECT rc = { 0, 0, 2000, 2000 };
  1033. SYSTEMTIME st;
  1034. RtlZeroMemory( &st, sizeof st );
  1035. st.wMonth = 12;
  1036. st.wDay = 28;
  1037. st.wDayOfWeek = 3;
  1038. st.wYear = 1994;
  1039. LCID lcid = App.GetLocale();
  1040. WCHAR awc[ cwcBufSize ];
  1041. int cwc = GetDateFormat( lcid, DATE_SHORTDATE, &st, 0, awc, cwcBufSize );
  1042. _cpDateWidth = _MeasureString( hdc, awc, rc, cwc - 1 );
  1043. st.wHour = 22;
  1044. st.wMinute = 59;
  1045. st.wSecond = 59;
  1046. st.wMilliseconds = 10;
  1047. cwc = GetTimeFormat( lcid, 0, &st, 0, awc, cwcBufSize );
  1048. _cpTimeWidth = _MeasureString( hdc, awc, rc, cwc - 1 );
  1049. _cpTimeWidth += _cpAvgWidth; // room between time and date...
  1050. _cpGuidWidth = _MeasureString( hdc, L"{8dee0300-16c2-101b-b121-08002b2ecda9}", rc);
  1051. _cpBoolWidth = _MeasureString( hdc, App.GetFalse(), rc);
  1052. // guess that only half of the attributes will be on at once
  1053. _cpAttribWidth = 4 + _MeasureString( hdc, App.GetAttrib(), rc ) / 2;
  1054. _cpFileIndexWidth = _MeasureString( hdc, L"0x88888888,88888888", rc );
  1055. SelectObject( hdc, hfOld );
  1056. ReleaseDC( _hwndList, hdc );
  1057. } //_ComputeFieldWidths