SPPPropertyGridView.cpp 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. /********************************************
  2. ** 工作室:S&P工作室
  3. ** 作者 :张东斌
  4. ** 日期 :2007年6月
  5. *********************************************/
  6. #include "stdafx.h"
  7. #include "SPDrawHelpers.h"
  8. #include "SPVC80Helpers.h"
  9. #include "resource.h"
  10. #include "SPPropertyGridInplaceEdit.h"
  11. #include "SPPropertyGridInplaceButton.h"
  12. #include "SPPropertyGridInplaceList.h"
  13. #include "SPPropertyGridItem.h"
  14. #include "SPPropertyGrid.h"
  15. #include "SPPropertyGridDefines.h"
  16. #include "SPPropertyGridPaintManager.h"
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. const UINT PGV_HIT_SPLITTER = 0x100;
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CSPPropertyGridToolTip
  25. BEGIN_MESSAGE_MAP(CSPPropertyGridToolTip, CWnd)
  26. //{{AFX_MSG_MAP(CSPPropertyGridView)
  27. ON_WM_ERASEBKGND()
  28. ON_WM_PAINT()
  29. ON_WM_NCHITTEST()
  30. //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32. LRESULT CSPPropertyGridToolTip::OnNcHitTest( CPoint point )
  33. {
  34. UNREFERENCED_PARAMETER( point );
  35. return ( LRESULT ) HTTRANSPARENT;
  36. }
  37. void CSPPropertyGridToolTip::Create( CSPPropertyGridView * pParentWnd )
  38. {
  39. CWnd::CreateEx( 0,AfxRegisterWndClass( 0,LoadCursor( 0,IDC_ARROW ) ),_T( "" ),WS_POPUP,CSPEmptyRect(),pParentWnd,0 );
  40. m_pGrid = pParentWnd;
  41. }
  42. void CSPPropertyGridToolTip::Activate( BOOL bActive )
  43. {
  44. if ( bActive )
  45. {
  46. CString strText;
  47. GetWindowText( strText );
  48. CWindowDC dc ( this );
  49. CSPFontDC font ( &dc,&m_pGrid->m_fontNormal );
  50. CSPWindowRect rc ( this );
  51. rc.right = rc.left + dc.GetTextExtent( strText ).cx + 8;
  52. CRect rcWork = CSPDrawHelpers::GetWorkArea( m_pGrid );
  53. if ( rc.right > rcWork.right )
  54. rc.OffsetRect( rcWork.right - rc.right,0 );
  55. MoveWindow( rc );
  56. }
  57. ShowWindow( bActive ? SW_SHOWNA : SW_HIDE );
  58. }
  59. BOOL CSPPropertyGridToolTip::OnEraseBkgnd( CDC * )
  60. {
  61. return TRUE;
  62. }
  63. void CSPPropertyGridToolTip::OnPaint()
  64. {
  65. CPaintDC dc ( this );
  66. CSPClientRect rc ( this );
  67. COLORREF clrText = GetXtremeColor( COLOR_INFOTEXT );
  68. dc.FillSolidRect( rc,GetXtremeColor( COLOR_INFOBK ) );
  69. dc.Draw3dRect( rc,clrText,clrText );
  70. CString strText;
  71. GetWindowText( strText );
  72. dc.SetTextColor( clrText );
  73. dc.SetBkMode( TRANSPARENT );
  74. CSPFontDC font ( &dc,&m_pGrid->m_fontNormal );
  75. CRect rcText ( rc );
  76. rcText.left += 4;
  77. dc.DrawText( strText,rcText,DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX );
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CSPPropertyGridView
  81. CSPPropertyGridView::CSPPropertyGridView()
  82. {
  83. m_properetySort = SPGridSortCategorized;
  84. m_dDivider = .5;
  85. m_bTracking = FALSE;
  86. LOGFONT lfIcon;
  87. VERIFY( ::SystemParametersInfo( SPI_GETICONTITLELOGFONT,sizeof( lfIcon ),&lfIcon,0 ) );
  88. lfIcon.lfWeight = FW_NORMAL;
  89. lfIcon.lfItalic = FALSE;
  90. VERIFY( m_fontNormal.CreateFontIndirect( &lfIcon ) );
  91. lfIcon.lfWeight = FW_BOLD;
  92. VERIFY( m_fontBold.CreateFontIndirect( &lfIcon ) );
  93. m_pSelected = NULL;
  94. m_pCategories = new CSPPropertyGridItems();
  95. m_pCategories->m_pGrid = this;
  96. m_hCursor = AfxGetApp()->LoadCursor( SP_IDC_HSPLITBAR );
  97. m_nLockUpdate = 0;
  98. m_pGrid = NULL;
  99. }
  100. CSPPropertyGridView::~CSPPropertyGridView()
  101. {
  102. m_pCategories->Clear();
  103. m_pCategories->InternalRelease();
  104. }
  105. IMPLEMENT_DYNAMIC( CSPPropertyGridView , CListBox )
  106. BEGIN_MESSAGE_MAP(CSPPropertyGridView, CListBox)
  107. //{{AFX_MSG_MAP(CSPPropertyGridView)
  108. ON_WM_ERASEBKGND()
  109. ON_WM_PAINT()
  110. ON_WM_NCPAINT()
  111. ON_WM_LBUTTONDOWN()
  112. ON_WM_RBUTTONDOWN()
  113. ON_WM_LBUTTONDBLCLK()
  114. ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelectionChanged)
  115. ON_WM_SETCURSOR()
  116. ON_WM_LBUTTONUP()
  117. ON_WM_CAPTURECHANGED()
  118. ON_WM_MOUSEMOVE()
  119. ON_WM_SIZE()
  120. ON_WM_KEYDOWN()
  121. ON_WM_SYSKEYDOWN()
  122. ON_WM_KEYUP()
  123. ON_WM_SYSKEYUP()
  124. ON_WM_CHAR()
  125. ON_WM_GETDLGCODE()
  126. ON_WM_VSCROLL()
  127. ON_WM_MOUSEWHEEL()
  128. ON_WM_SETFOCUS()
  129. ON_WM_KILLFOCUS()
  130. //}}AFX_MSG_MAP
  131. END_MESSAGE_MAP()
  132. /////////////////////////////////////////////////////////////////////////////
  133. // CSPPropertyGridView message handlers
  134. void CSPPropertyGridView::OnVScroll( UINT nSBCode , UINT nPos , CScrollBar * pScrollBar )
  135. {
  136. if ( GetScrollBarCtrl( SB_VERT ) == pScrollBar )
  137. {
  138. CListBox::OnVScroll( nSBCode,nPos,pScrollBar );
  139. Invalidate( FALSE );
  140. CWnd * pWnd = GetWindow( GW_CHILD );
  141. while ( pWnd )
  142. {
  143. pWnd->Invalidate( FALSE );
  144. pWnd = pWnd->GetWindow( GW_HWNDNEXT );
  145. }
  146. }
  147. else
  148. {
  149. CListBox::OnVScroll( nSBCode,nPos,pScrollBar );
  150. }
  151. }
  152. BOOL CSPPropertyGridView::OnMouseWheel( UINT nFlags , short zDelta , CPoint pt )
  153. {
  154. BOOL bResult = CWnd::OnMouseWheel( nFlags,zDelta,pt );
  155. Invalidate( FALSE );
  156. CWnd * pWnd = GetWindow( GW_CHILD );
  157. while ( pWnd )
  158. {
  159. pWnd->Invalidate( FALSE );
  160. pWnd = pWnd->GetWindow( GW_HWNDNEXT );
  161. }
  162. return bResult;
  163. }
  164. void CSPPropertyGridView::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct )
  165. {
  166. m_pGrid->m_pPaintManager->MeasureItem( lpMeasureItemStruct );
  167. }
  168. void CSPPropertyGridView::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  169. {
  170. ASSERT( lpDrawItemStruct->CtlType == ODT_LISTBOX );
  171. CSPPropertyGridItem * pItem = ( CSPPropertyGridItem * ) lpDrawItemStruct->itemData;
  172. if ( pItem == NULL )
  173. {
  174. return;
  175. }
  176. if ( ( int ) lpDrawItemStruct->itemID == GetCount() - 1 )
  177. {
  178. CDC * pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
  179. CSPClientRect rc ( this );
  180. rc.top = lpDrawItemStruct->rcItem.bottom;
  181. pDC->FillSolidRect( rc,m_clrBack );
  182. }
  183. if ( !( ( GetParent()->GetStyle() & SP_PGS_OWNERDRAW ) && ( GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_DRAWITEM,( LPARAM ) lpDrawItemStruct ) == TRUE ) ) )
  184. {
  185. m_pGrid->m_pPaintManager->DrawItem( lpDrawItemStruct );
  186. }
  187. }
  188. BOOL CSPPropertyGridView::OnEraseBkgnd( CDC * )
  189. {
  190. return TRUE;
  191. }
  192. void CSPPropertyGridView::OnPaint()
  193. {
  194. CPaintDC dc ( this );
  195. CSPClientRect rc ( this );
  196. CSPBufferDC buffer ( dc,rc );
  197. ASSERT( m_pGrid );
  198. m_pGrid->m_pPaintManager->FillPropertyGridView( &buffer,TRUE );
  199. CWnd::DefWindowProc( WM_PAINT,( WPARAM ) buffer.m_hDC,0 );
  200. }
  201. void CSPPropertyGridView::OnNcPaint()
  202. {
  203. CWindowDC dc ( this );
  204. CWnd::DefWindowProc( WM_PRINT,( WPARAM ) dc.m_hDC,PRF_NONCLIENT );
  205. ASSERT( m_pGrid );
  206. m_pGrid->m_pPaintManager->FillPropertyGridView( &dc,FALSE );
  207. }
  208. CSPPropertyGridItem * CSPPropertyGridView::InsertCategory( int nIndex , CString strCaption , CSPPropertyGridItem * pCategory )
  209. {
  210. ASSERT( nIndex >= 0 && nIndex <= m_pCategories->GetCount() );
  211. if ( nIndex < 0 || nIndex > m_pCategories->GetCount() )
  212. {
  213. nIndex = m_pCategories->GetCount();
  214. }
  215. if ( pCategory == NULL )
  216. {
  217. pCategory = new CSPPropertyGridItem( strCaption );
  218. }
  219. SetPropertySort( SPGridSortCategorized );
  220. pCategory->m_pGrid = this;
  221. pCategory->m_bCategory = TRUE;
  222. pCategory->m_nFlags = 0;
  223. pCategory->m_pChilds->m_pGrid = this;
  224. m_pCategories->InsertAt( nIndex,pCategory );
  225. if ( m_hWnd )
  226. {
  227. int nInsertAt = ( nIndex >= m_pCategories->GetCount() - 1 ) ? GetCount() : m_pCategories->GetAt( nIndex + 1 )->m_nIndex;
  228. InsertItem( pCategory,nInsertAt );
  229. }
  230. _RefreshIndexes();
  231. return pCategory;
  232. }
  233. CSPPropertyGridItem * CSPPropertyGridView::AddCategory( CString strCaption , CSPPropertyGridItem * pCategory )
  234. {
  235. return InsertCategory( m_pCategories->GetCount(),strCaption,pCategory );
  236. }
  237. void CSPPropertyGridView::Refresh()
  238. {
  239. _RefreshIndexes();
  240. SetPropertySort( m_properetySort,TRUE );
  241. if ( GetSafeHwnd() )
  242. {
  243. GetParent()->Invalidate( FALSE );
  244. }
  245. }
  246. void CSPPropertyGridView::ResetContent()
  247. {
  248. if ( m_pSelected )
  249. {
  250. m_pSelected->OnDeselect();
  251. m_pSelected = NULL;
  252. }
  253. if ( m_hWnd )
  254. {
  255. for ( int i = 0; i < GetCount(); i++ )
  256. {
  257. CSPPropertyGridItem * pItem = ( CSPPropertyGridItem * ) GetItemDataPtr( i );
  258. ASSERT( pItem );
  259. pItem->SetVisible( FALSE );
  260. }
  261. CListBox::ResetContent();
  262. SetFont( &m_fontNormal,FALSE );
  263. CWindowDC dc ( this );
  264. CSPFontDC font ( &dc,&m_fontNormal );
  265. SetItemHeight( 0,dc.GetTextExtent( _T( " " ) ).cy + 4 );
  266. }
  267. }
  268. void CSPPropertyGridView::SetPropertySort( SPPropertyGridSortOrder sort , BOOL bRrefresh )
  269. {
  270. if ( m_nLockUpdate > 0 )
  271. {
  272. m_properetySort = sort;
  273. return;
  274. }
  275. if ( sort == m_properetySort && !bRrefresh )
  276. {
  277. return;
  278. }
  279. if ( !m_hWnd )
  280. {
  281. return;
  282. }
  283. CSPPropertyGridItem * pSelected = GetSelectedItem();
  284. ResetContent();
  285. if ( sort == SPGridSortCategorized )
  286. {
  287. for ( int i = 0; i < m_pCategories->GetCount(); i++ )
  288. {
  289. CSPPropertyGridItem * pCategory = m_pCategories->GetAt( i );
  290. InsertItem( pCategory,GetCount() );
  291. }
  292. }
  293. else if ( sort == SPGridSortAlphabetical || sort == SPGridSortNoSort )
  294. {
  295. CSPPropertyGridItems lstItems;
  296. int i;
  297. for ( i = 0; i < m_pCategories->GetCount(); i++ )
  298. {
  299. CSPPropertyGridItem * pCategory = m_pCategories->GetAt( i );
  300. lstItems.AddTail( pCategory->m_pChilds );
  301. }
  302. if ( sort != SPGridSortNoSort )
  303. lstItems.Sort();
  304. for ( i = 0; i < lstItems.GetCount(); i++ )
  305. {
  306. CSPPropertyGridItem * pItem = lstItems.GetAt( i );
  307. InsertItem( pItem,GetCount() );
  308. }
  309. }
  310. else
  311. {
  312. ASSERT( FALSE );
  313. }
  314. _RefreshIndexes();
  315. if ( pSelected )
  316. {
  317. pSelected->Select();
  318. }
  319. OnSelectionChanged();
  320. if ( sort != m_properetySort )
  321. {
  322. m_properetySort = sort;
  323. ( ( CSPPropertyGrid * ) GetParent() )->OnSortChanged();
  324. }
  325. }
  326. int CSPPropertyGridView::GetDividerPos()
  327. {
  328. CSPWindowRect rcWindow ( this );
  329. return int( m_dDivider * rcWindow.Width() );
  330. }
  331. int CSPPropertyGridView::InsertItem( CSPPropertyGridItem * pItem , int nIndex )
  332. {
  333. if ( m_nLockUpdate > 0 )
  334. {
  335. return 0;
  336. }
  337. if ( !m_hWnd )
  338. {
  339. return 0;
  340. }
  341. pItem->OnBeforeInsert();
  342. nIndex = ( int ) ::SendMessage( m_hWnd,LB_INSERTSTRING,nIndex,( LPARAM ) pItem );
  343. ASSERT( nIndex != -1 );
  344. SetItemDataPtr( nIndex,pItem );
  345. if ( GetStyle() & LBS_OWNERDRAWVARIABLE )
  346. {
  347. MEASUREITEMSTRUCT measureItemStruct ={ODT_LISTBOX, 0, nIndex, 0, 0, ( ULONG_PTR ) pItem};
  348. MeasureItem( &measureItemStruct );
  349. if ( measureItemStruct.itemHeight != 0 )
  350. {
  351. SetItemHeight( nIndex,measureItemStruct.itemHeight );
  352. }
  353. }
  354. pItem->SetVisible( TRUE );
  355. int nItemsInserted = 1;
  356. if ( pItem->m_bExpanded )
  357. {
  358. nItemsInserted += _DoExpand( pItem,nIndex );
  359. }
  360. return nItemsInserted;
  361. }
  362. int CSPPropertyGridView::_DoExpand( CSPPropertyGridItem * pItem , int nIndex )
  363. {
  364. int nStart = nIndex;
  365. for ( int i = 0; i < pItem->GetChilds()->GetCount(); i++ )
  366. {
  367. CSPPropertyGridItem * pChild = pItem->GetChilds()->GetAt( i );
  368. nIndex += InsertItem( pChild,nIndex + 1 );
  369. }
  370. return nIndex - nStart;
  371. }
  372. void CSPPropertyGridView::_RefreshIndexes()
  373. {
  374. if ( m_hWnd )
  375. {
  376. for ( int i = 0; i < GetCount(); i++ )
  377. {
  378. CSPPropertyGridItem * pItem = ( CSPPropertyGridItem * ) GetItemDataPtr( i );
  379. ASSERT( pItem );
  380. pItem->m_nIndex = i;
  381. }
  382. }
  383. }
  384. void CSPPropertyGridView::_DoCollapse( CSPPropertyGridItem * pItem )
  385. {
  386. ASSERT( pItem );
  387. ASSERT( pItem->m_bExpanded );
  388. int nIndex = pItem->m_nIndex + 1;
  389. while ( nIndex < GetCount() )
  390. {
  391. CSPPropertyGridItem * pChild = ( CSPPropertyGridItem * ) GetItemDataPtr( nIndex );
  392. ASSERT( pChild );
  393. if ( !pChild || !pChild->HasParent( pItem ) )
  394. break;
  395. pChild->SetVisible( FALSE );
  396. DeleteString( nIndex );
  397. }
  398. _RefreshIndexes();
  399. }
  400. CSPPropertyGridItem * CSPPropertyGridView::GetItem( int nIndex )
  401. {
  402. if ( nIndex < 0 || nIndex >= GetCount() )
  403. {
  404. return 0;
  405. }
  406. CSPPropertyGridItem * pItem = ( CSPPropertyGridItem * ) GetItemDataPtr( nIndex );
  407. if ( ( ULONG_PTR ) pItem == ( ULONG_PTR ) ( -1 ) )
  408. {
  409. return NULL;
  410. }
  411. ASSERT( pItem );
  412. return pItem;
  413. }
  414. void CSPPropertyGridView::SwitchExpandState( int nItem )
  415. {
  416. CSPPropertyGridItem * pItem = GetItem( nItem );
  417. if ( !pItem )
  418. {
  419. return;
  420. }
  421. if ( pItem->m_bExpanded )
  422. {
  423. pItem->Collapse();
  424. }
  425. else
  426. {
  427. pItem->Expand();
  428. }
  429. }
  430. void CSPPropertyGridView::OnLButtonDown( UINT nFlags , CPoint point )
  431. {
  432. if ( HitTest( point ) == PGV_HIT_SPLITTER )
  433. {
  434. SetFocus();
  435. SetCapture();
  436. if ( m_pSelected )
  437. m_pSelected->OnValidateEdit();
  438. m_bTracking = TRUE;
  439. return;
  440. }
  441. CSPPropertyGridItem * pItem = ItemFromPoint( point );
  442. if ( pItem )
  443. {
  444. SetFocus();
  445. if ( GetFocus() != this )
  446. return;
  447. if ( ( ItemFromPoint( point ) == pItem ) && pItem->OnLButtonDown( nFlags,point ) )
  448. return;
  449. }
  450. CListBox::OnLButtonDown( nFlags,point );
  451. }
  452. CSPPropertyGridItem * CSPPropertyGridView::ItemFromPoint( CPoint point )
  453. {
  454. BOOL bOutside = FALSE;
  455. int nIndex = CListBox::ItemFromPoint( point,bOutside );
  456. if ( nIndex != -1 && !bOutside )
  457. {
  458. return GetItem( nIndex );
  459. }
  460. return NULL;
  461. }
  462. void CSPPropertyGridView::OnMouseMove( UINT nFlags , CPoint point )
  463. {
  464. if ( m_bTracking )
  465. {
  466. CSPWindowRect rcWindow ( this );
  467. m_dDivider = ( double ) point.x / rcWindow.Width();
  468. m_dDivider = __max( m_dDivider,.1 );
  469. m_dDivider = __min( m_dDivider,.85 );
  470. if ( m_pSelected )
  471. m_pSelected->OnSelect();
  472. Invalidate( FALSE );
  473. }
  474. else
  475. {
  476. ShowToolTip( point );
  477. }
  478. CListBox::OnMouseMove( nFlags,point );
  479. }
  480. void CSPPropertyGridView::OnLButtonUp( UINT nFlags , CPoint point )
  481. {
  482. if ( m_bTracking )
  483. {
  484. ReleaseCapture();
  485. m_bTracking = FALSE;
  486. }
  487. CListBox::OnLButtonUp( nFlags,point );
  488. }
  489. void CSPPropertyGridView::OnCaptureChanged( CWnd * pWnd )
  490. {
  491. m_bTracking = FALSE;
  492. CListBox::OnCaptureChanged( pWnd );
  493. }
  494. void CSPPropertyGridView::OnLButtonDblClk( UINT nFlags , CPoint point )
  495. {
  496. CListBox::OnLButtonDblClk( nFlags,point );
  497. CSPPropertyGridItem * pItem = ItemFromPoint( point );
  498. if ( pItem )
  499. {
  500. pItem->OnLButtonDblClk();
  501. if ( pItem == ItemFromPoint( point ) )
  502. {
  503. GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_DBLCLICK,( LPARAM ) pItem );
  504. }
  505. }
  506. }
  507. void CSPPropertyGridView::OnRButtonDown( UINT nFlags , CPoint point )
  508. {
  509. CListBox::OnRButtonDown( nFlags,point );
  510. CSPPropertyGridItem * pItem = ItemFromPoint( point );
  511. if ( pItem )
  512. {
  513. pItem->OnRButtonDown();
  514. if ( pItem == ItemFromPoint( point ) )
  515. {
  516. GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_RCLICK,( LPARAM ) pItem );
  517. }
  518. }
  519. }
  520. CSPPropertyGridItem * CSPPropertyGridView::GetSelectedItem()
  521. {
  522. return m_hWnd ? GetItem( GetCurSel() ) : 0;
  523. }
  524. void CSPPropertyGridView::OnChar( UINT nChar , UINT nRepCntr , UINT nFlags )
  525. {
  526. if ( m_bTracking )
  527. {
  528. return;
  529. }
  530. CSPPropertyGridItem * pItem = GetSelectedItem();
  531. if ( nChar == '+' && pItem && pItem->HasChilds() && !pItem->m_bExpanded )
  532. {
  533. pItem->Expand();
  534. return;
  535. }
  536. if ( nChar == '-' && pItem && pItem->HasChilds() && pItem->m_bExpanded )
  537. {
  538. pItem->Collapse();
  539. return;
  540. }
  541. if ( nChar == VK_TAB )
  542. {
  543. m_pGrid->OnNavigate( SPGridUIView,GetKeyState( VK_SHIFT ) >= 0,pItem );
  544. return;
  545. }
  546. if ( pItem && ( nChar != VK_RETURN || !pItem->HasChilds() ) )
  547. {
  548. if ( pItem->OnChar( nChar ) )
  549. {
  550. return;
  551. }
  552. }
  553. CWnd::OnChar( nChar,nRepCntr,nFlags );
  554. }
  555. UINT CSPPropertyGridView::OnGetDlgCode()
  556. {
  557. return DLGC_WANTALLKEYS;
  558. }
  559. void CSPPropertyGridView::OnKeyUp( UINT nChar , UINT nRepCnt , UINT nFlags )
  560. {
  561. #ifdef SP_SITENOTIFY_KEY
  562. SP_SITENOTIFY_KEY( this,this,FALSE,nChar )
  563. #endif
  564. CListBox::OnKeyUp( nChar,nRepCnt,nFlags );
  565. }
  566. void CSPPropertyGridView::OnSysKeyUp( UINT nChar , UINT nRepCnt , UINT nFlags )
  567. {
  568. #ifdef SP_SITENOTIFY_KEY
  569. SP_SITENOTIFY_KEY( this,this,FALSE,nChar )
  570. #endif
  571. CListBox::OnSysKeyUp( nChar,nRepCnt,nFlags );
  572. }
  573. void CSPPropertyGridView::OnKeyDown( UINT nChar , UINT nRepCnt , UINT nFlags )
  574. {
  575. #ifdef SP_SITENOTIFY_KEY
  576. SP_SITENOTIFY_KEY( this,this,TRUE,nChar )
  577. #endif
  578. CSPPropertyGridItem * pItem = GetSelectedItem();
  579. if ( nChar == VK_RIGHT )
  580. {
  581. if ( GetKeyState( VK_CONTROL ) < 0 )
  582. {
  583. CSPWindowRect rcWindow ( this );
  584. m_dDivider = m_dDivider + 2.0 / rcWindow.Width();
  585. m_dDivider = __max( m_dDivider,.1 );
  586. m_dDivider = __min( m_dDivider,.85 );
  587. if ( m_pSelected )
  588. m_pSelected->OnSelect();
  589. Invalidate( FALSE );
  590. return;
  591. }
  592. if ( pItem && pItem->HasChilds() && !pItem->m_bExpanded )
  593. {
  594. pItem->Expand();
  595. return;
  596. }
  597. }
  598. else if ( nChar == VK_LEFT )
  599. {
  600. if ( GetKeyState( VK_CONTROL ) < 0 )
  601. {
  602. CSPWindowRect rcWindow ( this );
  603. m_dDivider = m_dDivider - 2.0 / rcWindow.Width();
  604. m_dDivider = __max( m_dDivider,.1 );
  605. m_dDivider = __min( m_dDivider,.85 );
  606. if ( m_pSelected )
  607. m_pSelected->OnSelect();
  608. Invalidate( FALSE );
  609. return;
  610. }
  611. if ( pItem && pItem->HasChilds() && pItem->m_bExpanded )
  612. {
  613. pItem->Collapse();
  614. return;
  615. }
  616. }
  617. if ( nChar == VK_RETURN )
  618. {
  619. SwitchExpandState( GetCurSel() );
  620. return ;
  621. }
  622. if ( nChar == VK_F4 )
  623. {
  624. if ( m_pSelected && m_pSelected->GetFlags() & SPGridItemHasComboButton )
  625. {
  626. m_pSelected->OnInplaceButtonDown();
  627. }
  628. }
  629. CListBox::OnKeyDown( nChar,nRepCnt,nFlags );
  630. }
  631. void CSPPropertyGridView::OnSysKeyDown( UINT nChar , UINT nRepCnt , UINT nFlags )
  632. {
  633. #ifdef SP_SITENOTIFY_KEY
  634. SP_SITENOTIFY_KEY( this,this,TRUE,nChar )
  635. #endif
  636. if ( nChar == VK_DOWN || nChar == VK_UP )
  637. {
  638. if ( m_pSelected && m_pSelected->GetFlags() & SPGridItemHasComboButton )
  639. {
  640. m_pSelected->OnInplaceButtonDown();
  641. }
  642. }
  643. CListBox::OnSysKeyDown( nChar,nRepCnt,nFlags );
  644. }
  645. BOOL CSPPropertyGridView::OnWndMsg( UINT message , WPARAM wParam , LPARAM lParam , LRESULT * pResult )
  646. {
  647. static BOOL bRelay = FALSE;
  648. if ( m_wndTip.GetSafeHwnd() && m_wndTip.IsWindowVisible() && !bRelay )
  649. {
  650. bRelay = TRUE;
  651. RelayToolTipEvent( message );
  652. bRelay = FALSE;
  653. }
  654. return CWnd::OnWndMsg( message,wParam,lParam,pResult );
  655. }
  656. void CSPPropertyGridView::OnSelectionChanged()
  657. {
  658. CSPPropertyGridItem * pItem = GetSelectedItem();
  659. if ( m_pSelected )
  660. {
  661. m_pSelected->OnDeselect();
  662. }
  663. if ( pItem )
  664. {
  665. pItem->OnSelect();
  666. }
  667. m_pSelected = pItem;
  668. if ( m_pSelected )
  669. {
  670. ( ( CSPPropertyGrid * ) GetParent() )->OnSelectionChanged( m_pSelected );
  671. }
  672. }
  673. int CSPPropertyGridView::HitTest( CPoint point )
  674. {
  675. CSPWindowRect rcWindow ( this );
  676. int nWidth = int( m_dDivider * rcWindow.Width() );
  677. if ( point.x > nWidth - 4 && point.x <= nWidth + 2 && GetCount() > 0 )
  678. {
  679. return PGV_HIT_SPLITTER;
  680. }
  681. return -1;
  682. }
  683. BOOL CSPPropertyGridView::OnSetCursor( CWnd * pWnd , UINT nHitTest , UINT message )
  684. {
  685. if ( nHitTest == HTCLIENT )
  686. {
  687. CPoint point;
  688. GetCursorPos( &point );
  689. ScreenToClient( &point );
  690. if ( HitTest( point ) == PGV_HIT_SPLITTER )
  691. {
  692. SetCursor( m_hCursor );
  693. return TRUE;
  694. }
  695. }
  696. return CListBox::OnSetCursor( pWnd,nHitTest,message );
  697. }
  698. void CSPPropertyGridView::OnSize( UINT nType , int cx , int cy )
  699. {
  700. CListBox::OnSize( nType,cx,cy );
  701. OnSelectionChanged();
  702. }
  703. // ToolTips routings
  704. void CSPPropertyGridView::_ShowToolTip( CRect rcBound , CRect rcText )
  705. {
  706. m_wndTip.SetWindowText( m_strTipText );
  707. m_wndTip.MoveWindow( rcText );
  708. m_wndTip.Activate( TRUE );
  709. m_rcToolTip = rcBound;
  710. TRACKMOUSEEVENT tme ={sizeof( TRACKMOUSEEVENT ), TME_LEAVE, m_hWnd, 0};
  711. _TrackMouseEvent( &tme );
  712. }
  713. CSize CSPPropertyGridView::_GetTextExtent( CString str )
  714. {
  715. CWindowDC dc ( this );
  716. CSPFontDC font ( &dc,GetFont() );
  717. return dc.GetTextExtent( str );
  718. }
  719. void CSPPropertyGridView::ShowToolTip( CPoint pt )
  720. {
  721. if ( !m_wndTip.GetSafeHwnd() )
  722. {
  723. m_wndTip.Create( this );
  724. }
  725. CSPPropertyGridItem * pItem = ItemFromPoint( pt );
  726. if ( !pItem || pItem->IsCategory() )
  727. {
  728. return;
  729. }
  730. CSPWindowRect rcWindow ( this );
  731. CRect rc = pItem->GetItemRect();
  732. CRect rcCaption ( rc.left,rc.top,rc.left + int( m_dDivider * rcWindow.Width() ),rc.bottom );
  733. if ( rcCaption.PtInRect( pt ) )
  734. {
  735. if ( m_strTipText == pItem->GetCaption() )
  736. return;
  737. m_strTipText = pItem->GetCaption();
  738. ClientToScreen( &rcCaption );
  739. CRect rcCaptionText ( rcCaption );
  740. rcCaptionText.left += pItem->m_nIndent * SP_PGI_EXPAND_BORDER + 3 - 3 - 1;
  741. rcCaptionText.top--;
  742. if ( _GetTextExtent( m_strTipText ).cx + 3 > rcCaptionText.Width() )
  743. {
  744. if ( GetExStyle() & WS_EX_LAYOUTRTL )
  745. {
  746. rcCaptionText.left = rcCaption.right - _GetTextExtent( m_strTipText ).cx - 7 - ( pItem->m_nIndent * SP_PGI_EXPAND_BORDER );
  747. }
  748. _ShowToolTip( rcCaption,rcCaptionText );
  749. }
  750. }
  751. else
  752. {
  753. if ( m_strTipText == pItem->GetViewValue() )
  754. return;
  755. m_strTipText = pItem->GetViewValue();
  756. if ( GetFocus() && GetFocus()->IsKindOf( RUNTIME_CLASS( CSPPropertyGridInplaceEdit ) ) )
  757. {
  758. if ( ( ( CSPPropertyGridInplaceEdit * ) ( GetFocus() ) )->GetItem() == pItem )
  759. return;
  760. }
  761. CRect rcValue ( rc.left + int( m_dDivider * rcWindow.Width() ),rc.top,rc.right,rc.bottom );
  762. ClientToScreen( &rcValue );
  763. CRect rcValueText = pItem->GetValueRect();
  764. rcValueText.InflateRect( 1,2,0,1 );
  765. ClientToScreen( &rcValueText );
  766. if ( _GetTextExtent( m_strTipText ).cx + 3 > rcValueText.Width() )
  767. {
  768. if ( GetExStyle() & WS_EX_LAYOUTRTL )
  769. {
  770. rcValueText.left = rcValueText.right - 8 - _GetTextExtent( m_strTipText ).cx;
  771. }
  772. _ShowToolTip( rcValue,rcValueText );
  773. }
  774. }
  775. }
  776. void CSPPropertyGridView::RelayToolTipEvent( UINT message )
  777. {
  778. if ( m_wndTip.GetSafeHwnd() && m_wndTip.IsWindowVisible() )
  779. {
  780. CRect rc;
  781. m_wndTip.GetWindowRect( rc );
  782. CPoint pt;
  783. GetCursorPos( &pt );
  784. if ( !m_rcToolTip.PtInRect( pt ) )
  785. {
  786. m_strTipText = "";
  787. m_wndTip.Activate( FALSE );
  788. }
  789. switch ( message )
  790. {
  791. case WM_MOUSEWHEEL:
  792. m_strTipText = "";
  793. case WM_KEYDOWN:
  794. case WM_SYSKEYDOWN:
  795. case WM_LBUTTONDOWN:
  796. case WM_RBUTTONDOWN:
  797. case WM_MBUTTONDOWN:
  798. case WM_LBUTTONUP:
  799. case WM_RBUTTONUP:
  800. case WM_MBUTTONUP:
  801. case WM_MOUSELEAVE:
  802. m_wndTip.Activate( FALSE );
  803. }
  804. }
  805. }
  806. void CSPPropertyGridView::OnSetFocus( CWnd * pOldWnd )
  807. {
  808. CListBox::OnSetFocus( pOldWnd );
  809. #ifdef SP_SITENOTIFY_ONFOCUS
  810. SP_SITENOTIFY_ONFOCUS( this,this,TRUE )
  811. #endif
  812. }
  813. void CSPPropertyGridView::OnKillFocus( CWnd * pNewWnd )
  814. {
  815. CListBox::OnKillFocus( pNewWnd );
  816. #ifdef SP_SITENOTIFY_ONFOCUS
  817. SP_SITENOTIFY_ONFOCUS( this,this,FALSE )
  818. #endif
  819. }