IconListBox.cpp
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:13k
源码类别:

界面编程

开发平台:

Visual C++

  1. // IconListBox.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "ProfUIS_Controls.h"
  5. #include "IconListBox.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. /////////////////////////////////////////////////////////////////////////////
  12. // CListBoxCustomPainted window
  13. IMPLEMENT_DYNCREATE( CListBoxCustomPainted, CListBox );
  14. CListBoxCustomPainted::CListBoxCustomPainted()
  15. : m_bShowSelAlways( true )
  16. , m_bCaseSensitiveSort( true )
  17. , m_bAutoDestroyListBox( false )
  18. {
  19. PmBridge_Install( true );
  20. }
  21. CListBoxCustomPainted::~CListBoxCustomPainted()
  22. {
  23. PmBridge_Uninstall();
  24. }
  25. void CListBoxCustomPainted::_RedrawLB()
  26. {
  27. ASSERT_VALID( this );
  28. ASSERT( GetSafeHwnd() != NULL );
  29. Invalidate();
  30. UpdateWindow();
  31. }
  32. HFONT CListBoxCustomPainted::OnLbQueryItemFont( INT nItemIndex )
  33. {
  34. ASSERT_VALID( this );
  35. ASSERT( GetSafeHwnd() != NULL );
  36. nItemIndex;
  37. return (HFONT) ::SendMessage( m_hWnd, WM_GETFONT, 0, 0 );
  38. }
  39. CSize CListBoxCustomPainted::OnLbQueryItemExtraSize( INT nItemIndex )
  40. {
  41. ASSERT_VALID( this );
  42. ASSERT( GetSafeHwnd() != NULL );
  43. nItemIndex;
  44. return CSize( 2, 0 );
  45. }
  46. bool CListBoxCustomPainted::OnLbQueryWindowFocusedState()
  47. {
  48. ASSERT_VALID( this );
  49. ASSERT( GetSafeHwnd() != NULL );
  50. if( ::GetFocus() == m_hWnd )
  51. return true;
  52. else
  53. return false;
  54. }
  55. bool CListBoxCustomPainted::OnLbEraseEntire( CDC & dc, CRect rcClient )
  56. {
  57. ASSERT_VALID( this );
  58. ASSERT( dc.GetSafeHdc() != NULL );
  59. dc;
  60. rcClient;
  61. return false;
  62. }
  63. void CListBoxCustomPainted::PmBridge_OnPaintManagerChanged(
  64. CExtPaintManager * pGlobalPM
  65. )
  66. {
  67. ASSERT_VALID( this );
  68. CExtPmBridge::PmBridge_OnPaintManagerChanged( pGlobalPM );
  69. if( GetSafeHwnd() == NULL )
  70. return;
  71. Invalidate();
  72. }
  73. BEGIN_MESSAGE_MAP( CListBoxCustomPainted, CListBox )
  74. //{{AFX_MSG_MAP(CListBoxCustomPainted)
  75. //}}AFX_MSG_MAP
  76. ON_CONTROL_REFLECT( LBN_SELCANCEL, OnLbnReflectSelCancel )
  77. ON_CONTROL_REFLECT( LBN_KILLFOCUS, OnLbnReflectKillFocus )
  78. ON_CONTROL_REFLECT( LBN_SETFOCUS, OnLbnReflectSetFocus )
  79. END_MESSAGE_MAP()
  80. LRESULT CListBoxCustomPainted::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
  81. {
  82. if( message == WM_ERASEBKGND )
  83. return TRUE;
  84. if( message == WM_PAINT )
  85. {
  86. CRect rcClient;
  87. GetClientRect( &rcClient );
  88. CPaintDC dcPaint( this );
  89. CExtMemoryDC dc( &dcPaint, &rcClient );
  90. CExtPaintManager * pPM = PmBridge_GetPM();
  91. ASSERT_VALID( pPM );
  92. if( ! OnLbEraseEntire( dc, rcClient ) )
  93. dc.FillSolidRect( &rcClient, pPM->GetColor( COLOR_WINDOW, this ) );
  94. HWND hWndParent = ::GetParent( m_hWnd );
  95. UINT nOwnDlgCtrlID = UINT( GetDlgCtrlID() );
  96. INT nItemIndex, nCurSel = INT( GetCurSel() ), nItemCount = INT( GetCount() ), nTopIndex = ((CListBox*)this)->GetTopIndex();
  97. for( nItemIndex = nTopIndex; nItemIndex < nItemCount; nItemIndex ++ )
  98. {
  99. DRAWITEMSTRUCT dis;
  100. ::memset( &dis, 0, sizeof( DRAWITEMSTRUCT ) );
  101. dis.CtlType = ODT_LISTBOX;
  102. dis.CtlID = nOwnDlgCtrlID;
  103. dis.itemID = nItemIndex;
  104. dis.hDC = dc.GetSafeHdc();
  105. GetItemRect( nItemIndex, &dis.rcItem );
  106. dis.itemAction = ODA_DRAWENTIRE;
  107. dis.hwndItem = GetSafeHwnd();
  108. if( rcClient.bottom < dis.rcItem.top )
  109. break;
  110. if( GetSel( nItemIndex ) > 0 )
  111. dis.itemState |= ODS_SELECTED;
  112. if( nCurSel == nItemIndex )
  113. dis.itemState |= ODS_FOCUS;
  114. ::SendMessage( hWndParent, WM_DRAWITEM, (WPARAM)nOwnDlgCtrlID, (LPARAM)&dis );
  115. }
  116. return 0;
  117. }
  118. if( message == WM_MOUSEWHEEL )
  119. {
  120. INT nDelta = INT( short(HIWORD(wParam)) );
  121. if( ( GetStyle() & WS_VSCROLL ) != 0 )
  122. SendMessage( WM_VSCROLL, MAKELONG( ( ( nDelta > 0 ) ? SB_LINEUP : SB_LINEDOWN ), 0 ) );
  123. return 0;
  124. }
  125. if( message == WM_HSCROLL || message == WM_VSCROLL )
  126. {
  127. Invalidate();
  128. }
  129. return CListBox::WindowProc( message, wParam, lParam );
  130. }
  131. void CListBoxCustomPainted::PreSubclassWindow()
  132. {
  133. CListBox::PreSubclassWindow();
  134. }
  135. void CListBoxCustomPainted::PostNcDestroy()
  136. {
  137. CListBox::PostNcDestroy();
  138. if( m_bAutoDestroyListBox )
  139. delete this;
  140. }
  141. void CListBoxCustomPainted::DrawItem( LPDRAWITEMSTRUCT pDIS ) 
  142. {
  143. ASSERT_VALID( this );
  144. ASSERT( pDIS != NULL );
  145. ASSERT( pDIS->hDC != NULL );
  146. if( ((INT)pDIS->itemID) < 0 )
  147. return;
  148. DWORD dwStyle = GetStyle();
  149. if( ( dwStyle & LBS_HASSTRINGS ) == 0
  150. && ( dwStyle & (LBS_OWNERDRAWFIXED|LBS_OWNERDRAWVARIABLE) ) != 0
  151. )
  152. return;
  153. INT nItemCount = INT( GetCount() ), nItemIndex = pDIS->itemID;
  154. if( nItemIndex < 0 || nItemIndex >= nItemCount )
  155. return;
  156. CExtPaintManager * pPM = PmBridge_GetPM();
  157. ASSERT_VALID( pPM );
  158. bool bWindowFocused = OnLbQueryWindowFocusedState();
  159. bool bSelected = ( ( bWindowFocused || m_bShowSelAlways ) && ( pDIS->itemState & ODS_SELECTED ) != 0 ) ? true : false;
  160. bool bFocused = ( bWindowFocused && ( pDIS->itemState & ODS_FOCUS ) != 0 ) ? true : false;
  161. CDC dc;
  162. dc.Attach( pDIS->hDC );
  163. if( pDIS->itemAction & (ODA_DRAWENTIRE|ODA_SELECT) )
  164. {
  165. CRect rcErase( pDIS->rcItem );
  166. if( nItemIndex == ( nItemCount - 1 ) )
  167. {
  168. CRect rcClient;
  169. GetClientRect( &rcClient );
  170. if( rcErase.bottom < rcClient.bottom )
  171. rcErase.bottom = rcClient.bottom;
  172. }
  173. COLORREF clrBk = pPM->GetColor( ( ! IsWindowEnabled() ) ? COLOR_3DFACE : COLOR_WINDOW, this );
  174. dc.FillSolidRect( rcErase, clrBk );
  175. }
  176. CRect rcDrawItem( pDIS->rcItem );
  177. CSize sizeLbItemExtra = OnLbQueryItemExtraSize( nItemIndex );
  178. rcDrawItem.DeflateRect( sizeLbItemExtra );
  179. if( bSelected )
  180. dc.FillSolidRect( &rcDrawItem, pPM->GetColor( bWindowFocused ? COLOR_HIGHLIGHT : COLOR_3DFACE, this ) );
  181. CString sText;
  182. GetText( nItemIndex, sText );
  183. if( ! sText.IsEmpty() )
  184. {
  185. HFONT hFont = OnLbQueryItemFont( nItemIndex );
  186. ASSERT( hFont != NULL );
  187. HGDIOBJ hOldFont = ::SelectObject( dc.m_hDC, hFont );
  188. COLORREF clrTextOld = dc.SetTextColor( pPM->GetColor( bSelected  ? ( bWindowFocused ?  COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT ) : COLOR_BTNTEXT, this ) );
  189. int nOldBkMode = dc.SetBkMode( TRANSPARENT );
  190. CRect rcText( rcDrawItem );
  191. UINT nFormat = DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_NOPREFIX;
  192. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  193. nFormat |= DT_EXPANDTABS;
  194. dc.DrawText( sText, &rcText, nFormat );
  195. dc.SetBkMode( nOldBkMode );
  196. dc.SetTextColor( clrTextOld );
  197. ::SelectObject( dc.m_hDC, hOldFont );
  198. }
  199. if( bFocused )
  200. {
  201. COLORREF clrTextOld = dc.SetTextColor( RGB(255,255,255) );
  202. COLORREF clrBkOld = dc.SetBkColor( RGB(0,0,0) );
  203. dc.DrawFocusRect( &rcDrawItem );
  204. dc.SetBkColor( clrBkOld );
  205. dc.SetTextColor( clrTextOld );
  206. }
  207. dc.Detach();
  208. }
  209. void CListBoxCustomPainted::MeasureItem( LPMEASUREITEMSTRUCT pMIS ) 
  210. {
  211. ASSERT_VALID( this );
  212. ASSERT( pMIS != NULL );
  213. ASSERT( ((INT)pMIS->itemID) >= 0 );
  214. DWORD dwStyle = GetStyle();
  215. if( ( dwStyle & LBS_HASSTRINGS ) == 0
  216. && ( dwStyle & (LBS_OWNERDRAWFIXED|LBS_OWNERDRAWVARIABLE) ) != 0
  217. )
  218. return;
  219. pMIS->itemWidth = pMIS->itemHeight = 16;
  220. INT nItemIndex = INT( pMIS->itemID );
  221. if( nItemIndex < 0 || nItemIndex >= INT(GetCount()) )
  222. return;
  223. HFONT hFont = OnLbQueryItemFont( nItemIndex );
  224. ASSERT( hFont != NULL );
  225. CString sMeasure;
  226. GetText( nItemIndex, sMeasure );
  227. if( sMeasure.IsEmpty() )
  228. return;
  229. CWindowDC dc( NULL );
  230. CExtSafeString _sMeasure;
  231. _sMeasure = sMeasure;
  232. CRect rcMeasure = CExtPaintManager::stat_CalcTextDimension( dc, * CFont::FromHandle(hFont), _sMeasure, DT_SINGLELINE|DT_LEFT|DT_NOPREFIX );
  233. INT nWidth = rcMeasure.Width();
  234. INT nHeight = rcMeasure.Height();
  235. pMIS->itemWidth = nWidth;
  236. pMIS->itemHeight = max( nHeight, (INT)pMIS->itemHeight );
  237. CSize sizeLbItemExtra = OnLbQueryItemExtraSize( nItemIndex );
  238. pMIS->itemWidth += sizeLbItemExtra.cx * 2;
  239. pMIS->itemHeight += sizeLbItemExtra.cy * 2;
  240. }
  241. int CListBoxCustomPainted::CompareItem( LPCOMPAREITEMSTRUCT pCIS )
  242. {
  243. ASSERT_VALID( this );
  244. ASSERT( pCIS != NULL );
  245. DWORD dwStyle = GetStyle();
  246. if( ( dwStyle & LBS_HASSTRINGS ) == 0
  247. && ( dwStyle & (LBS_OWNERDRAWFIXED|LBS_OWNERDRAWVARIABLE) ) != 0
  248. )
  249. return 0;
  250. CString sText1, sText2;
  251. GetText( INT( pCIS->itemID1 ), sText1 );
  252. GetText( INT( pCIS->itemID2 ), sText2 );
  253. INT nRetVal = m_bCaseSensitiveSort ? sText1.Compare( LPCTSTR(sText2) ) : sText1.CompareNoCase( LPCTSTR(sText2) );
  254. return nRetVal;
  255. }
  256. void CListBoxCustomPainted::DeleteItem( LPDELETEITEMSTRUCT pDIS )
  257. {
  258. ASSERT_VALID( this );
  259. ASSERT( pDIS != NULL );
  260. CListBox::DeleteItem( pDIS );
  261. }
  262. int CListBoxCustomPainted::VKeyToItem( UINT nKey, UINT nIndex )
  263. {
  264. ASSERT_VALID( this );
  265. return CListBox::VKeyToItem( nKey, nIndex );
  266. }
  267. int CListBoxCustomPainted::CharToItem( UINT nKey, UINT nIndex )
  268. {
  269. ASSERT_VALID( this );
  270. return CListBox::CharToItem( nKey, nIndex );
  271. }
  272. void CListBoxCustomPainted::OnLbnReflectSelCancel() 
  273. {
  274. ASSERT_VALID( this );
  275. _RedrawLB();
  276. }
  277. void CListBoxCustomPainted::OnLbnReflectKillFocus() 
  278. {
  279. ASSERT_VALID( this );
  280. _RedrawLB();
  281. }
  282. void CListBoxCustomPainted::OnLbnReflectSetFocus() 
  283. {
  284. ASSERT_VALID( this );
  285. _RedrawLB();
  286. }
  287. /////////////////////////////////////////////////////////////////////////////
  288. // CListBoxMenuLike window
  289. CListBoxMenuLike::CListBoxMenuLike()
  290. {
  291. }
  292. CListBoxMenuLike::~CListBoxMenuLike()
  293. {
  294. RemoveAllIcons();
  295. }
  296. BEGIN_MESSAGE_MAP( CListBoxMenuLike, CListBoxCustomPainted )
  297. //{{AFX_MSG_MAP(CListBoxMenuLike)
  298. ON_CONTROL_REFLECT(LBN_SELCANCEL, OnSelcancel)
  299. ON_CONTROL_REFLECT(LBN_KILLFOCUS, OnKillfocus)
  300. ON_CONTROL_REFLECT(LBN_SETFOCUS, OnSetfocus)
  301. //}}AFX_MSG_MAP
  302. END_MESSAGE_MAP()
  303. /////////////////////////////////////////////////////////////////////////////
  304. // CListBoxMenuLike message handlers
  305. void CListBoxMenuLike::DrawItem( LPDRAWITEMSTRUCT pDIS ) 
  306. {
  307. ASSERT_VALID( this );
  308. ASSERT( pDIS != NULL );
  309. ASSERT( pDIS->hDC != NULL );
  310. if( ((INT)pDIS->itemID) < 0 )
  311. return;
  312. CDC * pDC = CDC::FromHandle( pDIS->hDC );
  313. CRect rcItem = pDIS->rcItem;
  314. if( ( pDIS->itemState & ( ODS_SELECTED | ODS_FOCUS ) ) != 0 )
  315. {
  316. CRect rcErase( rcItem );
  317. if( INT(pDIS->itemID) == (GetCount()-1) )
  318. {
  319. CRect rcClient;
  320. GetClientRect( &rcClient );
  321. if( rcErase.bottom < rcClient.bottom )
  322. rcErase.bottom = rcClient.bottom;
  323. }
  324. pDC->FillSolidRect( rcErase, g_PaintManager->GetColor( COLOR_WINDOW, (CObject*)this ) );
  325. CRect rcBottomArea( rcErase );
  326. rcBottomArea.top = rcItem.bottom;
  327. CExtPaintManager::PAINTMENUITEMDATA _pmid(
  328. NULL,
  329. rcBottomArea,
  330. rcBottomArea,
  331. GetIconAreaWidth(),
  332. _T(""),
  333. _T(""),
  334. NULL,
  335. false,
  336. false,
  337. false,
  338. false,
  339. false,
  340. true,
  341. false,
  342. false,
  343. false,
  344. 0,
  345. NULL
  346. );
  347. g_PaintManager->PaintMenuItem( *pDC, _pmid );
  348. }
  349. INT nIconAreaWidth = GetIconAreaWidth();
  350. m_arrItems[ pDIS->itemID ] -> DrawItem( nIconAreaWidth, pDIS );
  351. if( ( pDIS->itemState & ODS_SELECTED ) != 0
  352. && OnLbQueryWindowFocusedState()
  353. )
  354. {
  355. CRect rcFocus = rcItem;
  356. rcFocus.left += nIconAreaWidth;
  357. rcFocus.DeflateRect( 3, 3 );
  358. pDC->DrawFocusRect( &rcFocus );
  359. }
  360. }
  361. void CListBoxMenuLike::MeasureItem( LPMEASUREITEMSTRUCT pMIS ) 
  362. {
  363. ASSERT_VALID( this );
  364. ASSERT( pMIS != NULL );
  365. ASSERT( ((INT)pMIS->itemID) >= 0 );
  366. CRect rcClient;
  367. GetClientRect( &rcClient );
  368. CSize _sizeClientArea = rcClient.Size();
  369. m_arrItems[ pMIS->itemID ] -> MeasureItem( pMIS, _sizeClientArea );
  370. }
  371. void CListBoxMenuLike::OnSelcancel() 
  372. {
  373. _Invalidate();
  374. }
  375. void CListBoxMenuLike::OnKillfocus() 
  376. {
  377. _Invalidate();
  378. }
  379. void CListBoxMenuLike::OnSetfocus() 
  380. {
  381. _Invalidate();
  382. }
  383. void CListBoxMenuLike::ITEM_DATA::DrawItem(INT nIconAreaWidth, LPDRAWITEMSTRUCT pDIS)
  384. {
  385. CRect rcItem = pDIS->rcItem;
  386. CDC dcTmp;
  387. dcTmp.Attach( pDIS->hDC );
  388. CExtMemoryDC dc( &dcTmp, &rcItem );
  389. bool bSelected = (pDIS->itemState & ODS_SELECTED) != 0;
  390. CExtPaintManager::PAINTMENUITEMDATA _pmid(
  391. NULL,
  392. rcItem,
  393. rcItem,
  394. nIconAreaWidth,
  395. LPCTSTR(m_strText), // _T(""),
  396. _T(""),
  397. &m_icon,
  398. false,
  399. bSelected,
  400. false,
  401. false,
  402. false,
  403. true,
  404. false,
  405. false,
  406. false,
  407. 0,
  408. NULL
  409. );
  410. g_PaintManager->PaintMenuItem( dc, _pmid );
  411. dc.__Flush();
  412. dcTmp.Detach();
  413. }
  414. void CListBoxMenuLike::ITEM_DATA::MeasureItem(
  415. LPMEASUREITEMSTRUCT pMIS,
  416. CSize _sizeClientArea
  417. {
  418. CSize _sizeIcon = GetSize();
  419. pMIS->itemWidth = _sizeClientArea.cx;
  420. pMIS->itemHeight = _sizeIcon.cy;
  421. CWindowDC dcDesktop( NULL );
  422. CRect rcText( 0, 0, _sizeClientArea.cx, 0 );
  423. CFont * pOldFont = dcDesktop.SelectObject( &g_PaintManager->m_FontNormal );
  424. UINT nTextHeight = (UINT) dcDesktop.DrawText( m_strText, &rcText, DT_LEFT|DT_TOP|DT_CALCRECT );
  425. dcDesktop.SelectObject( pOldFont );
  426. pMIS->itemHeight = max( nTextHeight, pMIS->itemHeight );
  427. // vertical gaps
  428. pMIS->itemHeight += 8;
  429. rcText = CalcTextRect( CRect( 0, 0, pMIS->itemWidth, pMIS->itemHeight ), _sizeIcon );
  430. }
  431. bool CListBoxMenuLike::OnLbEraseEntire( CDC & dc, CRect rcClient )
  432. {
  433. ASSERT_VALID( this );
  434. ASSERT( dc.GetSafeHdc() != NULL );
  435. CExtPaintManager::PAINTMENUITEMDATA _pmid(
  436. NULL,
  437. rcClient,
  438. rcClient,
  439. GetIconAreaWidth(),
  440. _T(""),
  441. _T(""),
  442. NULL,
  443. false,
  444. false,
  445. false,
  446. false,
  447. false,
  448. true,
  449. false,
  450. false,
  451. false,
  452. 0,
  453. NULL
  454. );
  455. g_PaintManager->PaintMenuItem( dc, _pmid );
  456. return false;
  457. }