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

界面编程

开发平台:

Visual C++

  1. // This is part of the Professional User Interface Suite library.
  2. // Copyright (C) 2001-2009 FOSS Software, Inc.
  3. // All rights reserved.
  4. //
  5. // http://www.prof-uis.com
  6. // mailto:support@prof-uis.com
  7. //
  8. // This source code can be used, modified and redistributed
  9. // under the terms of the license agreement that is included
  10. // in the Professional User Interface Suite package.
  11. //
  12. // Warranties and Disclaimers:
  13. // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
  14. // INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  16. // IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
  17. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
  18. // INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
  19. // INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
  20. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  21. #include "stdafx.h"
  22. #if (!defined __EXT_MFC_NO_CHECK_LIST)
  23. #if (!defined __EXT_CHECK_LIST_H)
  24. #include <ExtCheckListWnd.h>
  25. #endif // (!defined __EXT_CHECK_LIST_H)
  26. #if (!defined __EXT_PAINT_MANAGER_H)
  27. #include <ExtPaintManager.h>
  28. #endif
  29. #if (! defined __VSSYM32_H__)
  30. #include <vssym32/vssym32.h>
  31. #endif // (! defined __VSSYM32_H__)
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CExtCheckListWnd
  39. IMPLEMENT_DYNAMIC( CExtCheckListWnd, CListBox );
  40. IMPLEMENT_CExtPmBridge_MEMBERS( CExtCheckListWnd );
  41. CExtCheckListWnd::CExtCheckListWnd()
  42. : m_nStyle( BS_CHECKBOX )
  43. , m_bUsePM( true )
  44. {
  45. PmBridge_Install();
  46. }
  47. CExtCheckListWnd::~CExtCheckListWnd()
  48. {
  49. PmBridge_Uninstall();
  50. }
  51. BEGIN_MESSAGE_MAP(CExtCheckListWnd, CListBox)
  52. //{{AFX_MSG_MAP(CExtCheckListWnd)
  53. ON_WM_LBUTTONDOWN()
  54. ON_WM_LBUTTONDBLCLK()
  55. ON_WM_KEYDOWN()
  56. ON_MESSAGE(LB_ADDSTRING, OnLBAddString)
  57. ON_MESSAGE(LB_FINDSTRING, OnLBFindString)
  58. ON_MESSAGE(LB_FINDSTRINGEXACT, OnLBFindStringExact)
  59. ON_MESSAGE(LB_GETITEMDATA, OnLBGetItemData)
  60. ON_MESSAGE(LB_GETTEXT, OnLBGetText)
  61. ON_MESSAGE(LB_INSERTSTRING, OnLBInsertString)
  62. ON_MESSAGE(LB_SELECTSTRING, OnLBSelectString)
  63. ON_MESSAGE(LB_SETITEMDATA, OnLBSetItemData)
  64. //}}AFX_MSG_MAP
  65. END_MESSAGE_MAP()
  66. void CExtCheckListWnd::SetCheckStyle(
  67. DWORD nStyle
  68. )
  69. {
  70. ASSERT(
  71. nStyle == BS_CHECKBOX 
  72. || nStyle == BS_AUTOCHECKBOX 
  73. || nStyle == BS_AUTO3STATE 
  74. || nStyle == BS_3STATE
  75. || nStyle == BS_AUTORADIOBUTTON 
  76. || nStyle == BS_RADIOBUTTON
  77. );
  78. m_nStyle = nStyle;
  79. }
  80. void CExtCheckListWnd::SetCheck(
  81. INT nIndex, 
  82. INT nCheck
  83. )
  84. {
  85. ASSERT_VALID( this );
  86. if( nCheck == 2 
  87. && m_nStyle != BS_3STATE
  88. && m_nStyle != BS_AUTO3STATE
  89. )
  90. return;
  91. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, nIndex, 0 );
  92. if( lResult != LB_ERR )
  93. {
  94. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lResult;
  95. if( pState == NULL )
  96. pState = new EXT_ITEM_DATA;
  97. pState->m_nCheck = nCheck;
  98. VERIFY( DefWindowProc( LB_SETITEMDATA, nIndex, (LPARAM)pState ) != LB_ERR );
  99. Invalidate();
  100. }
  101. }
  102. INT CExtCheckListWnd::GetCheck(
  103. INT nIndex
  104. )
  105. {
  106. ASSERT_VALID( this );
  107. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, nIndex, 0 );
  108. if( lResult != LB_ERR )
  109. {
  110. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lResult;
  111. if( pState != NULL )
  112. return pState->m_nCheck;
  113. }
  114. return 0;
  115. }
  116. void CExtCheckListWnd::Enable(
  117. INT nIndex, 
  118. BOOL bEnabled
  119. )
  120. {
  121. ASSERT_VALID( this );
  122. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, nIndex, 0 );
  123. if( lResult != LB_ERR )
  124. {
  125. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lResult;
  126. if( pState == NULL )
  127. pState = new EXT_ITEM_DATA;
  128. pState->m_bEnabled = bEnabled;
  129. VERIFY( DefWindowProc( LB_SETITEMDATA, nIndex, (LPARAM)pState) != LB_ERR );
  130. Invalidate();
  131. }
  132. }
  133. BOOL CExtCheckListWnd::IsEnabled(
  134. INT nIndex
  135. )
  136. {
  137. ASSERT_VALID( this );
  138. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, nIndex, 0 );
  139. if( lResult != LB_ERR )
  140. {
  141. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lResult;
  142. if( pState != NULL )
  143. return pState->m_bEnabled;
  144. }
  145. return TRUE;
  146. }
  147. //////////////////////////////////////////////////////////////////////////
  148. CRect CExtCheckListWnd::OnQueryItemMargins( 
  149. INT nIndex 
  150. ) const
  151. {
  152. ASSERT_VALID( this );
  153. if( !(nIndex >= 0 && nIndex < GetCount()) )
  154. {
  155. ASSERT( FALSE );
  156. return CRect( 0, 0, 0, 0 );
  157. }
  158. return CRect( 2, 1, 2, 1 );
  159. }
  160. CRect CExtCheckListWnd::OnQueryItemCheckMargins( 
  161. INT nIndex 
  162. ) const
  163. {
  164. ASSERT_VALID( this );
  165. if( !(nIndex >= 0 && nIndex < GetCount()) )
  166. {
  167. ASSERT( FALSE );
  168. return CRect( 0, 0, 0, 0 );
  169. }
  170. return CRect( 1, 0, 2, 0 );
  171. }
  172. HFONT CExtCheckListWnd::OnQueryItemFont( 
  173. INT nIndex 
  174. ) const
  175. {
  176. ASSERT_VALID( this );
  177. if( !(nIndex >= 0 && nIndex < GetCount()) )
  178. {
  179. ASSERT( FALSE );
  180. return NULL;
  181. }
  182. HFONT hFont = (HFONT)
  183. ::SendMessage( m_hWnd, WM_GETFONT, 0L, 0L );
  184. if( hFont == NULL )
  185. {
  186. HWND hWndParent = ::GetParent( m_hWnd );
  187. if( hWndParent != NULL )
  188. hFont = (HFONT)
  189. ::SendMessage( hWndParent, WM_GETFONT, 0L, 0L );
  190. } // if( hFont == NULL )
  191. if( hFont == NULL )
  192. {
  193. hFont = (HFONT)::GetStockObject( DEFAULT_GUI_FONT );
  194. if( hFont == NULL )
  195. hFont = (HFONT)::GetStockObject( SYSTEM_FONT );
  196. } // if( hFont == NULL )
  197. return hFont;
  198. }
  199. CSize CExtCheckListWnd::OnQueryItemCheckSize( 
  200. CDC & dc, 
  201. INT nIndex 
  202. )
  203. {
  204. ASSERT_VALID( this );
  205. ASSERT( nIndex >= 0 && nIndex < GetCount() );
  206. if( m_bUsePM )
  207. {
  208. CExtPaintManager * pPM = PmBridge_GetPM();
  209. bool bPushed = false, bEnabled = true;
  210. CExtPaintManager::eBoxState_t eState = CExtPaintManager::BOX_UNCHECKED;
  211. CRect rcCheck( 0, 0, 13, 13 );
  212. CExtPaintManager::PAINTCHECKRADIOBUTTONDATA _pcrbd(
  213. this,
  214. eState,
  215. false,
  216. false,
  217. rcCheck,
  218. _T(""),
  219. false,
  220. bPushed,
  221. bEnabled,
  222. false, 
  223. 0,
  224. (HFONT)pPM->m_FontNormal.GetSafeHandle(),
  225. true
  226. );
  227. return pPM->GetCheckButtonBoxSize( dc, _pcrbd );
  228. } // if( m_bUsePM )
  229. if( g_PaintManager.m_UxTheme.IsControlsThemed()
  230. && g_PaintManager.m_UxTheme.OpenThemeData( GetSafeHwnd(), L"BUTTON" ) != NULL
  231. )
  232. {
  233. INT nCheck = GetCheck( nIndex );
  234. BOOL bDisabled = (!IsEnabled( nIndex ));
  235. INT nState = 0;
  236. INT nPartID = 0;
  237. switch( m_nStyle )
  238. {
  239. case BS_CHECKBOX:
  240. case BS_AUTOCHECKBOX:
  241. case BS_3STATE:
  242. case BS_AUTO3STATE:
  243. {
  244. nPartID = BP_CHECKBOX;
  245. if( nCheck > 0 )
  246. {
  247. nState = 
  248. bDisabled 
  249. ? ( nCheck == 2 ? CBS_MIXEDDISABLED : CBS_CHECKEDDISABLED ) 
  250. : ( nCheck == 2 ? CBS_MIXEDNORMAL : CBS_CHECKEDNORMAL );
  251. }
  252. else
  253. {
  254. nState = 
  255. bDisabled 
  256. ? CBS_UNCHECKEDDISABLED 
  257. : CBS_UNCHECKEDNORMAL;
  258. }
  259. }
  260. break;
  261. case BS_RADIOBUTTON:
  262. case BS_AUTORADIOBUTTON:
  263. {
  264. nPartID = BP_RADIOBUTTON;
  265. if( nCheck > 0 )
  266. {
  267. nState = 
  268. bDisabled 
  269. ? RBS_CHECKEDDISABLED
  270. : RBS_CHECKEDNORMAL;
  271. }
  272. else
  273. {
  274. nState = 
  275. bDisabled 
  276. ? RBS_UNCHECKEDDISABLED 
  277. : RBS_UNCHECKEDNORMAL;
  278. }
  279. }
  280. break;
  281. default:
  282. ASSERT( FALSE );
  283. } // switch( m_nStyle )
  284. CSize szPart(0,0);
  285. if( g_PaintManager.m_UxTheme.GetThemePartSize(
  286. dc.GetSafeHdc(), 
  287. nPartID, 
  288. nState, 
  289. NULL, 
  290. CExtUxTheme::__EXT_UX_TS_TRUE, 
  291. &szPart
  292. ) != S_OK
  293. )
  294. szPart = CSize( 0, 0 );
  295. g_PaintManager.m_UxTheme.CloseThemeData( true );
  296. if( szPart != CSize( 0, 0 ) )
  297. return szPart;
  298. }
  299. return CSize( 13, 13 );
  300. }
  301. //////////////////////////////////////////////////////////////////////////
  302. void CExtCheckListWnd::OnPaintItemCheck(
  303. CDC & dc,
  304. const RECT & rcCheck,
  305. INT nIndex
  306. )
  307. {
  308. ASSERT_VALID( this );
  309. ASSERT( dc.GetSafeHdc() != NULL );
  310. if( ! dc.RectVisible(&rcCheck) )
  311. return;
  312. ASSERT( nIndex >= 0 && nIndex < GetCount() );
  313. INT nCheck = GetCheck( nIndex );
  314. BOOL bDisabled = (!IsEnabled( nIndex ));
  315. if( m_bUsePM )
  316. {
  317. bool bPushed = false, bHover = false, bPushTracking = false, bKeyTracking = false, bEnabled = bDisabled ? false : true;
  318. CExtPaintManager::eBoxState_t eState = CExtPaintManager::BOX_UNCHECKED;
  319. switch( nCheck ) 
  320. {
  321. case BST_UNCHECKED:
  322. if( bEnabled )
  323. {
  324. if( ( bHover && !bPushTracking) 
  325. ||  (!bHover &&  bPushTracking && !bKeyTracking) 
  326. )
  327. eState = CExtPaintManager::BOX_MOUSE_HOVER_UNCHECKED;
  328. else if( (bHover && bPushTracking) || bKeyTracking )
  329. eState = CExtPaintManager::BOX_LDOWN_UNCHECKED;
  330. else
  331. eState = CExtPaintManager::BOX_UNCHECKED;
  332. }
  333. else
  334. eState = CExtPaintManager::BOX_DISABLED_UNCHECKED;
  335. break;
  336. case BST_CHECKED:
  337. if( bEnabled )
  338. {
  339. if( ( bHover && !bPushTracking) 
  340. ||  (!bHover &&  bPushTracking && !bKeyTracking) 
  341. )
  342. eState = CExtPaintManager::BOX_MOUSE_HOVER_CHECKED;
  343. else if( (bHover && bPushTracking) || bKeyTracking )
  344. eState = CExtPaintManager::BOX_LDOWN_CHECKED;
  345. else
  346. eState = CExtPaintManager::BOX_CHECKED;
  347. }
  348. else
  349. eState = CExtPaintManager::BOX_DISABLED_CHECKED;
  350. break;
  351. case BST_INDETERMINATE:
  352. if( bEnabled )
  353. {
  354. if( ( bHover && !bPushTracking) 
  355. ||  (!bHover &&  bPushTracking && !bKeyTracking ) 
  356. )
  357. eState = CExtPaintManager::BOX_MOUSE_HOVER_INDETERMINATE;
  358. else if( (bHover && bPushTracking) || bKeyTracking )
  359. eState = CExtPaintManager::BOX_LDOWN_INDETERMINATE;
  360. else
  361. eState = CExtPaintManager::BOX_INDETERMINATE;
  362. }
  363. else
  364. eState = CExtPaintManager::BOX_DISABLED_INDETERMINATE;
  365. break;
  366. }
  367. CExtPaintManager * pPM = PmBridge_GetPM();
  368. CExtPaintManager::PAINTCHECKRADIOBUTTONDATA _pcrbd(
  369. this,
  370. eState,
  371. false,
  372. false,
  373. rcCheck,
  374. _T(""),
  375. false,
  376. bPushed,
  377. bEnabled,
  378. false, 
  379. 0,
  380. (HFONT)pPM->m_FontNormal.GetSafeHandle(),
  381. true
  382. );
  383. //  _pcrbd.m_rcTextMargins.SetRect(0,0,0,0);
  384. //  _pcrbd.m_clrForceBk = GetBkColor();
  385. //  _pcrbd.m_clrForceTextDisabled = GetTextColorDisabled();
  386. //  _pcrbd.m_clrForceTextNormal = GetTextColorNormal();
  387. //  _pcrbd.m_clrForceTextHover = GetTextColorHover();
  388. //  _pcrbd.m_clrForceTextPressed = GetTextColorPressed();
  389. pPM->PaintCheckButton( dc, _pcrbd );
  390. return;
  391. } // if( m_bUsePM )
  392. bool bDefaultDrawing = true;
  393. if( g_PaintManager.m_UxTheme.IsControlsThemed()
  394. && g_PaintManager.m_UxTheme.OpenThemeData( GetSafeHwnd(), L"BUTTON" ) != NULL
  395. )
  396. {
  397. INT nState = 0;
  398. INT nPartID = 0;
  399. switch( m_nStyle )
  400. {
  401. case BS_CHECKBOX:
  402. case BS_AUTOCHECKBOX:
  403. case BS_3STATE:
  404. case BS_AUTO3STATE:
  405. {
  406. nPartID = BP_CHECKBOX;
  407. if( nCheck > 0 )
  408. {
  409. nState = 
  410. bDisabled 
  411. ? ( nCheck == 2 ? CBS_MIXEDDISABLED : CBS_CHECKEDDISABLED ) 
  412. : ( nCheck == 2 ? CBS_MIXEDNORMAL : CBS_CHECKEDNORMAL );
  413. }
  414. else
  415. {
  416. nState = 
  417. bDisabled 
  418. ? CBS_UNCHECKEDDISABLED 
  419. : CBS_UNCHECKEDNORMAL;
  420. }
  421. }
  422. break;
  423. case BS_RADIOBUTTON:
  424. case BS_AUTORADIOBUTTON:
  425. {
  426. nPartID = BP_RADIOBUTTON;
  427. if( nCheck > 0 )
  428. {
  429. nState = 
  430. bDisabled 
  431. ? RBS_CHECKEDDISABLED
  432. : RBS_CHECKEDNORMAL;
  433. }
  434. else
  435. {
  436. nState = 
  437. bDisabled 
  438. ? RBS_UNCHECKEDDISABLED 
  439. : RBS_UNCHECKEDNORMAL;
  440. }
  441. }
  442. break;
  443. default:
  444. ASSERT( FALSE );
  445. return;
  446. } // switch( m_nStyle )
  447. if( g_PaintManager.m_UxTheme.
  448. DrawThemeBackground(
  449. dc.GetSafeHdc(), 
  450. nPartID, 
  451. nState, 
  452. &rcCheck,
  453. &rcCheck
  454. ) == S_OK
  455. )
  456. bDefaultDrawing = false;
  457. g_PaintManager.m_UxTheme.CloseThemeData( true );
  458. }
  459. if( bDefaultDrawing )
  460. {
  461. UINT nState = 0;
  462. switch( m_nStyle )
  463. {
  464. case BS_CHECKBOX:
  465. case BS_AUTOCHECKBOX:
  466. nState |= DFCS_BUTTONCHECK;
  467. break;
  468. case BS_RADIOBUTTON:
  469. case BS_AUTORADIOBUTTON:
  470. nState |= DFCS_BUTTONRADIO;
  471. break;
  472. case BS_3STATE:
  473. case BS_AUTO3STATE:
  474. nState |= DFCS_BUTTONCHECK;
  475. if( nCheck == 2 )
  476. nState |= DFCS_BUTTON3STATE;
  477. break;
  478. default:
  479. ASSERT( FALSE );
  480. break;
  481. }; // switch( m_nStyle )
  482. if( nCheck > 0 )
  483. nState |= DFCS_CHECKED;
  484. if( bDisabled )
  485. nState |= DFCS_INACTIVE;
  486. dc.DrawFrameControl(
  487. (RECT *)&rcCheck,
  488. DFC_BUTTON,
  489. nState //| DFCS_FLAT
  490. );
  491. } // if( bDefaultDrawing )
  492. }
  493. /////////////////////////////////////////////////////////////////////////////
  494. // CExtCheckListWnd message handlers
  495. void CExtCheckListWnd::PreSubclassWindow() 
  496. {
  497. CListBox::PreSubclassWindow();
  498. DWORD dwStyle = GetStyle();
  499. ASSERT( (dwStyle & LBS_OWNERDRAWFIXED) != 0 || (dwStyle & LBS_OWNERDRAWVARIABLE) != 0 );
  500. }
  501. BOOL CExtCheckListWnd::PreCreateWindow( CREATESTRUCT& cs ) 
  502. {
  503. if( ! CListBox::PreCreateWindow(cs) )
  504. return FALSE;
  505. if( (cs.style & LBS_OWNERDRAWVARIABLE) == 0 )
  506. cs.style |= LBS_OWNERDRAWVARIABLE;
  507. if( (cs.style & LBS_HASSTRINGS) == 0 )
  508. cs.style |= LBS_HASSTRINGS;
  509. return TRUE;
  510. }
  511. void CExtCheckListWnd::DrawItem( LPDRAWITEMSTRUCT lpDIS ) 
  512. {
  513. ASSERT_VALID( this );
  514. ASSERT( lpDIS != NULL && lpDIS->hDC != NULL );
  515. DWORD dwStyle = GetStyle();
  516. INT nItem = (INT)lpDIS->itemID;
  517. if( nItem < 0 || nItem >= GetCount() )
  518. return;
  519. CRect rcItem( lpDIS->rcItem );
  520. CDC dc;
  521. dc.Attach( lpDIS->hDC );
  522. if( lpDIS->itemAction & (ODA_DRAWENTIRE | ODA_SELECT) )
  523. {
  524. CRect rcErase( lpDIS->rcItem );
  525. if( nItem == (GetCount() - 1) )
  526. {
  527. CRect rcClient;
  528. GetClientRect( &rcClient );
  529. if( rcErase.bottom < rcClient.bottom )
  530. rcErase.bottom = rcClient.bottom;
  531. }
  532. dc.FillSolidRect(
  533. rcErase, 
  534. PmBridge_GetPM()->GetColor( COLOR_WINDOW, this )
  535. );
  536. }
  537. CSize szCheck = OnQueryItemCheckSize( dc, nItem );
  538. ASSERT( szCheck.cx >= 0 && szCheck.cy >= 0 );
  539. CRect rcCheck( rcItem );
  540. rcCheck.right = rcCheck.left + szCheck.cx;
  541. CRect rcCheckMargins = OnQueryItemCheckMargins( nItem );
  542. rcCheck.OffsetRect( rcCheckMargins.TopLeft() );
  543. rcCheck.right += rcCheckMargins.right;
  544. rcCheck.bottom += rcCheckMargins.bottom;
  545. rcItem.left = rcCheck.right;
  546. rcCheck.DeflateRect( 0, (rcCheck.Height() - szCheck.cy) / 2 );
  547. OnPaintItemCheck( dc, rcCheck, nItem );
  548. if( (GetStyle() & LBS_HASSTRINGS) != 0 && nItem >= 0 )
  549. {
  550. CString sText;
  551. GetText( nItem, sText );
  552. if( ! sText.IsEmpty() )
  553. {
  554. HFONT hFont = OnQueryItemFont( nItem );
  555. ASSERT( hFont != NULL );
  556. CFont * pOldFont =
  557. dc.SelectObject( CFont::FromHandle( hFont ) );
  558. COLORREF clrTextOld =
  559. dc.SetTextColor(
  560. PmBridge_GetPM()->GetColor(
  561. ( (lpDIS->itemState & ODS_SELECTED) != 0 && (dwStyle & LBS_NOSEL) == 0 )
  562. ? COLOR_HIGHLIGHTTEXT
  563. : COLOR_BTNTEXT,
  564. this
  565. )
  566. );
  567. /////////////////////////////////////////////////////////////////////////////////////
  568. // Blurry text problem fix problem reported by Scott Sanders
  569. // OLD CODE: int nOldBkMode = dc.SetBkMode( TRANSPARENT );
  570. bool bSelMode = false;
  571. if( ( lpDIS->itemState & ODS_SELECTED ) != 0 
  572. && (dwStyle & LBS_NOSEL) == 0 
  573. )
  574. bSelMode = true;
  575. int nOldBkMode = dc.SetBkMode( OPAQUE );
  576. dc.SetBkColor ( PmBridge_GetPM()->GetColor( bSelMode ? COLOR_HIGHLIGHT : COLOR_WINDOW, this ) );
  577. /////////////////////////////////////////////////////////////////////////////////////
  578. CRect rcText( rcItem );
  579. UINT nFormat = 
  580. DT_SINGLELINE
  581. | DT_LEFT
  582. | DT_NOPREFIX
  583. ;
  584. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  585. nFormat |= DT_EXPANDTABS;
  586. CRect rcMeasureText(0,0,0,0);
  587. dc.DrawText(
  588. sText, 
  589. sText.GetLength(),
  590. rcMeasureText,
  591. (nFormat|DT_CALCRECT)
  592. );
  593. rcText.DeflateRect( 
  594. 0,
  595. (rcText.Height() - rcMeasureText.Height()) / 2 
  596. );
  597. CRect rcMargins = OnQueryItemMargins( nItem );
  598. rcText.OffsetRect( rcMargins.left, 0 );
  599. if( bSelMode )
  600. dc.FillSolidRect(
  601. &rcItem,
  602. PmBridge_GetPM()->GetColor( COLOR_HIGHLIGHT, this )
  603. );
  604. dc.DrawText(
  605. sText,
  606. &rcText,
  607. nFormat
  608. );
  609. dc.SetBkMode( nOldBkMode );
  610. dc.SetTextColor( clrTextOld );
  611. if( ( lpDIS->itemState & ODS_SELECTED ) != 0 
  612. && (dwStyle & LBS_NOSEL) == 0 
  613. )
  614. {
  615. COLORREF clrTextOld = 
  616. dc.SetTextColor( RGB(255,255,255) );
  617. COLORREF clrBkOld =
  618. dc.SetBkColor( RGB(0,0,0) );
  619. dc.DrawFocusRect( &rcItem );
  620. dc.SetBkColor( clrBkOld );
  621. dc.SetTextColor( clrTextOld );
  622. }
  623. dc.SelectObject( pOldFont );
  624. } // if( ! sText.IsEmpty() )
  625. } // if( nItem >= 0 )
  626. dc.Detach();
  627. }
  628. void CExtCheckListWnd::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) 
  629. {
  630. ASSERT_VALID( this );
  631. ASSERT( lpMIS != NULL );
  632. INT nItem = (INT)lpMIS->itemID;
  633. if( nItem < 0 || nItem >= GetCount() )
  634. return;
  635. lpMIS->itemWidth = 0; 
  636. lpMIS->itemHeight = 15;
  637. CWindowDC dc( this );
  638. if( (GetStyle() & LBS_HASSTRINGS) != 0
  639. && nItem >= 0 
  640. )
  641. {
  642. CString sText;
  643. GetText( nItem, sText );
  644. if( ! sText.IsEmpty() )
  645. {
  646. HFONT hFont = OnQueryItemFont( nItem );
  647. ASSERT( hFont != NULL );
  648. UINT nFormat = 
  649. DT_SINGLELINE
  650. | DT_LEFT
  651. | DT_NOPREFIX
  652. ;
  653. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  654. nFormat |= DT_EXPANDTABS;
  655. CRect rcMeasure =
  656. CExtPaintManager::stat_CalcTextDimension( 
  657. dc, 
  658. ( * CFont::FromHandle( hFont ) ), 
  659. CExtSafeString(LPCTSTR(sText)),
  660. nFormat
  661. );
  662. lpMIS->itemWidth = rcMeasure.Width();
  663. lpMIS->itemHeight = rcMeasure.Height();
  664. } // if( ! sText.IsEmpty() )
  665. } // if( nItem >= 0 )
  666. CSize szCheck = 
  667. OnQueryItemCheckSize( dc, nItem );
  668. ASSERT( szCheck.cx >= 0 && szCheck.cy >= 0 );
  669. CRect rcCheckMargins = 
  670. OnQueryItemCheckMargins( nItem );
  671. szCheck.cx += (rcCheckMargins.left + rcCheckMargins.right);
  672. szCheck.cy += (rcCheckMargins.top + rcCheckMargins.bottom);
  673. lpMIS->itemWidth += szCheck.cx;
  674. lpMIS->itemHeight = max( UINT(szCheck.cy), lpMIS->itemHeight );
  675. CRect rcMargins = 
  676. OnQueryItemMargins( nItem );
  677. lpMIS->itemWidth += (rcMargins.left + rcMargins.right);
  678. lpMIS->itemHeight += (rcMargins.top + rcMargins.bottom);
  679. }
  680. int CExtCheckListWnd::CompareItem( LPCOMPAREITEMSTRUCT lpCompareItemStruct ) 
  681. {
  682. ASSERT_VALID( this );
  683. COMPAREITEMSTRUCT compareItem;
  684. __EXT_MFC_MEMCPY( 
  685. &compareItem, 
  686. sizeof(COMPAREITEMSTRUCT),
  687. lpCompareItemStruct, 
  688. sizeof(COMPAREITEMSTRUCT) 
  689. );
  690. if( compareItem.itemData1 != 0 
  691. && compareItem.itemData1 != LB_ERR
  692. )
  693. {
  694. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) compareItem.itemData1;
  695. compareItem.itemData1 = pState->m_dwUserData;
  696. }
  697. if( compareItem.itemData2 != 0 
  698. && compareItem.itemData2 != LB_ERR
  699. )
  700. {
  701. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) compareItem.itemData2;
  702. compareItem.itemData2 = pState->m_dwUserData;
  703. }
  704. return CListBox::CompareItem( &compareItem );
  705. }
  706. void CExtCheckListWnd::DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct ) 
  707. {
  708. ASSERT_VALID( this );
  709. DELETEITEMSTRUCT deleteItem;
  710. __EXT_MFC_MEMCPY( 
  711. &deleteItem, 
  712. sizeof(DELETEITEMSTRUCT),
  713. lpDeleteItemStruct, 
  714. sizeof(DELETEITEMSTRUCT) 
  715. );
  716. // WINBUG: The following if block is required because Windows NT
  717. // version 3.51 does not properly fill out the LPDELETEITEMSTRUCT.
  718. if( deleteItem.itemData == 0 )
  719. {
  720. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, deleteItem.itemID, 0 );
  721. if( lResult != LB_ERR )
  722. deleteItem.itemData = (UINT)lResult;
  723. }
  724. if( deleteItem.itemData != 0 
  725. && deleteItem.itemData != LB_ERR
  726. )
  727. {
  728. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) deleteItem.itemData;
  729. deleteItem.itemData = pState->m_dwUserData;
  730. delete pState;
  731. }
  732. CListBox::DeleteItem( &deleteItem );
  733. }
  734. INT CExtCheckListWnd::CheckBoxFromPoint(
  735. CPoint point, 
  736. BOOL & bInCheck
  737. )
  738. {
  739. ASSERT_VALID( this );
  740. bInCheck = FALSE;
  741. INT nIndex = -1;
  742. for( INT nItem = GetTopIndex(); nItem < GetCount(); nItem++ )
  743. {
  744. CRect rcItem;
  745. GetItemRect( nItem, &rcItem );
  746. if( rcItem.PtInRect( point ) )
  747. {
  748. CWindowDC dc( this );
  749. CSize szCheck = 
  750. OnQueryItemCheckSize( dc, nItem );
  751. ASSERT( szCheck.cx >= 0 && szCheck.cy >= 0 );
  752. CRect rcCheckMargins = 
  753. OnQueryItemCheckMargins( nItem );
  754. szCheck.cx += (rcCheckMargins.left + rcCheckMargins.right);
  755. szCheck.cy += (rcCheckMargins.top + rcCheckMargins.bottom);
  756. nIndex = nItem;
  757. if( point.x < rcItem.left + szCheck.cx )
  758. bInCheck = !bInCheck;
  759. break;
  760. }
  761. }
  762. return nIndex;
  763. }
  764. void CExtCheckListWnd::SetSelectionCheck( 
  765. INT nCheck 
  766. )
  767. {
  768. ASSERT_VALID( this );
  769. INT nSelectedItems = GetSelCount();
  770. if( nSelectedItems > 0 )
  771. {
  772. LPINT pnSelectedItems = new INT[ nSelectedItems * sizeof(INT) ];
  773. GetSelItems( 
  774. nSelectedItems, 
  775. pnSelectedItems 
  776. );
  777. for( INT nSelectedItem = 0; nSelectedItem < nSelectedItems; nSelectedItem++ )
  778. {
  779. if( IsEnabled( pnSelectedItems[ nSelectedItem ] ) )
  780. {
  781. SetCheck( pnSelectedItems[ nSelectedItem ], nCheck );
  782. Invalidate();
  783. }
  784. }
  785. delete pnSelectedItems;
  786. pnSelectedItems = NULL;
  787. }
  788. }
  789. void CExtCheckListWnd::OnLButtonDown( UINT nFlags, CPoint point )
  790. {
  791. ASSERT_VALID( this );
  792. SetFocus();
  793. // determine where the click is
  794. BOOL bInCheck = FALSE;
  795. INT nIndex = CheckBoxFromPoint( point, bInCheck );
  796. // toggle the check mark automatically if the check mark was hit
  797. if( bInCheck 
  798. && IsEnabled( nIndex )
  799. )
  800. {
  801. CWnd * pParent = GetParent();
  802. ASSERT_VALID( pParent );
  803. INT nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
  804. INT nCheck = GetCheck( nIndex );
  805. nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
  806. INT nNewCheck = (nCheck + 1) % nModulo;
  807. SetCheck( nIndex, nNewCheck );
  808. Invalidate();
  809. if( ( GetStyle() & (LBS_EXTENDEDSEL|LBS_MULTIPLESEL) ) != 0
  810. && GetSel( nIndex ) > 0
  811. )
  812. {
  813. // The listbox is a multi-select listbox, and the user clicked on
  814. // a selected check, so change the check on all of the selected
  815. // items.
  816. SetSelectionCheck( nNewCheck );
  817. }
  818. else
  819. {
  820. CListBox::OnLButtonDown( nFlags, point );
  821. }
  822. // Inform parent of check
  823. pParent->SendMessage( 
  824. WM_COMMAND, 
  825. MAKEWPARAM( GetDlgCtrlID(), CLBN_CHKCHANGE ), 
  826. (LPARAM)m_hWnd 
  827. );
  828. return;
  829. } // if( bInCheck )
  830. // do default listbox selection logic
  831. CListBox::OnLButtonDown( nFlags, point );
  832. }
  833. void CExtCheckListWnd::OnLButtonDblClk( UINT nFlags, CPoint point )
  834. {
  835. ASSERT_VALID( this );
  836. BOOL bInCheck = FALSE;
  837. INT nHitIndex = CheckBoxFromPoint( point, bInCheck );
  838. if( bInCheck )
  839. {
  840. // Double and single clicks act the same on the check box
  841. OnLButtonDown( nFlags, point );
  842. return;
  843. }
  844. if( nHitIndex >= 0 && IsEnabled( nHitIndex ) )
  845. {
  846. CWnd * pParent = GetParent();
  847. ASSERT_VALID( pParent );
  848. INT nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
  849. INT nCheck = GetCheck( nHitIndex );
  850. nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
  851. INT nNewCheck = (nCheck + 1) % nModulo;
  852. SetCheck( nHitIndex, nNewCheck );
  853. Invalidate();
  854. if( ( GetStyle() & (LBS_EXTENDEDSEL|LBS_MULTIPLESEL) ) != 0
  855. && GetSel( nHitIndex ) > 0
  856. )
  857. {
  858. // The listbox is a multi-select listbox, and the user clicked on
  859. // a selected check, so change the check on all of the selected
  860. // items.
  861. SetSelectionCheck( nNewCheck );
  862. }
  863. else
  864. {
  865. CListBox::OnLButtonDblClk( nFlags, point );
  866. }
  867. // Inform parent of check
  868. pParent->SendMessage( 
  869. WM_COMMAND, 
  870. MAKEWPARAM( GetDlgCtrlID(), CLBN_CHKCHANGE ), 
  871. (LPARAM)m_hWnd 
  872. );
  873. return;
  874. } // if( nHitIndex >= 0 && IsEnabled( nHitIndex ) )
  875. CListBox::OnLButtonDblClk( nFlags, point );
  876. }
  877. void CExtCheckListWnd::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  878. {
  879. ASSERT_VALID( this );
  880. if( nChar == VK_SPACE )
  881. {
  882. CWnd * pParent = GetParent();
  883. ASSERT_VALID( pParent );
  884. INT nIndex = GetCaretIndex();
  885. if( nIndex != LB_ERR )
  886. {
  887. if( (GetStyle() & LBS_MULTIPLESEL) != 0 )
  888. {
  889. if( IsEnabled( nIndex ) )
  890. {
  891. BOOL bSelected = GetSel( nIndex ) > 0 ? TRUE : FALSE;
  892. if( bSelected )
  893. {
  894. INT nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
  895. INT nCheck = GetCheck( nIndex );
  896. nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
  897. SetCheck( nIndex, (nCheck + 1) % nModulo );
  898. // Inform of check
  899. pParent->SendMessage(
  900. WM_COMMAND,
  901. MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
  902. (LPARAM)m_hWnd
  903. );
  904. }
  905. SetSel( nIndex, !bSelected );
  906. }
  907. else
  908. SetSel( nIndex, FALSE ); // unselect disabled items
  909. return;
  910. }
  911. else
  912. {
  913. // If there is a selection, the space bar toggles that check,
  914. // all other keys are the same as a standard listbox.
  915. if( IsEnabled( nIndex ) )
  916. {
  917. INT nModulo = (m_nStyle == BS_AUTO3STATE) ? 3 : 2;
  918. INT nCheck = GetCheck(nIndex);
  919. nCheck = (nCheck == nModulo) ? nCheck - 1 : nCheck;
  920. INT nNewCheck = (nCheck + 1) % nModulo;
  921. SetCheck( nIndex, nNewCheck );
  922. Invalidate();
  923. if( (GetStyle() & LBS_EXTENDEDSEL) != 0 )
  924. {
  925. // The listbox is a multi-select listbox, and the user
  926. // clicked on a selected check, so change the check on all
  927. // of the selected items.
  928. SetSelectionCheck( nNewCheck );
  929. }
  930. // Inform of check
  931. pParent->SendMessage(
  932. WM_COMMAND,
  933. MAKEWPARAM(GetDlgCtrlID(), CLBN_CHKCHANGE),
  934. (LPARAM)m_hWnd
  935. );
  936. }
  937. else
  938. SetSel( nIndex, FALSE ); // unselect disabled items
  939. return;
  940. }
  941. } // if( nIndex != LB_ERR )
  942. } // if( nChar == VK_SPACE )
  943. CListBox::OnKeyDown(nChar, nRepCnt, nFlags);
  944. }
  945. LRESULT CExtCheckListWnd::OnLBAddString(WPARAM wParam, LPARAM lParam)
  946. {
  947. ASSERT_VALID( this );
  948. EXT_ITEM_DATA * pState = NULL;
  949. if( (GetStyle() & LBS_HASSTRINGS) == 0 )
  950. {
  951. pState = new EXT_ITEM_DATA;
  952. pState->m_dwUserData = (DWORD)lParam;
  953. lParam = (LPARAM) pState;
  954. }
  955. LRESULT lResult = DefWindowProc( LB_ADDSTRING, wParam, lParam );
  956. if( lResult == LB_ERR 
  957. && pState != NULL 
  958. )
  959. delete pState;
  960. return lResult;
  961. }
  962. LRESULT CExtCheckListWnd::OnLBFindString(WPARAM wParam, LPARAM lParam)
  963. {
  964. ASSERT_VALID( this );
  965. if( (GetStyle() & LBS_HASSTRINGS) != 0 )
  966. return DefWindowProc( LB_FINDSTRING, wParam, lParam );
  967. INT nIndex = (INT)wParam;
  968. if( nIndex == -1 ) 
  969. nIndex = 0;
  970. for( ; nIndex < GetCount(); nIndex++ )
  971. if( (DWORD)lParam == GetItemData( nIndex ) )
  972. return nIndex;
  973. return LB_ERR;
  974. }
  975. LRESULT CExtCheckListWnd::OnLBFindStringExact(WPARAM wParam, LPARAM lParam)
  976. {
  977. if( (GetStyle() & (LBS_HASSTRINGS | LBS_SORT)) != 0 )
  978. return DefWindowProc( LB_FINDSTRINGEXACT, wParam, lParam );
  979. INT nIndex = (INT)wParam;
  980. if( nIndex == -1 ) 
  981. nIndex = 0;
  982. for( ; nIndex < GetCount(); nIndex++ )
  983. if( (DWORD)lParam == GetItemData( nIndex ) )
  984. return nIndex;
  985. return LB_ERR;
  986. }
  987. LRESULT CExtCheckListWnd::OnLBGetItemData(WPARAM wParam, LPARAM lParam)
  988. {
  989. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, wParam, lParam );
  990. if( lResult != LB_ERR )
  991. {
  992. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lResult;
  993. if( pState == NULL )
  994. return 0;
  995. lResult = pState->m_dwUserData;
  996. }
  997. return lResult;
  998. }
  999. LRESULT CExtCheckListWnd::OnLBGetText(WPARAM wParam, LPARAM lParam)
  1000. {
  1001. LRESULT lResult = DefWindowProc( LB_GETTEXT, wParam, lParam);
  1002. if( (GetStyle() & LBS_HASSTRINGS) != 0 )
  1003. return lResult;
  1004. if( lResult != LB_ERR )
  1005. {
  1006. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*) lParam;
  1007. if( pState != NULL )
  1008. lParam = pState->m_dwUserData;
  1009. }
  1010. return lResult;
  1011. }
  1012. LRESULT CExtCheckListWnd::OnLBInsertString(WPARAM wParam, LPARAM lParam)
  1013. {
  1014. EXT_ITEM_DATA * pState = NULL;
  1015. if( (GetStyle() & LBS_HASSTRINGS) == 0 )
  1016. {
  1017. pState = new EXT_ITEM_DATA;
  1018. pState->m_dwUserData = (DWORD)lParam;
  1019. lParam = (LPARAM) pState;
  1020. }
  1021. LRESULT lResult = DefWindowProc( LB_INSERTSTRING, wParam, lParam);
  1022. if( lResult == LB_ERR && pState != NULL )
  1023. delete pState;
  1024. return lResult;
  1025. }
  1026. LRESULT CExtCheckListWnd::OnLBSelectString(WPARAM wParam, LPARAM lParam)
  1027. {
  1028. if( (GetStyle() & LBS_HASSTRINGS) != 0 )
  1029. return DefWindowProc( LB_SELECTSTRING, wParam, lParam );
  1030. INT nIndex = (INT)wParam;
  1031. if( nIndex == -1 ) 
  1032. nIndex = 0;
  1033. for( ; nIndex < GetCount(); nIndex++ )
  1034. if( (DWORD)lParam == GetItemData( nIndex ) )
  1035. {
  1036. SetCurSel( nIndex );
  1037. return nIndex;
  1038. }
  1039. return LB_ERR;
  1040. }
  1041. LRESULT CExtCheckListWnd::OnLBSetItemData(WPARAM wParam, LPARAM lParam)
  1042. {
  1043. LRESULT lResult = DefWindowProc( LB_GETITEMDATA, wParam, 0 );
  1044. if( lResult != LB_ERR )
  1045. {
  1046. EXT_ITEM_DATA * pState = (EXT_ITEM_DATA*)lResult;
  1047. if(pState == NULL)
  1048. pState = new EXT_ITEM_DATA;
  1049. pState->m_dwUserData = (DWORD)lParam;
  1050. lResult = DefWindowProc( LB_SETITEMDATA, wParam, (LPARAM) pState );
  1051. if( lResult == LB_ERR )
  1052. delete pState;
  1053. }
  1054. return lResult;
  1055. }
  1056. #endif // (!defined __EXT_MFC_NO_CHECK_LIST)