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

界面编程

开发平台:

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_COMBO_BOX_H)
  23. #include <ExtComboBox.h>
  24. #endif
  25. #if (!defined __EXT_PAINT_MANAGER_H)
  26. #include <ExtPaintManager.h>
  27. #endif
  28. #if (!defined __EXT_MEMORY_DC_H)
  29. #include <../Src/ExtMemoryDC.h>
  30. #endif
  31. #if (!defined __EXT_POPUP_MENU_WND_H)
  32. #include <ExtPopupMenuWnd.h>
  33. #endif
  34. #if (!defined __EXT_TOOLCONTROLBAR_H)
  35. #include <ExtToolControlBar.h>
  36. #endif
  37. #if (!defined __EXT_SCROLLWND_H)
  38. #include <ExtScrollWnd.h>
  39. #endif 
  40. #if (!defined __AFXPRIV_H__)
  41. #include <AfxPriv.h>
  42. #endif
  43. #if (! defined __VSSYM32_H__)
  44. #include <vssym32/vssym32.h>
  45. #endif // (! defined __VSSYM32_H__)
  46. #ifdef _DEBUG
  47. #define new DEBUG_NEW
  48. #undef THIS_FILE
  49. static char THIS_FILE[] = __FILE__;
  50. #endif
  51. //////////////////////////////////////////////////////////////////////////
  52. // CExtComboBoxPopupListBox
  53. //////////////////////////////////////////////////////////////////////////
  54. IMPLEMENT_DYNAMIC( CExtComboBoxPopupListBox, CWnd );
  55. BEGIN_MESSAGE_MAP( CExtComboBoxPopupListBox, CWnd )
  56. //{{AFX_MSG_MAP(CExtComboBoxPopupListBox)
  57. ON_WM_MOUSEMOVE()
  58. ON_WM_LBUTTONUP()
  59. ON_WM_LBUTTONDOWN()
  60. ON_WM_LBUTTONDBLCLK()
  61. ON_WM_KEYDOWN()
  62. ON_WM_PAINT()
  63. ON_WM_ERASEBKGND()
  64. //}}AFX_MSG_MAP
  65. END_MESSAGE_MAP()
  66. CExtComboBoxPopupListBox::CExtComboBoxPopupListBox()
  67. : m_pCB( NULL )
  68. , m_hWndCB( NULL )
  69. , m_bFirstActivationInvocation( true )
  70. , m_bSimpleModeComboBox( false )
  71. , m_rcWndRestore( 0, 0, 0, 0 )
  72. {
  73. }
  74. CExtComboBoxPopupListBox::~CExtComboBoxPopupListBox()
  75. {
  76. }
  77. bool CExtComboBoxPopupListBox::_IsEnabledItem( CPoint point )
  78. {
  79. ASSERT_VALID( this );
  80. if( GetSafeHwnd() == NULL || m_hWndCB == NULL || ( ! ::IsWindow( m_hWndCB ) ) )
  81. return false;
  82. CRect rcClient;
  83. GetClientRect( rcClient );
  84. if( rcClient.PtInRect( point ) )
  85. {
  86. BOOL bOutside = FALSE;
  87. INT nIndex = ((CListBox *)this)->ItemFromPoint( point, bOutside );
  88. if( (!bOutside) 
  89. && m_pCB->LbItemIsEnabled( nIndex )
  90. )
  91. return true;
  92. return false;
  93. }
  94. return true;
  95. }
  96. void CExtComboBoxPopupListBox::OnLButtonUp( UINT nFlags, CPoint point ) 
  97. {
  98. ASSERT_VALID( this );
  99. if( ! _IsEnabledItem( point ) )
  100. return;
  101. CWnd::OnLButtonUp(nFlags, point);
  102. }
  103. void CExtComboBoxPopupListBox::OnMouseMove(UINT nFlags, CPoint point) 
  104. {
  105. ASSERT_VALID( this );
  106. if( ! _IsEnabledItem( point ) )
  107. return;
  108. CWnd::OnMouseMove(nFlags, point);
  109. }
  110. void CExtComboBoxPopupListBox::OnLButtonDown(UINT nFlags, CPoint point) 
  111. {
  112. ASSERT_VALID( this );
  113. if( ! _IsEnabledItem( point ) )
  114. return;
  115. CWnd::OnLButtonDown(nFlags, point);
  116. }
  117. void CExtComboBoxPopupListBox::OnLButtonDblClk(UINT nFlags, CPoint point) 
  118. {
  119. ASSERT_VALID( this );
  120. if( ! _IsEnabledItem( point ) )
  121. return;
  122. CWnd::OnLButtonDblClk(nFlags, point);
  123. }
  124. void CExtComboBoxPopupListBox::PreSubclassWindow()
  125. {
  126. ASSERT_VALID( this );
  127. CWnd::PreSubclassWindow();
  128. ASSERT_VALID( m_pCB );
  129. ASSERT( m_pCB->GetSafeHwnd() != NULL && m_pCB->m_hWnd == m_hWndCB );
  130. DWORD dwStyle = m_pCB->GetStyle();
  131. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  132. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  133. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST 
  134. )
  135. m_bSimpleModeComboBox = true;
  136. if( m_bSimpleModeComboBox )
  137. ModifyStyle( 0, WS_CLIPCHILDREN|WS_CLIPSIBLINGS );
  138. }
  139. void CExtComboBoxPopupListBox::PostNcDestroy()
  140. {
  141. ASSERT_VALID( this );
  142. delete this;
  143. }
  144. LRESULT CExtComboBoxPopupListBox::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
  145. {
  146. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  147. {
  148. LRESULT lResult = 0L;
  149. if( m_pCB->_OnCbLbPreWndProc( lResult, message, wParam, lParam ) )
  150. return lResult;
  151. }
  152. switch( message )
  153. {
  154. case WM_NCCALCSIZE:
  155. if( m_bSimpleModeComboBox)
  156. {
  157. NCCALCSIZE_PARAMS * myNCSIZE = (NCCALCSIZE_PARAMS*)lParam;
  158. CRect rcSaved = myNCSIZE->rgrc[0];
  159. LRESULT lResult = CWnd::WindowProc( message, wParam, lParam );
  160. //myNCSIZE->rgrc[0].left = rcSaved.left;
  161. myNCSIZE->rgrc[0].top = rcSaved.top;
  162. myNCSIZE->rgrc[0].bottom = rcSaved.bottom;
  163. myNCSIZE->rgrc[0].right ++;
  164. return lResult;
  165. }
  166. break;
  167. case (WM_USER+555):
  168. MoveWindow( &m_rcWndRestore );
  169. return 0L;
  170. case WM_PRINT:
  171. case WM_PRINTCLIENT:
  172. if( m_bFirstActivationInvocation )
  173. {
  174. m_bFirstActivationInvocation = false;
  175. if( ! m_bSimpleModeComboBox )
  176. {
  177. GetWindowRect( &m_rcWndRestore );
  178. MoveWindow( -32000, -32000, 0, 0 );
  179. PostMessage( (WM_USER+555) );
  180. }
  181. }
  182. if( ! m_bSimpleModeComboBox )
  183. return 0L;
  184. break;
  185. case WM_ERASEBKGND:
  186. if(  (GetStyle() & LBS_OWNERDRAWFIXED) != 0 
  187. || (GetStyle() & LBS_OWNERDRAWVARIABLE) != 0 
  188. )
  189. return TRUE;
  190. break;
  191. case WM_PAINT:
  192. if(  (GetStyle() & LBS_OWNERDRAWFIXED) != 0 
  193. || (GetStyle() & LBS_OWNERDRAWVARIABLE) != 0 
  194. )
  195. {
  196. CPaintDC dcPaint( this );
  197. CRect rcClient;
  198. GetClientRect( &rcClient );
  199. CExtMemoryDC dc( &dcPaint, &rcClient );
  200. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  201. {
  202. CExtPaintManager * pPM = m_pCB->PmBridge_GetPM();
  203. ASSERT_VALID( pPM );
  204. dc.FillSolidRect( &rcClient, pPM->GetColor( COLOR_WINDOW, this ) );
  205. HFONT hFont = m_pCB->OnQueryFont();
  206. if( hFont == NULL )
  207. hFont = (HFONT)pPM->m_FontNormal.GetSafeHandle();
  208. ASSERT( hFont != NULL );
  209. HFONT hOldFont = (HFONT)::SelectObject( dc.m_hDC, hFont );
  210. INT nCount = m_pCB->GetCount();
  211. INT nTopIndex = ((CListBox*)this)->GetTopIndex();
  212. for( INT nItem = nTopIndex; nItem < nCount; nItem++ )
  213. {
  214. DRAWITEMSTRUCT dis;
  215. ::memset( &dis, 0, sizeof( DRAWITEMSTRUCT ) );
  216. dis.CtlType = ODT_LISTBOX;
  217. dis.CtlID = GetDlgCtrlID();
  218. dis.itemID = nItem;
  219. dis.hDC = dc.GetSafeHdc();
  220. ((CListBox*)this)->GetItemRect( nItem, &dis.rcItem );
  221. dis.itemAction = ODA_DRAWENTIRE;
  222. dis.hwndItem = GetSafeHwnd();
  223. dis.itemData = m_pCB->GetItemData( nItem );
  224. if( rcClient.bottom < dis.rcItem.top )
  225. break;
  226. if( ((CListBox*)this)->GetSel( nItem ) > 0 )
  227. dis.itemState |= ODS_SELECTED;
  228. if( ((CListBox*)this)->GetCurSel() == nItem )
  229. dis.itemState |= ODS_FOCUS;
  230. m_pCB->SendMessage( WM_DRAWITEM, (WPARAM)GetDlgCtrlID(), (LPARAM)&dis );
  231. }
  232. ::SelectObject( dc.m_hDC, hOldFont );
  233. }
  234. return TRUE;
  235. }
  236. break;
  237. } // switch( message )
  238. HWND hWndCB = m_hWndCB, hWndOwn = m_hWnd;
  239. LRESULT lResult = CWnd::WindowProc( message, wParam, lParam );
  240. if( ! ( hWndOwn != NULL && ::IsWindow( hWndOwn ) ) )
  241. return lResult;
  242. if( hWndCB != NULL && ::IsWindow( hWndCB ) && m_pCB != NULL && LPVOID(CWnd::FromHandlePermanent(hWndCB)) == LPVOID(m_pCB) )
  243. m_pCB->_OnCbLbPostWndProc( lResult, message, wParam, lParam );
  244. LONG nFrame = RDW_FRAME;
  245. switch( message )
  246. {
  247. case WM_VSCROLL:
  248. case WM_HSCROLL:
  249. nFrame = 0L;
  250. case WM_SHOWWINDOW:
  251. case WM_WINDOWPOSCHANGED:
  252. RedrawWindow(
  253. NULL,
  254. NULL,
  255. RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|nFrame
  256. );
  257. break;
  258. } // switch( message )
  259. return lResult;
  260. }
  261. void CExtComboBoxPopupListBox::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) 
  262. {
  263. ASSERT_VALID( this );
  264. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) && m_pCB->GetDroppedState() )
  265. {
  266. DWORD dwComboBoxType = m_pCB->GetStyle() & 0x0003L;
  267. CListBox * pListBox = ( CListBox * ) this;
  268. bool bSelChanged = false;
  269. switch( nChar )
  270. {
  271. case VK_LEFT:
  272. case VK_UP:
  273. {
  274. INT nCount = pListBox->GetCount();
  275. if( nCount == 0 )
  276. break;
  277. // Go up until we find a valid selection then set the current selection to that one
  278. INT nCurSel = pListBox->GetCurSel();
  279. INT nSel = nCurSel;
  280. bool bInitSelection = false;
  281. if( nSel < 0 && nCount > 0 )
  282. {
  283. nSel = nCount - 1;
  284. bInitSelection = true;
  285. }
  286. if( nSel != LB_ERR )
  287. {
  288. while( nSel > 0 )
  289. {
  290. INT nItem = nSel - ( bInitSelection ? 0 : 1 );
  291. if( m_pCB->LbItemIsEnabled( nItem ) )
  292. {
  293. if( nCurSel != nItem )
  294. {
  295. pListBox->SetRedraw( FALSE );
  296. INT nRealSel = pListBox->SetCurSel( nItem );
  297. if( nCurSel != nRealSel )
  298. {
  299. if( dwComboBoxType == CBS_DROPDOWNLIST )
  300. {
  301. INT nTopIndex = pListBox->GetTopIndex();
  302. m_pCB->SetCurSel( nRealSel );
  303. pListBox->SetTopIndex( nTopIndex );
  304. }
  305. else
  306. {
  307. CString sText;
  308. pListBox->GetText( nRealSel, sText );
  309. m_pCB->SetWindowText( sText );
  310. m_pCB->SetEditSel( 0, -1 );
  311. }
  312. bSelChanged = true;
  313. }
  314. pListBox->SetRedraw( TRUE );
  315. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  316. }
  317. break;
  318. }
  319. nSel--;
  320. }
  321. }
  322. }
  323. break;
  324. case VK_RIGHT:
  325. case VK_DOWN:
  326. {
  327. INT nCount = pListBox->GetCount();
  328. if( nCount == 0 )
  329. break;
  330. // Go down until we find a valid selection then set the current selection to that one
  331. INT nCurSel = pListBox->GetCurSel();
  332. INT nSel = nCurSel;
  333. bool bInitSelection = false;
  334. if( nSel < 0 && nCount > 0 )
  335. {
  336. nSel = 0;
  337. bInitSelection = true;
  338. }
  339. if( nSel != LB_ERR )
  340. {
  341. while( nSel < nCount - 1 )
  342. {
  343. INT nItem = nSel + ( bInitSelection ? 0 : 1 );
  344. if( nItem == nCount )
  345. break;
  346. if( m_pCB->LbItemIsEnabled( nItem ) )
  347. {
  348. if( nCurSel != nItem )
  349. {
  350. pListBox->SetRedraw( FALSE );
  351. INT nRealSel = pListBox->SetCurSel( nItem );
  352. if( nCurSel != nRealSel )
  353. {
  354. if( dwComboBoxType == CBS_DROPDOWNLIST )
  355. {
  356. INT nTopIndex = pListBox->GetTopIndex();
  357. m_pCB->SetCurSel( nRealSel );
  358. pListBox->SetTopIndex( nTopIndex );
  359. }
  360. else
  361. {
  362. CString sText;
  363. pListBox->GetText( nRealSel, sText );
  364. m_pCB->SetWindowText( sText );
  365. m_pCB->SetEditSel( 0, -1 );
  366. }
  367. bSelChanged = true;
  368. }
  369. pListBox->SetRedraw( TRUE );
  370. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  371. }
  372. break;
  373. }
  374. nSel++;
  375. }
  376. }
  377. }
  378. break;
  379. case VK_PRIOR:
  380. {
  381. INT nCount = pListBox->GetCount();
  382. if( nCount == 0 )
  383. break;
  384.   INT nTopIndex = pListBox->GetTopIndex();
  385. INT nCurSel = pListBox->GetCurSel();
  386. if( nCurSel == 0 && nTopIndex == 0 )
  387. break;
  388. SCROLLINFO _scroll_info;
  389. ::memset( &_scroll_info, 0, sizeof(SCROLLINFO) );
  390. _scroll_info.cbSize = sizeof(SCROLLINFO);
  391. if( ! pListBox->GetScrollInfo( SB_VERT, &_scroll_info ) )
  392. break;
  393. INT nNewSel = _scroll_info.nPos - _scroll_info.nPage;
  394. if( nNewSel < 0 )
  395. nNewSel = 0;
  396. if( nNewSel != nCurSel || nTopIndex != nNewSel  )
  397. {
  398. pListBox->SetRedraw( FALSE );
  399. if( nTopIndex != nNewSel )
  400. pListBox->SetTopIndex( nNewSel );
  401. if( nNewSel != nCurSel )
  402. {
  403. m_pCB->SetCurSel( nNewSel );
  404. bSelChanged = true;
  405. }
  406. if( dwComboBoxType != CBS_DROPDOWNLIST )
  407. {
  408. CString sText;
  409. pListBox->GetText( nNewSel, sText );
  410. m_pCB->SetWindowText( sText );
  411. m_pCB->SetEditSel( 0, -1 );
  412. }
  413. pListBox->SetRedraw( TRUE );
  414. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  415. }
  416. }
  417. break;
  418. case VK_NEXT:
  419. {
  420. INT nCount = pListBox->GetCount();
  421. if( nCount == 0 )
  422. break;
  423.   INT nTopIndex = pListBox->GetTopIndex();
  424. INT nCurSel = pListBox->GetCurSel();
  425. SCROLLINFO _scroll_info;
  426. ::memset( &_scroll_info, 0, sizeof(SCROLLINFO) );
  427. _scroll_info.cbSize = sizeof(SCROLLINFO);
  428. if( ! pListBox->GetScrollInfo( SB_VERT, &_scroll_info ) )
  429. break;
  430. INT nNewTopIndex = _scroll_info.nPos + _scroll_info.nPage;
  431. INT nNewSel = nNewTopIndex + _scroll_info.nPage - 1;
  432. if( nNewSel >= nCount )
  433. nNewSel = nCount - 1;
  434. if( nNewSel != nCurSel || nNewTopIndex != nTopIndex )
  435. {
  436. pListBox->SetRedraw( FALSE );
  437. if( nNewSel != nCurSel )
  438. {
  439. m_pCB->SetCurSel( nNewSel );
  440. bSelChanged = true;
  441. }
  442. if( nNewTopIndex != nTopIndex )
  443. m_pCB->SetTopIndex( nNewTopIndex );
  444. if( dwComboBoxType != CBS_DROPDOWNLIST )
  445. {
  446. CString sText;
  447. pListBox->GetText( nNewSel, sText );
  448. m_pCB->SetWindowText( sText );
  449. m_pCB->SetEditSel( 0, -1 );
  450. }
  451. pListBox->SetRedraw( TRUE );
  452. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  453. }
  454. }
  455. break;
  456. case VK_HOME:
  457. {
  458. INT nCount = pListBox->GetCount();
  459. if( nCount == 0 )
  460. break;
  461. // Select first non-disabled item
  462. INT nCurSel = pListBox->GetCurSel();
  463. INT nSel = 0;
  464. while( nSel < nCount - 1 )
  465. {
  466. INT nItem = nSel;
  467. if( m_pCB->LbItemIsEnabled( nItem ) )
  468. {
  469. if( nCurSel != nItem )
  470. {
  471. pListBox->SetRedraw( FALSE );
  472. INT nRealSel = pListBox->SetCurSel( nItem );
  473. if( nCurSel != nRealSel )
  474. {
  475. if( dwComboBoxType == CBS_DROPDOWNLIST )
  476. {
  477. INT nTopIndex = pListBox->GetTopIndex();
  478. m_pCB->SetCurSel( nRealSel );
  479. pListBox->SetTopIndex( nTopIndex );
  480. }
  481. else
  482. {
  483. CString sText;
  484. pListBox->GetText( nRealSel, sText );
  485. m_pCB->SetWindowText( sText );
  486. m_pCB->SetEditSel( 0, -1 );
  487. }
  488. bSelChanged = true;
  489. }
  490. pListBox->SetRedraw( TRUE );
  491. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  492. }
  493. break;
  494. }
  495. nSel++;
  496. }
  497. }
  498. break;
  499. case VK_END:
  500. {
  501. INT nCount = pListBox->GetCount();
  502. if( nCount == 0 )
  503. break;
  504. // Select last non-disabled item
  505. INT nCurSel = pListBox->GetCurSel();
  506. INT nSel = nCount;
  507. while( nSel > 0 )
  508. {
  509. INT nItem = nSel - 1;
  510. if( m_pCB->LbItemIsEnabled( nItem ) )
  511. {
  512. if( nCurSel != nItem )
  513. {
  514. pListBox->SetRedraw( FALSE );
  515. INT nRealSel = pListBox->SetCurSel( nItem );
  516. if( nCurSel != nRealSel )
  517. {
  518. if( dwComboBoxType == CBS_DROPDOWNLIST )
  519. {
  520. INT nTopIndex = pListBox->GetTopIndex();
  521. m_pCB->SetCurSel( nRealSel );
  522. pListBox->SetTopIndex( nTopIndex );
  523. }
  524. else
  525. {
  526. CString sText;
  527. pListBox->GetText( nRealSel, sText );
  528. m_pCB->SetWindowText( sText );
  529. m_pCB->SetEditSel( 0, -1 );
  530. }
  531. bSelChanged = true;
  532. }
  533. pListBox->SetRedraw( TRUE );
  534. pListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  535. }
  536. break;
  537. }
  538. nSel--;
  539. }
  540. }
  541. break;
  542. default:
  543. CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
  544. return;
  545. } // switch( nChar )
  546. if( bSelChanged )
  547. {
  548. // The CBN_SELCHANGE notification message is not sent when the selection 
  549. // is changed using the CB_SETCURSEL message. 
  550. if( ! m_pCB->m_bEnableSelChangeWorkaround  )
  551. {
  552. CWnd * pWnd = m_pCB->GetParent();
  553. if( pWnd->GetSafeHwnd() != NULL )
  554. {
  555. ASSERT_VALID( pWnd );
  556. pWnd->SendMessage(
  557. WM_COMMAND,
  558. MAKEWPARAM( m_pCB->GetDlgCtrlID(), CBN_SELCHANGE ),
  559. (LPARAM) m_hWnd
  560. );
  561. }
  562. }
  563. }
  564. return;
  565. } // if( ... && m_pCB->GetDroppedState() )
  566. CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
  567. }
  568. /////////////////////////////////////////////////////////////////////////////
  569. // CExtComboBoxFilterPopupListBox::LB_ITEM
  570. //////////////////////////////////////////////////////////////////////////
  571. CExtComboBoxFilterPopupListBox::LB_ITEM::LB_ITEM()
  572. {
  573. m_lParam = 0L;
  574. }
  575. CExtComboBoxFilterPopupListBox::LB_ITEM::~LB_ITEM()
  576. {
  577. }
  578. LPARAM CExtComboBoxFilterPopupListBox::LB_ITEM::LParamGet() const
  579. {
  580. return m_lParam;
  581. }
  582. void CExtComboBoxFilterPopupListBox::LB_ITEM::LParamSet( 
  583. LPARAM lParam 
  584. )
  585. {
  586. m_lParam = lParam;
  587. }
  588. //////////////////////////////////////////////////////////////////////////
  589. // CExtComboBoxFilterPopupListBox
  590. //////////////////////////////////////////////////////////////////////////
  591. IMPLEMENT_DYNAMIC( CExtComboBoxFilterPopupListBox, CListBox );
  592. BEGIN_MESSAGE_MAP(CExtComboBoxFilterPopupListBox, CListBox)
  593. //{{AFX_MSG_MAP(CExtComboBoxFilterPopupListBox)
  594. ON_WM_MOUSEACTIVATE()
  595. ON_WM_MOUSEMOVE()
  596. ON_WM_LBUTTONDOWN()
  597. ON_WM_LBUTTONUP()
  598. ON_WM_NCLBUTTONDOWN()
  599. ON_WM_SETCURSOR()
  600. ON_WM_CAPTURECHANGED()
  601. ON_WM_CANCELMODE()
  602. ON_WM_NCLBUTTONUP()
  603. ON_WM_NCCALCSIZE()
  604. ON_WM_NCPAINT()
  605. ON_WM_NCLBUTTONDBLCLK()
  606. ON_WM_LBUTTONDBLCLK()
  607. ON_WM_KEYDOWN()
  608. ON_MESSAGE( LB_ADDSTRING, OnLBAddString )
  609. ON_MESSAGE( LB_INSERTSTRING, OnLBInsertString )
  610. ON_MESSAGE( LB_DELETESTRING, OnLBDeleteString )
  611. ON_MESSAGE( LB_RESETCONTENT, OnLBResetContent )
  612. ON_MESSAGE( LB_ADDFILE, OnLBAddFile )
  613. //}}AFX_MSG_MAP
  614. ON_WM_ACTIVATEAPP()
  615. __EXT_MFC_ON_WM_NCHITTEST()
  616. END_MESSAGE_MAP()
  617. CExtComboBoxFilterPopupListBox::CExtComboBoxFilterPopupListBox(
  618. CExtComboBoxBase * pCB // = NULL
  619. )
  620. : m_pCB( pCB )
  621. , m_hWndCB( NULL )
  622. , m_hCursorSizeWE( NULL )
  623. , m_hCursorSizeNS( NULL )
  624. , m_hCursorSizeNWSE( NULL )
  625. , m_bResizingX( false )
  626. , m_bResizingY( false )
  627. , m_ptCursorPosLast( 0, 0 )
  628. {
  629. m_hCursorSizeWE = ::LoadCursor( NULL, IDC_SIZEWE );
  630. ASSERT( m_hCursorSizeWE != NULL );
  631. m_hCursorSizeNS = ::LoadCursor( NULL, IDC_SIZENS );
  632. ASSERT( m_hCursorSizeNS != NULL );
  633. m_hCursorSizeNWSE = ::LoadCursor( NULL, IDC_SIZENWSE );
  634. ASSERT( m_hCursorSizeNWSE != NULL );
  635. }
  636. CExtComboBoxFilterPopupListBox::~CExtComboBoxFilterPopupListBox()
  637. {
  638. LbItemRemoveAll();
  639. if( m_hCursorSizeWE != NULL )
  640. {
  641. ::DestroyCursor( m_hCursorSizeWE );
  642. m_hCursorSizeWE = NULL;
  643. }
  644. if( m_hCursorSizeNS != NULL )
  645. {
  646. ::DestroyCursor( m_hCursorSizeNS );
  647. m_hCursorSizeNS = NULL;
  648. }
  649. if( m_hCursorSizeNWSE != NULL )
  650. {
  651. ::DestroyCursor( m_hCursorSizeNWSE );
  652. m_hCursorSizeNWSE = NULL;
  653. }
  654. }
  655. INT CExtComboBoxFilterPopupListBox::LbItemInsert( 
  656. INT nIndex // = -1
  657. )
  658. {
  659. INT nCount = INT( m_arrLBItems.GetSize() );
  660. if( nIndex < 0 || nIndex > nCount )
  661. nIndex = nCount; // append
  662. LB_ITEM * pItem = new LB_ITEM();
  663. ASSERT( pItem != NULL );
  664. m_arrLBItems.InsertAt( nIndex, pItem );
  665. return nIndex;
  666. }
  667. bool CExtComboBoxFilterPopupListBox::LbItemRemove(
  668. LONG nIndex
  669. )
  670. {
  671. INT nCount = INT( m_arrLBItems.GetSize() );
  672. if( nIndex < 0 || nIndex >= nCount )
  673. return false;
  674. LB_ITEM * pItem = m_arrLBItems.GetAt( nIndex );
  675. ASSERT( pItem != NULL );
  676. if( pItem != NULL )
  677. {
  678. delete pItem;
  679. pItem = NULL;
  680. }
  681. m_arrLBItems.RemoveAt( nIndex );
  682. return true;
  683. }
  684. void CExtComboBoxFilterPopupListBox::LbItemRemoveAll()
  685. {
  686. while( m_arrLBItems.GetSize() > 0 )
  687. {
  688. LB_ITEM * pItem = m_arrLBItems[0];
  689. if( pItem != NULL ) 
  690. {
  691. delete pItem;
  692. pItem = NULL;
  693. }
  694. m_arrLBItems.RemoveAt(0);
  695. }
  696. }
  697. CExtComboBoxFilterPopupListBox::LB_ITEM * CExtComboBoxFilterPopupListBox::LbItemGet( 
  698. LONG nIndex 
  699. ) const
  700. {
  701. INT nCount = INT( m_arrLBItems.GetSize() );
  702. if( nIndex < 0 || nIndex >= nCount )
  703. return NULL;
  704. LB_ITEM * pItem = m_arrLBItems.GetAt( nIndex );
  705. ASSERT( pItem != NULL );
  706. return pItem;
  707. }
  708. INT CExtComboBoxFilterPopupListBox::LbItemGetIndexOf( 
  709. const LB_ITEM * pItem 
  710. ) const
  711. {
  712. INT nCount = INT( m_arrLBItems.GetSize() );
  713. for( INT nIndex = 0; nIndex < nCount; nIndex++ )
  714. {
  715. LB_ITEM * pItem2 = m_arrLBItems.GetAt( nIndex );
  716. ASSERT( pItem2 != NULL );
  717. if( pItem2 == pItem )
  718. return nIndex;
  719. }
  720. return -1;
  721. }
  722. INT CExtComboBoxFilterPopupListBox::LbItemGetCount() const
  723. {
  724. INT nCount = INT( m_arrLBItems.GetSize() );
  725. return nCount;
  726. }
  727. LRESULT CExtComboBoxFilterPopupListBox::OnLBAddString( WPARAM wParam, LPARAM lParam )
  728. {
  729. ASSERT_VALID( this );
  730. LRESULT lResult = DefWindowProc( LB_ADDSTRING, wParam, lParam );
  731. if( lResult != LB_ERR )
  732. LbItemInsert( (INT)lResult );
  733. return lResult;
  734. }
  735. LRESULT CExtComboBoxFilterPopupListBox::OnLBInsertString( WPARAM wParam, LPARAM lParam )
  736. {
  737. ASSERT_VALID( this );
  738. LRESULT lResult = DefWindowProc( LB_INSERTSTRING, wParam, lParam );
  739. if( lResult != LB_ERR )
  740. LbItemInsert( (INT)lResult );
  741. return lResult;
  742. }
  743. LRESULT CExtComboBoxFilterPopupListBox::OnLBDeleteString( WPARAM wParam, LPARAM lParam )
  744. {
  745. ASSERT_VALID( this );
  746. LRESULT lResult = DefWindowProc( LB_DELETESTRING, wParam, lParam );
  747. if( lResult != LB_ERR )
  748. LbItemRemove( (LONG)wParam );
  749. return lResult;
  750. }
  751. LRESULT CExtComboBoxFilterPopupListBox::OnLBResetContent( WPARAM wParam, LPARAM lParam )
  752. {
  753. ASSERT_VALID( this );
  754. LRESULT lResult = DefWindowProc( LB_RESETCONTENT, wParam, lParam );
  755. LbItemRemoveAll();
  756. return lResult;
  757. }
  758. LRESULT CExtComboBoxFilterPopupListBox::OnLBAddFile( WPARAM wParam, LPARAM lParam )
  759. {
  760. ASSERT_VALID( this );
  761. LRESULT lResult = DefWindowProc( LB_ADDSTRING, wParam, lParam );
  762. if( lResult != LB_ERR )
  763. LbItemInsert( (INT)lResult );
  764. return lResult;
  765. }
  766. void CExtComboBoxFilterPopupListBox::DrawItem( LPDRAWITEMSTRUCT lpDIS ) 
  767. {
  768. ASSERT_VALID( this );
  769. ASSERT( lpDIS != NULL && lpDIS->hDC != NULL );
  770. if( ! ( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) ) )
  771. return;
  772. if( (GetStyle() & CBS_HASSTRINGS) == 0 
  773. && (GetStyle() & LBS_HASSTRINGS) == 0 
  774. )
  775. return;
  776. INT nCount = GetCount();
  777. INT nItem = lpDIS->itemID;
  778. if( nItem < 0 || nItem >= nCount )
  779. return;
  780. LB_ITEM * pFLbItem = LbItemGet( nItem );
  781. ASSERT( pFLbItem != NULL );
  782. if( pFLbItem != NULL )
  783. {
  784. CExtComboBoxBase::LB_ITEM * pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  785. ASSERT( pLbItem != NULL );
  786. if( pLbItem != NULL )
  787. {
  788. CDC dc;
  789. dc.Attach( lpDIS->hDC );
  790. if( lpDIS->itemAction & (ODA_DRAWENTIRE | ODA_SELECT) )
  791. {
  792. CRect rcErase( lpDIS->rcItem );
  793. if( nItem == ( nCount - 1 ) )
  794. {
  795. CRect rcClient;
  796. GetClientRect( &rcClient );
  797. if( rcErase.bottom < rcClient.bottom )
  798. rcErase.bottom = rcClient.bottom;
  799. }
  800. dc.FillSolidRect(
  801. rcErase, 
  802. m_pCB->PmBridge_GetPM()->GetColor( COLOR_WINDOW, this )
  803. );
  804. }
  805. m_pCB->OnPopupListBoxDrawItem( 
  806. dc,
  807. lpDIS->rcItem,
  808. m_pCB->OnPopupListBoxCalcItemExtraSizes( nItem ),
  809. lpDIS->itemState,
  810. pLbItem 
  811. );
  812. dc.Detach();
  813. } // if( pLbItem != NULL )
  814. } // if( pFLbItem != NULL )
  815. }
  816. void CExtComboBoxFilterPopupListBox::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) 
  817. {
  818. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  819. m_pCB->OnPopupListBoxMeasureItem( lpMIS );
  820. }
  821. LRESULT CExtComboBoxFilterPopupListBox::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
  822. {
  823. switch( message )
  824. {
  825. case WM_ERASEBKGND:
  826. if(  (GetStyle() & LBS_OWNERDRAWFIXED) != 0 
  827. || (GetStyle() & LBS_OWNERDRAWVARIABLE) != 0 
  828. )
  829. return TRUE;
  830. break;
  831. case WM_PAINT:
  832. if(  (GetStyle() & LBS_OWNERDRAWFIXED) != 0 
  833. || (GetStyle() & LBS_OWNERDRAWVARIABLE) != 0 
  834. )
  835. {
  836. CPaintDC dcPaint( this );
  837. CRect rcClient;
  838. GetClientRect( &rcClient );
  839. CExtMemoryDC dc( &dcPaint, &rcClient );
  840. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  841. {
  842. CExtPaintManager * pPM = m_pCB->PmBridge_GetPM();
  843. ASSERT_VALID( pPM );
  844. dc.FillSolidRect( &rcClient, pPM->GetColor( COLOR_WINDOW, this ) );
  845. HFONT hFont = m_pCB->OnQueryFont();
  846. if( hFont == NULL )
  847. hFont = (HFONT)pPM->m_FontNormal.GetSafeHandle();
  848. ASSERT( hFont != NULL );
  849. HFONT hOldFont = (HFONT)::SelectObject( dc.m_hDC, hFont );
  850. INT nCount = GetCount();
  851. for( INT nItem = GetTopIndex(); nItem < nCount; nItem++ )
  852. {
  853. DRAWITEMSTRUCT dis;
  854. ::memset( &dis, 0, sizeof( DRAWITEMSTRUCT ) );
  855. dis.CtlType = ODT_LISTBOX;
  856. dis.CtlID = GetDlgCtrlID();
  857. dis.itemID = nItem;
  858. dis.hDC = dc.GetSafeHdc();
  859. GetItemRect( nItem, &dis.rcItem );
  860. dis.itemAction = ODA_DRAWENTIRE;
  861. dis.hwndItem = GetSafeHwnd();
  862. if( rcClient.bottom < dis.rcItem.top )
  863. break;
  864. if( GetSel( nItem ) > 0 )
  865. dis.itemState |= ODS_SELECTED;
  866. if( GetCurSel() == nItem )
  867. dis.itemState |= ODS_FOCUS;
  868. SendMessage( WM_DRAWITEM, (WPARAM)GetDlgCtrlID(), (LPARAM)&dis );
  869. }
  870. ::SelectObject( dc.m_hDC, hOldFont );
  871. }
  872. return TRUE;
  873. }
  874. break;
  875. }
  876. return CListBox::WindowProc( message, wParam, lParam );
  877. }
  878. void CExtComboBoxFilterPopupListBox::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) 
  879. {
  880. ASSERT_VALID( this );
  881. switch( nChar )
  882. {
  883. case VK_LEFT:
  884. case VK_UP:
  885. {
  886. // Go up until we find a valid selection
  887. // then set the current selection to that one
  888. INT nSel = GetCurSel();
  889. bool bInitSelection = false;
  890. INT nCount = GetCount();
  891. if( nSel < 0 && nCount > 0 )
  892. {
  893. nSel = nCount - 1;
  894. bInitSelection = true;
  895. }
  896. if( nSel != LB_ERR )
  897. {
  898. while( nSel >= 0 )
  899. {
  900. INT nItem = nSel - ( bInitSelection ? 0 : 1 );
  901. if( nItem < 0 && nCount > 0 )
  902. nItem = 0;
  903. LB_ITEM * pFLbItem = LbItemGet( nItem );
  904. ASSERT( pFLbItem != NULL );
  905. CExtComboBoxBase::LB_ITEM * pLbItem = NULL;
  906. if( pFLbItem != NULL )
  907. pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  908. ASSERT( pLbItem != NULL );
  909. if( pLbItem->IsEnabled() )
  910. {
  911. SetCurSel( nItem );
  912. break;
  913. }
  914. nSel--;
  915. }
  916. }
  917. }
  918. return;
  919. case VK_RIGHT:
  920. case VK_DOWN:
  921. {
  922. // Go down until we find a valid selection
  923. // then set the current selection to that one
  924. INT nSel = GetCurSel();
  925. bool bInitSelection = false;
  926. INT nCount = GetCount();
  927. if( nSel < 0 && nCount > 0 )
  928. {
  929. nSel = 0;
  930. bInitSelection = true;
  931. }
  932. if( nSel != LB_ERR )
  933. {
  934. while( nSel <= nCount - 1 )
  935. {
  936. INT nItem = nSel + ( bInitSelection ? 0 : 1 );
  937. if( nItem >= nCount )
  938. nItem = nCount - 1;
  939. LB_ITEM * pFLbItem = LbItemGet( nItem );
  940. ASSERT( pFLbItem != NULL );
  941. CExtComboBoxBase::LB_ITEM * pLbItem = NULL;
  942. if( pFLbItem != NULL )
  943. pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  944. ASSERT( pLbItem != NULL );
  945. if( pLbItem->IsEnabled() )
  946. {
  947. SetCurSel( nItem );
  948. break;
  949. }
  950. nSel++;
  951. }
  952. }
  953. }
  954. return;
  955. case VK_HOME:
  956. case VK_PRIOR:
  957. {
  958. // Select first non-disabled item
  959. INT nCount = GetCount();
  960. INT nSel = 0;
  961. while( nSel < nCount - 1 )
  962. {
  963. INT nItem = nSel;
  964. LB_ITEM * pFLbItem = LbItemGet( nItem );
  965. ASSERT( pFLbItem != NULL );
  966. CExtComboBoxBase::LB_ITEM * pLbItem = NULL;
  967. if( pFLbItem != NULL )
  968. pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  969. ASSERT( pLbItem != NULL );
  970. if( pLbItem->IsEnabled() )
  971. {
  972. SetCurSel( nItem );
  973. break;
  974. }
  975. nSel++;
  976. }
  977. }
  978. return;
  979. case VK_END:
  980. case VK_NEXT:
  981. {
  982. // Select last non-disabled item
  983. INT nCount = GetCount();
  984. INT nSel = nCount;
  985. while( nSel > 0 )
  986. {
  987. INT nItem = nSel - 1;
  988. LB_ITEM * pFLbItem = LbItemGet( nItem );
  989. ASSERT( pFLbItem != NULL );
  990. CExtComboBoxBase::LB_ITEM * pLbItem = NULL;
  991. if( pFLbItem != NULL )
  992. pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  993. ASSERT( pLbItem != NULL );
  994. if( pLbItem->IsEnabled() )
  995. {
  996. SetCurSel( nItem );
  997. break;
  998. }
  999. nSel--;
  1000. }
  1001. }
  1002. return;
  1003. default:
  1004. break;
  1005. }
  1006. CListBox::OnKeyDown( nChar, nRepCnt, nFlags );
  1007. }
  1008. LONG CExtComboBoxFilterPopupListBox::HitTest( 
  1009. const POINT & ptClient
  1010. ) const
  1011. {
  1012. ASSERT_VALID( this );
  1013. if( GetSafeHwnd() == NULL
  1014. || ( ! ::IsWindow( GetSafeHwnd() ) )
  1015. )
  1016. return HTNOWHERE;
  1017. CPoint ptWnd( ptClient );
  1018. ClientToScreen( &ptWnd );
  1019. CRect rcWnd;
  1020. GetWindowRect( &rcWnd );
  1021. CRect rcGrip( rcWnd );
  1022. rcGrip.top = rcGrip.bottom - ::GetSystemMetrics( SM_CYVSCROLL );
  1023. rcGrip.left = rcGrip.right - ::GetSystemMetrics( SM_CXVSCROLL );
  1024. if( rcGrip.PtInRect( ptWnd ) )
  1025. return HTBOTTOMRIGHT;
  1026. CRect rcBottom( rcWnd );
  1027. rcBottom.top = rcBottom.bottom - ::GetSystemMetrics( SM_CYEDGE );
  1028. if( rcBottom.PtInRect( ptWnd ) )
  1029. return HTBOTTOM;
  1030. CRect rcRight( rcWnd );
  1031. rcRight.left = rcRight.right - ::GetSystemMetrics( SM_CXEDGE );
  1032. if( rcRight.PtInRect( ptWnd ) )
  1033. return HTRIGHT;
  1034. if( rcWnd.PtInRect( ptWnd ) )
  1035. return HTCLIENT;
  1036. return HTNOWHERE;
  1037. }
  1038. #if _MFC_VER < 0x700
  1039. void CExtComboBoxFilterPopupListBox::OnActivateApp(BOOL bActive, HTASK hTask) 
  1040. #else
  1041. void CExtComboBoxFilterPopupListBox::OnActivateApp(BOOL bActive, DWORD hTask) 
  1042. #endif
  1043. {
  1044. CListBox::OnActivateApp(bActive, hTask);
  1045. if( ! bActive )
  1046. SendMessage( WM_CANCELMODE );
  1047. }
  1048. void CExtComboBoxFilterPopupListBox::OnCancelMode() 
  1049. {
  1050. CListBox::OnCancelMode();
  1051. if( ::GetCapture() == GetSafeHwnd() )
  1052. ::ReleaseCapture();
  1053. m_bResizingX = false;
  1054. m_bResizingY = false;
  1055. m_ptCursorPosLast = CPoint( 0, 0 );
  1056. Invalidate();
  1057. UpdateWindow();
  1058. }
  1059. void CExtComboBoxFilterPopupListBox::OnCaptureChanged(CWnd *pWnd) 
  1060. {
  1061. CListBox::OnCaptureChanged(pWnd);
  1062. if( ::GetCapture() != m_hWnd )
  1063. SendMessage( WM_CANCELMODE );
  1064. }
  1065. void CExtComboBoxFilterPopupListBox::OnLButtonDown(UINT nFlags, CPoint point) 
  1066. {
  1067. if( !_ProcessMouseClick( point, true, MK_LBUTTON ) )
  1068. CListBox::OnLButtonDown(nFlags, point);
  1069. }
  1070. void CExtComboBoxFilterPopupListBox::OnLButtonUp(UINT nFlags, CPoint point) 
  1071. {
  1072. if( !_ProcessMouseClick( point, false, MK_LBUTTON ) )
  1073. CListBox::OnLButtonUp(nFlags, point);
  1074. }
  1075. void CExtComboBoxFilterPopupListBox::OnNcLButtonDblClk(UINT nHitTest, CPoint point) 
  1076. {
  1077. if( !_ProcessMouseClick( point, true, MK_LBUTTON ) )
  1078. CListBox::OnNcLButtonDblClk(nHitTest, point);
  1079. }
  1080. void CExtComboBoxFilterPopupListBox::OnLButtonDblClk(UINT nFlags, CPoint point) 
  1081. {
  1082. if( !_ProcessMouseClick( point, true, MK_LBUTTON ) )
  1083. CListBox::OnLButtonDblClk(nFlags, point);
  1084. }
  1085. void CExtComboBoxFilterPopupListBox::OnNcLButtonDown(UINT nHitTest, CPoint point) 
  1086. {
  1087. if( !_ProcessMouseClick( point, true, MK_LBUTTON ) )
  1088. CListBox::OnNcLButtonDown(nHitTest, point);
  1089. }
  1090. void CExtComboBoxFilterPopupListBox::OnNcLButtonUp(UINT nHitTest, CPoint point) 
  1091. {
  1092. if( !_ProcessMouseClick( point, false, MK_LBUTTON ) )
  1093. CListBox::OnNcLButtonUp(nHitTest, point);
  1094. }
  1095. void CExtComboBoxFilterPopupListBox::OnMouseMove(UINT nFlags, CPoint point) 
  1096. {
  1097. if( !_ProcessMouseMove( point ) )
  1098. CListBox::OnMouseMove(nFlags, point);
  1099. }
  1100. bool CExtComboBoxFilterPopupListBox::_ProcessMouseClick(
  1101. CPoint point,
  1102. bool bButtonPressed,
  1103. INT nMouseButton // MK_... values
  1104. )
  1105. {
  1106. ASSERT_VALID( this );
  1107. // process only left mouse button clicks
  1108. if( nMouseButton != MK_LBUTTON )
  1109. return false;
  1110. // select item
  1111. if( (! bButtonPressed)
  1112. &&  (! m_bResizingX)
  1113. &&  (! m_bResizingY)
  1114. )
  1115. {
  1116. INT nCount = GetCount();
  1117. if( nCount > 0 )
  1118. {
  1119. BOOL bOutside = TRUE;
  1120. INT nHitTest = (INT) ItemFromPoint( point, bOutside );
  1121. if( !bOutside )
  1122. {
  1123. LB_ITEM * pFLbItem = LbItemGet( nHitTest );
  1124. ASSERT( pFLbItem != NULL );
  1125. CExtComboBoxBase::LB_ITEM * pLbItem = NULL;
  1126. if( pFLbItem != NULL )
  1127. pLbItem = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  1128. ASSERT( pLbItem != NULL );
  1129. if( pLbItem->IsEnabled() )
  1130. {
  1131. SetCurSel( nHitTest );
  1132. if( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  1133. m_pCB->OnFilterPopupListSelEndOK();
  1134. }
  1135. }
  1136. }
  1137. return true;
  1138. }
  1139. LONG nHT = HitTest( point );
  1140. m_bResizingX = false;
  1141. m_bResizingY = false;
  1142. m_ptCursorPosLast = CPoint( 0, 0 );
  1143. if( bButtonPressed )
  1144. {
  1145. if( nHT == HTBOTTOMRIGHT )
  1146. m_bResizingX = m_bResizingY = true;
  1147. if( nHT == HTRIGHT )
  1148. m_bResizingX = true;
  1149. if( nHT == HTBOTTOM )
  1150. m_bResizingY = true;
  1151. if( m_bResizingX || m_bResizingY )
  1152. {
  1153. m_ptCursorPosLast = point;
  1154. if( ::GetCapture() != GetSafeHwnd() )
  1155. ::SetCapture( GetSafeHwnd() );
  1156. return true;
  1157. }
  1158. }
  1159. else
  1160. {
  1161. if( ::GetCapture() == GetSafeHwnd() )
  1162. ::ReleaseCapture();
  1163. }
  1164. if( nHT == HTCLIENT )
  1165. return true;
  1166. return false;
  1167. }
  1168. bool CExtComboBoxFilterPopupListBox::_ProcessMouseMove( CPoint point )
  1169. {
  1170. ASSERT_VALID( this );
  1171. if( CExtPopupMenuWnd::IsMenuTracking() 
  1172. || (! CExtPopupMenuWnd::TestHoverEnabledFromActiveHWND( GetSafeHwnd() ) )
  1173. )
  1174. return false;
  1175. LONG nHT = HitTest( point );
  1176. if( nHT == HTCLIENT 
  1177. && !(m_bResizingX || m_bResizingY)
  1178. && m_ptCursorPosLast != point
  1179. )
  1180. {
  1181. INT nCount = GetCount();
  1182. if( nCount == 0 )
  1183. return true;
  1184. BOOL bOutside = TRUE;
  1185. INT nHitTest = (INT) ItemFromPoint( point, bOutside );
  1186. if( bOutside )
  1187. {
  1188. INT nTop = GetTopIndex();
  1189. if( nHitTest <= nTop )
  1190. {
  1191. if( nTop > 0 )
  1192. nHitTest--;
  1193. }
  1194. else
  1195. {
  1196. if( nCount > 0 && nHitTest >= (nCount-2) )
  1197. nHitTest++;
  1198. }
  1199. } // if( bOutside )
  1200. m_ptCursorPosLast = point;
  1201. INT nCurSel = GetCurSel();
  1202. if( nCurSel == nHitTest )
  1203. return true;
  1204. SetRedraw( FALSE );
  1205. SetCurSel( nHitTest );
  1206. SetRedraw( TRUE );
  1207. RedrawWindow(
  1208. NULL,
  1209. NULL,
  1210. RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME
  1211. );
  1212. return true;
  1213. }
  1214. // resize window
  1215. if( ( m_bResizingX || m_bResizingY )
  1216. && m_ptCursorPosLast != point
  1217. && m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB )
  1218. )
  1219. {
  1220. CRect rcWindow;
  1221. GetWindowRect( &rcWindow );
  1222. CRect rcWindowNew = rcWindow;
  1223. CRect rcClient;
  1224. GetClientRect( &rcClient );
  1225. CSize szMin = m_pCB->OnFilterPopupListQueryMinSize();
  1226. CSize szMax = m_pCB->OnFilterPopupListQueryMaxSize();
  1227. if( m_bResizingX 
  1228. && point.x > szMin.cx 
  1229. && ( point.x < szMax.cx || szMax.cx < 0 )
  1230. )
  1231. {
  1232. INT nOffsetX = point.x - m_ptCursorPosLast.x;
  1233. rcWindowNew.right += nOffsetX;
  1234. m_ptCursorPosLast.x += nOffsetX;
  1235. }
  1236. if( m_bResizingY 
  1237. && point.y > szMin.cy 
  1238. && ( point.y < szMax.cy || szMax.cy < 0 )
  1239. )
  1240. {
  1241. INT nOffsetY = point.y - m_ptCursorPosLast.y;
  1242. rcWindowNew.bottom += nOffsetY;
  1243. m_ptCursorPosLast.y += nOffsetY;
  1244. }
  1245. if( rcWindowNew != rcWindow )
  1246. {
  1247. SetWindowPos(
  1248. NULL,
  1249. 0,0,
  1250. rcWindowNew.Width(), rcWindowNew.Height(),
  1251. SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE 
  1252. | SWP_NOACTIVATE | SWP_NOSENDCHANGING
  1253. );
  1254. Invalidate( FALSE );
  1255. UpdateWindow();
  1256. }
  1257. }
  1258. return true;
  1259. }
  1260. BOOL CExtComboBoxFilterPopupListBox::OnSetCursor( CWnd * pWnd, UINT nHitTest, UINT message ) 
  1261. {
  1262. ASSERT_VALID( this );
  1263. CPoint ptClient;
  1264. ::GetCursorPos( &ptClient );
  1265. ScreenToClient( &ptClient );
  1266. LONG nHT = HitTest( ptClient );
  1267. if( nHT == HTBOTTOMRIGHT 
  1268. && m_hCursorSizeNWSE != NULL
  1269. )
  1270. {
  1271. SetCursor( m_hCursorSizeNWSE );
  1272. return TRUE;
  1273. }
  1274. if( nHT == HTRIGHT 
  1275. && m_hCursorSizeWE != NULL
  1276. )
  1277. {
  1278. SetCursor( m_hCursorSizeWE );
  1279. return TRUE;
  1280. }
  1281. if( nHT == HTBOTTOM
  1282. && m_hCursorSizeNS != NULL
  1283. )
  1284. {
  1285. SetCursor( m_hCursorSizeNS );
  1286. return TRUE;
  1287. }
  1288. return CListBox::OnSetCursor(pWnd, nHitTest, message);
  1289. }
  1290. int CExtComboBoxFilterPopupListBox::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
  1291. {
  1292. if( (GetStyle()&WS_TABSTOP) == 0 )
  1293. return MA_NOACTIVATE;
  1294. return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
  1295. }
  1296. UINT CExtComboBoxFilterPopupListBox::OnNcHitTest( CPoint point ) 
  1297. {
  1298. CPoint ptClient = point;
  1299. ScreenToClient( &ptClient );
  1300. LONG nHT = HitTest( ptClient );
  1301. if( nHT != HTCLIENT )
  1302. return HTCLIENT;
  1303. return UINT( CListBox::OnNcHitTest(point) );
  1304. }
  1305. void CExtComboBoxFilterPopupListBox::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
  1306. {
  1307. CRect & rcNcRect =
  1308. reinterpret_cast < CRect & > ( lpncsp->rgrc[0] );
  1309. rcNcRect.bottom -= 14;
  1310. CListBox::OnNcCalcSize(bCalcValidRects, lpncsp);
  1311. }
  1312. void CExtComboBoxFilterPopupListBox::OnNcPaint() 
  1313. {
  1314. ASSERT_VALID( this );
  1315. Default();
  1316. CRect rcInBarWnd, rcInBarClient;
  1317.     GetWindowRect( &rcInBarWnd );
  1318.     GetClientRect( &rcInBarClient );
  1319.     ClientToScreen( &rcInBarClient );
  1320.     if( rcInBarWnd == rcInBarClient )
  1321.         return;
  1322. CPoint ptDevOffset = -rcInBarWnd.TopLeft();
  1323.     rcInBarWnd.OffsetRect( ptDevOffset );
  1324.     rcInBarClient.OffsetRect( ptDevOffset );
  1325.    
  1326. CWindowDC dc( this );
  1327. const INT cx = ::GetSystemMetrics(SM_CXVSCROLL);
  1328. const INT cy = ::GetSystemMetrics(SM_CYHSCROLL);
  1329. DWORD dwStyle = GetStyle();
  1330. bool bHasVerticalSB = ( (dwStyle&WS_VSCROLL) != 0 ) ? true : false;
  1331. bool bHasHorizontalSB = ( (dwStyle&WS_HSCROLL) != 0 ) ? true : false;
  1332. COLORREF clrWindow =
  1333. ( m_pCB != NULL && m_hWndCB != NULL && ::IsWindow( m_hWndCB ) )
  1334. ? m_pCB->PmBridge_GetPM()->GetColor( COLOR_WINDOW, this )
  1335. : ::GetSysColor( COLOR_WINDOW )
  1336. ;
  1337.     if( bHasVerticalSB && bHasHorizontalSB )
  1338.     {
  1339. INT nNcX = rcInBarWnd.right - rcInBarClient.right - cx;
  1340. INT nNcY = rcInBarWnd.bottom - rcInBarClient.bottom - cy;
  1341.         dc.FillSolidRect(
  1342.             rcInBarWnd.right - cx - nNcX,
  1343.             rcInBarWnd.bottom - cy - nNcY,
  1344.             cx,
  1345.             cy,
  1346. clrWindow
  1347.             );
  1348.     }
  1349. CRect rcExclude( rcInBarClient );
  1350.     if( bHasVerticalSB )
  1351.         rcExclude.right += cx;
  1352.     if( bHasHorizontalSB )
  1353.         rcExclude.bottom += cy;
  1354. dc.ExcludeClipRect( &rcExclude );
  1355. rcInBarWnd.DeflateRect( 1, 1 );
  1356.     dc.FillSolidRect( &rcInBarWnd, clrWindow );
  1357. CRect rcGrip( rcInBarWnd );
  1358. g_PaintManager->PaintResizingGripper(
  1359. dc,
  1360. rcGrip,
  1361. this
  1362. );
  1363. dc.SelectClipRgn( NULL );
  1364. }
  1365. /////////////////////////////////////////////////////////////////////////////
  1366. // CExtComboEditCtrlHook
  1367. /////////////////////////////////////////////////////////////////////////////
  1368. CExtComboEditCtrlHook::CExtComboEditCtrlHook()
  1369. {
  1370. }
  1371. CExtComboEditCtrlHook::~CExtComboEditCtrlHook()
  1372. {
  1373. }
  1374. CExtComboBoxBase * CExtComboEditCtrlHook::OnQueryComboBox() const
  1375. {
  1376. ASSERT( GetSafeHwnd() != NULL );
  1377. ASSERT( ::IsWindow(GetSafeHwnd()) );
  1378. HWND hWndParent = ::GetParent( GetSafeHwnd() );
  1379. ASSERT( hWndParent != NULL );
  1380. ASSERT( ::IsWindow(hWndParent) );
  1381. CExtComboBoxBase * pCombo = 
  1382. DYNAMIC_DOWNCAST(
  1383. CExtComboBoxBase,
  1384. FromHandlePermanent(hWndParent)
  1385. );
  1386. ASSERT( pCombo != NULL );
  1387. return pCombo;
  1388. }
  1389. IMPLEMENT_DYNCREATE( CExtComboEditCtrlHook, CExtEditBase );
  1390. BEGIN_MESSAGE_MAP(CExtComboEditCtrlHook, CExtEditBase)
  1391. //{{AFX_MSG_MAP(CExtComboEditCtrlHook)
  1392. ON_WM_CONTEXTMENU()
  1393. ON_WM_DESTROY()
  1394. //}}AFX_MSG_MAP
  1395. END_MESSAGE_MAP()
  1396. LRESULT CExtComboEditCtrlHook::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  1397. {
  1398. bool bFlushAutoComplete = false;
  1399. switch( message )
  1400. {
  1401. case WM_CUT:
  1402. case WM_COPY:
  1403. case WM_PASTE:
  1404. case WM_CLEAR:
  1405. case WM_UNDO:
  1406. bFlushAutoComplete = true;
  1407. break;
  1408. case WM_COMMAND:
  1409. switch( LOWORD(wParam) )
  1410. {
  1411. case ID_EDIT_CLEAR:
  1412. case ID_EDIT_CLEAR_ALL:
  1413. case ID_EDIT_COPY:
  1414. case ID_EDIT_CUT:
  1415. case ID_EDIT_FIND:
  1416. case ID_EDIT_PASTE:
  1417. case ID_EDIT_PASTE_LINK:
  1418. case ID_EDIT_PASTE_SPECIAL:
  1419. case ID_EDIT_REPEAT:
  1420. case ID_EDIT_REPLACE:
  1421. case ID_EDIT_SELECT_ALL:
  1422. case ID_EDIT_UNDO:
  1423. case ID_EDIT_REDO:
  1424. bFlushAutoComplete = true;
  1425. break;
  1426. } // switch( LOWORD(wParam) )
  1427. break;
  1428. } // switch( message )
  1429. if( bFlushAutoComplete )
  1430. OnQueryComboBox()->m_bAutoComplete = false;
  1431. return CExtEditBase::WindowProc(message,wParam,lParam);
  1432. }
  1433. __EXT_MFC_INT_PTR CExtComboEditCtrlHook::OnToolHitTest(
  1434. CPoint point,
  1435. TOOLINFO * pTI
  1436. ) const
  1437. {
  1438. __PROF_UIS_MANAGE_STATE;
  1439. __EXT_MFC_IMPLEMENT_TT_REDIR_OnToolHitTest_EX( CExtComboEditCtrlHook, CExtToolControlBar, m_wndToolTip, point, pTI, 2 )
  1440. return CExtEditBase::OnToolHitTest( point, pTI );
  1441. }
  1442. void CExtComboEditCtrlHook::OnContextMenu(CWnd* pWnd,CPoint pos )
  1443. {
  1444. if( ! m_bHandleCtxMenus )
  1445. {
  1446. CExtEditBase::OnContextMenu( pWnd, pos );
  1447. return;
  1448. }
  1449. CExtComboBoxBase * pCombo = OnQueryComboBox();
  1450. if( pCombo == NULL )
  1451. return;
  1452. m_bHandleCtxMenus = pCombo->m_bHandleCtxMenus;
  1453. SetFocus();
  1454. CExtEditBase::OnContextMenu( pWnd, pos );
  1455. VERIFY(
  1456. pCombo->RedrawWindow(
  1457. NULL,
  1458. NULL,
  1459. RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ERASENOW | RDW_FRAME | RDW_ALLCHILDREN
  1460. )
  1461. );
  1462. }
  1463. void CExtComboEditCtrlHook::OnDestroy() 
  1464. {
  1465. //
  1466. // Afreen had problems with this code
  1467. //
  1468. //  CExtComboBoxBase * pCB = OnQueryComboBox();
  1469. //  ASSERT( pCB != NULL );
  1470. //  if( pCB != NULL )
  1471. //  {
  1472. //  ASSERT_VALID( pCB );
  1473. //  pCB->OnFilterPopupListClose();
  1474. //  }
  1475. CExtEditBase::OnDestroy();
  1476. }
  1477. COLORREF CExtComboEditCtrlHook::OnQueryBackColor() const
  1478. ASSERT_VALID( this );
  1479. CExtComboBoxBase * pCB = OnQueryComboBox();
  1480. return pCB->GetBkColor(); 
  1481. }
  1482. COLORREF CExtComboEditCtrlHook::OnQueryTextColor() const
  1483. ASSERT_VALID( this );
  1484. CExtComboBoxBase * pCB = OnQueryComboBox();
  1485. return pCB->GetTextColor(); 
  1486. }
  1487. /////////////////////////////////////////////////////////////////////////////
  1488. // CExtComboBoxBase::LB_ITEM::CELL
  1489. CExtComboBoxBase::LB_ITEM::CELL::CELL(
  1490. __EXT_MFC_SAFE_LPCTSTR sItemText // = NULL
  1491. )
  1492. {
  1493. m_sItemText = (sItemText != NULL) ? sItemText : _T("");
  1494. m_nLParam = 0L;
  1495. m_clrText = COLORREF( -1L );
  1496. m_clrBack = COLORREF( -1L );
  1497. }
  1498. CExtComboBoxBase::LB_ITEM::CELL::~CELL()
  1499. {
  1500. }
  1501. /////////////////////////////////////////////////////////////////////////////
  1502. // CExtComboBoxBase::LB_ITEM
  1503. CExtComboBoxBase::LB_ITEM::LB_ITEM()
  1504. {
  1505. m_bEnabled = true;
  1506. }
  1507. CExtComboBoxBase::LB_ITEM::~LB_ITEM()
  1508. {
  1509. while( m_arrItemCells.GetSize() > 0 )
  1510. {
  1511. CELL * pItemCell = m_arrItemCells[0];
  1512. if( pItemCell != NULL ) 
  1513. {
  1514. delete pItemCell;
  1515. pItemCell = NULL;
  1516. }
  1517. m_arrItemCells.RemoveAt(0);
  1518. }
  1519. }
  1520. INT CExtComboBoxBase::LB_ITEM::LbItemCellInsert(
  1521. __EXT_MFC_SAFE_LPCTSTR sItemText, // = NULL
  1522. INT nPos // = -1 // append
  1523. )
  1524. {
  1525. INT nCount = INT( m_arrItemCells.GetSize() );
  1526. if( nPos < 0 || nPos > nCount )
  1527. nPos = nCount; // append
  1528. CELL * pItemCell = new CELL( sItemText );
  1529. ASSERT( pItemCell != NULL );
  1530. m_arrItemCells.InsertAt( nPos, pItemCell );
  1531. return nPos;
  1532. }
  1533. bool CExtComboBoxBase::LB_ITEM::LbItemCellRemove(
  1534. LONG nItem
  1535. )
  1536. {
  1537. INT nCount = INT( m_arrItemCells.GetSize() );
  1538. if( nItem < 0 || nItem >= nCount )
  1539. return false;
  1540. CELL * pItemCell = m_arrItemCells.GetAt( nItem );
  1541. ASSERT( pItemCell != NULL );
  1542. if( pItemCell != NULL )
  1543. {
  1544. delete pItemCell;
  1545. pItemCell = NULL;
  1546. }
  1547. m_arrItemCells.RemoveAt( nItem );
  1548. return true;
  1549. }
  1550. CExtComboBoxBase::LB_ITEM::CELL * CExtComboBoxBase::LB_ITEM::LbItemCellGet( 
  1551. LONG nItem 
  1552. ) const
  1553. {
  1554. INT nCount = INT( m_arrItemCells.GetSize() );
  1555. if( nItem < 0 || nItem >= nCount )
  1556. return NULL;
  1557. CELL * pItemCell = m_arrItemCells.GetAt( nItem );
  1558. ASSERT( pItemCell != NULL );
  1559. return pItemCell;
  1560. }
  1561. INT CExtComboBoxBase::LB_ITEM::LbItemCellGetIndexOf( 
  1562. const CELL * pItemCell 
  1563. ) const
  1564. {
  1565. INT nCount = INT( m_arrItemCells.GetSize() );
  1566. for( INT nItem = 0; nItem < nCount; nItem++ )
  1567. {
  1568. CELL * pItemCell2 = m_arrItemCells.GetAt( nItem );
  1569. ASSERT( pItemCell2 != NULL );
  1570. if( pItemCell2 == pItemCell )
  1571. return nItem;
  1572. }
  1573. return -1;
  1574. }
  1575. INT CExtComboBoxBase::LB_ITEM::LbItemCellGetCount() const
  1576. {
  1577. INT nCount = INT( m_arrItemCells.GetSize() );
  1578. return nCount;
  1579. }
  1580. bool CExtComboBoxBase::LB_ITEM::IsEnabled() const
  1581. {
  1582. return m_bEnabled;
  1583. }
  1584. void CExtComboBoxBase::LB_ITEM::Enable(
  1585. bool bEnable // = true
  1586. )
  1587. {
  1588. m_bEnabled = bEnable;
  1589. }
  1590. /////////////////////////////////////////////////////////////////////////////
  1591. // CExtComboBoxBase
  1592. IMPLEMENT_DYNCREATE( CExtComboBoxBase, CComboBox );
  1593. CExtComboBoxBase::CExtComboBoxBase()
  1594. : m_bAutoComplete( true )
  1595. , m_bHandleCtxMenus( true )
  1596. , m_bEnableAutoComplete( true )
  1597. , m_bUseCaseSensitiveAutoComplete( false )
  1598. , m_clrBack( COLORREF(-1L) )
  1599. , m_clrBackPrev( COLORREF(-1L) )
  1600. , m_clrText( COLORREF(-1L) )
  1601. , m_pPopupListWnd( NULL )
  1602. , m_szFilterPopupListBox( -1, -1 )
  1603. , m_bEnableAutoFilter( false )
  1604. , m_bEnableSelChangeWorkaround( false )
  1605. , m_bInitialized( false )
  1606. , m_pWndPopupListBox( NULL )
  1607. , m_hWndPopupListBox( NULL )
  1608. {
  1609. EnableToolTips();
  1610. }
  1611. CExtComboBoxBase::~CExtComboBoxBase()
  1612. {
  1613. CExtAnimationSite * pAcAS = AnimationClient_SiteGet();
  1614. if( pAcAS != NULL )
  1615. pAcAS->AnimationSite_ClientRemove( this );
  1616. LbItemRemoveAll();
  1617. if( m_pWndPopupListBox != NULL )
  1618. {
  1619. if( m_hWndPopupListBox != NULL
  1620. && ::IsWindow( m_hWndPopupListBox )
  1621. && LPVOID( CWnd::FromHandlePermanent(m_hWndPopupListBox) ) == LPVOID( m_pWndPopupListBox )
  1622. )
  1623. m_pWndPopupListBox->m_pCB = NULL;
  1624. }
  1625. if( m_pPopupListWnd != NULL )
  1626. {
  1627. delete m_pPopupListWnd;
  1628. m_pPopupListWnd = NULL;
  1629. }
  1630. }
  1631. bool CExtComboBoxBase::_OnCbLbPreWndProc( LRESULT & lResult, UINT message, WPARAM wParam, LPARAM lParam )
  1632. {
  1633. lResult; message; wParam; lParam;
  1634. return false;
  1635. }
  1636. void CExtComboBoxBase::_OnCbLbPostWndProc( LRESULT lResult, UINT message, WPARAM wParam, LPARAM lParam )
  1637. {
  1638. lResult; message; wParam; lParam;
  1639. }
  1640. CExtComboBoxPopupListBox * CExtComboBoxBase::OnComboBoxPopupListBoxInstantiate()
  1641. {
  1642. ASSERT_VALID( this );
  1643. // return (new CExtComboBoxPopupListBox);
  1644. bool bSimpleMode = false;
  1645. DWORD dwStyle = GetStyle();
  1646. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  1647. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  1648. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST 
  1649. )
  1650. bSimpleMode = true;
  1651. CExtNCSB < CExtComboBoxPopupListBox > * pWndPopupListBox = new CExtNCSB < CExtComboBoxPopupListBox >;
  1652. if( bSimpleMode )
  1653. pWndPopupListBox->m_rcNcsbCustomNcAreaSizes.SetRect( 0, 0, 0, 0 );
  1654. return pWndPopupListBox;
  1655. }
  1656. CExtComboBoxPopupListBox * CExtComboBoxBase::OnComboBoxPopupListBoxQuery(
  1657. HWND hWndSubclass // = NULL
  1658. )
  1659. {
  1660. ASSERT_VALID( this );
  1661. if( GetSafeHwnd() == NULL )
  1662. return NULL;
  1663. if( m_pWndPopupListBox != NULL )
  1664. {
  1665. ASSERT_VALID( m_pWndPopupListBox );
  1666. if( hWndSubclass != NULL )
  1667. {
  1668. if( m_pWndPopupListBox->GetSafeHwnd() != hWndSubclass )
  1669. return NULL;
  1670. m_hWndPopupListBox = hWndSubclass;
  1671. }
  1672. return m_pWndPopupListBox;
  1673. }
  1674. if( hWndSubclass == NULL
  1675. || (! ::IsWindow( hWndSubclass ) )
  1676. )
  1677. return NULL;
  1678. try
  1679. {
  1680. m_pWndPopupListBox = OnComboBoxPopupListBoxInstantiate();
  1681. m_pWndPopupListBox->m_pCB = this;
  1682. m_pWndPopupListBox->m_hWndCB = m_hWnd;
  1683. VERIFY( m_pWndPopupListBox->SubclassWindow( hWndSubclass ) );
  1684. m_hWndPopupListBox = hWndSubclass;
  1685. //  m_pWndPopupListBox->RedrawWindow( NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME );
  1686. m_pWndPopupListBox->SetWindowPos(
  1687. NULL, 0, 0, 0, 0,
  1688. SWP_NOSIZE|SWP_NOMOVE
  1689. |SWP_NOZORDER|SWP_NOOWNERZORDER
  1690. |SWP_NOREPOSITION
  1691. |SWP_FRAMECHANGED
  1692. );
  1693. return m_pWndPopupListBox;
  1694. }
  1695. catch( CException * pException )
  1696. {
  1697. pException->Delete();
  1698. }
  1699. catch( ... )
  1700. {
  1701. }
  1702. return NULL;
  1703. }
  1704. BEGIN_MESSAGE_MAP(CExtComboBoxBase, CComboBox)
  1705. //{{AFX_MSG_MAP(CExtComboBoxBase)
  1706. ON_MESSAGE(CB_ADDSTRING, OnCBAddString)
  1707. ON_MESSAGE(CB_INSERTSTRING, OnCBInsertString)
  1708. ON_MESSAGE(CB_DELETESTRING, OnCBDeleteString)
  1709. ON_MESSAGE(CB_RESETCONTENT, OnCBResetContent)
  1710. ON_MESSAGE(CB_SETCURSEL, OnCBSetCurSel)
  1711. ON_WM_CTLCOLOR_REFLECT()
  1712. ON_WM_SIZE()
  1713. ON_WM_DESTROY()
  1714. ON_WM_CHARTOITEM()
  1715. ON_WM_KEYDOWN()
  1716. //}}AFX_MSG_MAP
  1717. ON_MESSAGE( WM_CTLCOLORLISTBOX, OnCtlColor )
  1718. END_MESSAGE_MAP()
  1719. /////////////////////////////////////////////////////////////////////////////
  1720. // CExtComboBoxBase message handlers
  1721. CSize CExtComboBoxBase::OnFilterPopupListQueryMinSize()
  1722. {
  1723. return CSize( 40, 20 );
  1724. }
  1725. CSize CExtComboBoxBase::OnFilterPopupListQueryMaxSize()
  1726. {
  1727. return CSize( -1, -1 );
  1728. }
  1729. CSize CExtComboBoxBase::GetFilterPopupListSize() const
  1730. {
  1731. return m_szFilterPopupListBox;
  1732. }
  1733. CSize CExtComboBoxBase::SetFilterPopupListSize( CSize szSize )
  1734. {
  1735. CSize szFilterPopupListBoxOld = m_szFilterPopupListBox;
  1736. m_szFilterPopupListBox = szSize;
  1737. return szFilterPopupListBoxOld;
  1738. }
  1739. bool CExtComboBoxBase::OnHookSpyPreTranslateMessage(
  1740. MSG * pMSG
  1741. )
  1742. {
  1743. ASSERT( pMSG != NULL );
  1744. // if( m_hWnd == NULL 
  1745. // || (!::IsWindow( m_hWnd ))
  1746. // || m_pPopupListWnd->GetSafeHwnd() == NULL 
  1747. // || (!::IsWindow( m_pPopupListWnd->m_hWnd ))
  1748. // || (!m_pPopupListWnd->IsWindowVisible())
  1749. // )
  1750. // return CExtHookSpy::OnHookSpyPreTranslateMessage( pMSG );
  1751. if( m_hWnd != NULL
  1752. && ( GetStyle() & WS_VISIBLE ) != 0
  1753. && ( pMSG->hwnd == m_hWnd 
  1754. || ::IsChild( m_hWnd, pMSG->hwnd )
  1755. || ::GetParent( m_hWnd ) == pMSG->hwnd
  1756. )
  1757. )
  1758. {
  1759. if( pMSG->message == WM_ACTIVATEAPP
  1760. || pMSG->message == WM_CANCELMODE
  1761. || pMSG->message == WM_SETFOCUS
  1762. || pMSG->message == WM_KILLFOCUS
  1763. || pMSG->message == WM_SYSCOMMAND
  1764. || pMSG->message == WM_STYLECHANGING
  1765. || pMSG->message == WM_STYLECHANGED
  1766. || pMSG->message == WM_CLOSE
  1767. || pMSG->message == WM_DESTROY
  1768. || pMSG->message == WM_NCDESTROY
  1769. || pMSG->message == WM_ENABLE
  1770. || pMSG->message == WM_SIZE
  1771. || pMSG->message == WM_NEXTDLGCTL
  1772. || pMSG->message == WM_LBUTTONDOWN
  1773. || pMSG->message == WM_RBUTTONDOWN
  1774. || pMSG->message == WM_MBUTTONDOWN
  1775. || CExtPopupMenuWnd::IsMenuTracking()
  1776. || CExtControlBar::_DraggingGetBar() != NULL
  1777. || ( ( pMSG->message == WM_WINDOWPOSCHANGING
  1778. || pMSG->message == WM_WINDOWPOSCHANGED
  1779. )
  1780. && ( ((LPWINDOWPOS)pMSG->lParam)->flags&(SWP_NOMOVE|SWP_NOSIZE) ) == 0
  1781. )
  1782. || ( ( pMSG->message == WM_ACTIVATE || pMSG->message == WM_MOUSEACTIVATE )
  1783. && (! ::IsChild( m_hWnd, pMSG->hwnd ) ) 
  1784. )
  1785. )
  1786. {
  1787. OnFilterPopupListClose();
  1788. return true;
  1789. }
  1790. }
  1791. return CExtHookSpy::OnHookSpyPreTranslateMessage( pMSG );
  1792. }
  1793. HWND CExtComboBoxBase::AnimationSite_GetSafeHWND() const
  1794. {
  1795. __PROF_UIS_MANAGE_STATE;
  1796. HWND hWnd = GetSafeHwnd();
  1797. return hWnd;
  1798. }
  1799. void CExtComboBoxBase::ShowFilterPopupList( 
  1800. CExtSafeString & sFilterText 
  1801. )
  1802. {
  1803. ASSERT_VALID( this );
  1804. if( m_pPopupListWnd->GetSafeHwnd() == NULL
  1805. || (!::IsWindow( m_pPopupListWnd->m_hWnd ))
  1806. )
  1807. m_pPopupListWnd = OnFilterPopupListCreate();
  1808. if( m_pPopupListWnd == NULL )
  1809. {
  1810. ASSERT( FALSE );
  1811. return;
  1812. }
  1813. ASSERT_VALID( m_pPopupListWnd );
  1814. OnFilterPopupListSyncContents( sFilterText );
  1815. if( sFilterText.IsEmpty()
  1816. || m_pPopupListWnd->GetCount() == 0 
  1817. )
  1818. {
  1819. OnFilterPopupListClose();
  1820. }
  1821. else
  1822. {
  1823. if( ! m_pPopupListWnd->IsWindowVisible() )
  1824. {
  1825. CRect rcWnd;
  1826. GetWindowRect( &rcWnd );
  1827. CSize szMax = OnFilterPopupListQueryMaxSize();
  1828. szMax.cx = szMax.cx > 0 ? szMax.cx : 150;
  1829. szMax.cy = szMax.cy > 0 ? szMax.cy : 100;
  1830. if( m_szFilterPopupListBox.cx < 0 )
  1831. m_szFilterPopupListBox.cx = max( rcWnd.Width(), szMax.cx );
  1832. if( m_szFilterPopupListBox.cy < 0 )
  1833. m_szFilterPopupListBox.cy = max( ::MulDiv( rcWnd.Width(), 2, 3 ), szMax.cy );
  1834. CRect rcPopupListWnd(
  1835. rcWnd.left,
  1836. rcWnd.bottom,
  1837. rcWnd.left + m_szFilterPopupListBox.cx,
  1838. rcWnd.bottom + m_szFilterPopupListBox.cy
  1839. );
  1840. rcPopupListWnd.OffsetRect( 1, 1 );
  1841. m_pPopupListWnd->SetWindowPos(
  1842. NULL,
  1843. rcWnd.left,
  1844. rcWnd.bottom,
  1845. m_szFilterPopupListBox.cx,
  1846. m_szFilterPopupListBox.cy,
  1847. SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE
  1848. );
  1849. }
  1850. }
  1851. }
  1852. CExtComboBoxFilterPopupListBox * CExtComboBoxBase::OnFilterPopupListCreate()
  1853. {
  1854. ASSERT_VALID( this );
  1855. if( m_pPopupListWnd->GetSafeHwnd() != NULL
  1856. && ::IsWindow( m_pPopupListWnd->m_hWnd )
  1857. )
  1858. return m_pPopupListWnd;
  1859. if( m_pPopupListWnd != NULL )
  1860. {
  1861. delete m_pPopupListWnd;
  1862. m_pPopupListWnd = NULL;
  1863. }
  1864. CExtNCSB < CExtComboBoxFilterPopupListBox > * pPopupListWnd = new CExtNCSB < CExtComboBoxFilterPopupListBox > ( true );
  1865. pPopupListWnd->m_pCB = this;
  1866. pPopupListWnd->m_hWndCB = m_hWnd;
  1867. if( pPopupListWnd == NULL )
  1868. {
  1869. ASSERT( FALSE );
  1870. return NULL;
  1871. }
  1872. ASSERT_VALID( pPopupListWnd );
  1873. if( !pPopupListWnd->CreateEx(
  1874. WS_EX_TOPMOST | WS_EX_WINDOWEDGE,
  1875. _T("LISTBOX"),
  1876. _T(""),
  1877. WS_POPUP | WS_BORDER | WS_VSCROLL | LBS_NOINTEGRALHEIGHT | LBS_HASSTRINGS | LBS_OWNERDRAWVARIABLE,
  1878. CRect(0,0,0,0),
  1879. this,
  1880. UINT(0)
  1881. )
  1882. )
  1883. {
  1884. ASSERT( FALSE );
  1885. return NULL;
  1886. }
  1887. pPopupListWnd->SetFont( 
  1888. CFont::FromHandle( (HFONT)::GetStockObject(DEFAULT_GUI_FONT) ) 
  1889. );
  1890. return pPopupListWnd;
  1891. }
  1892. void CExtComboBoxBase::OnFilterPopupListClose()
  1893. {
  1894. ASSERT_VALID( this );
  1895. if( m_pPopupListWnd->GetSafeHwnd() != NULL 
  1896. && ::IsWindow( m_pPopupListWnd->m_hWnd )
  1897. && m_pPopupListWnd->IsWindowVisible()
  1898. )
  1899. {
  1900. CRect rcWnd;
  1901. m_pPopupListWnd->GetWindowRect( &rcWnd );
  1902. m_szFilterPopupListBox = rcWnd.Size();
  1903. m_pPopupListWnd->SetWindowPos(
  1904. NULL,
  1905. 0,0,0,0,
  1906. SWP_HIDEWINDOW | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  1907. );
  1908. }
  1909. }
  1910. void CExtComboBoxBase::OnFilterPopupListSyncContents(
  1911. CExtSafeString & sFilterText
  1912. )
  1913. {
  1914. ASSERT_VALID( this );
  1915. if( m_pPopupListWnd->GetSafeHwnd() == NULL 
  1916. || (!::IsWindow( m_pPopupListWnd->m_hWnd ))
  1917. )
  1918. return;
  1919. m_pPopupListWnd->SetRedraw( FALSE );
  1920. m_pPopupListWnd->ResetContent();
  1921. if( !sFilterText.IsEmpty() )
  1922. {
  1923. CStringArray arrTextToRemove; 
  1924. arrTextToRemove.Add( _T("http://") );
  1925. arrTextToRemove.Add( _T("http://www.") );
  1926. arrTextToRemove.Add( _T("ftp://") );
  1927. arrTextToRemove.Add( _T("ftp://www.") );
  1928. arrTextToRemove.Add( _T("file://") );
  1929. arrTextToRemove.Add( _T("www.") );
  1930. INT nLenght = sFilterText.GetLength();
  1931. CString sItemText;
  1932. INT nCount = GetCount();
  1933. for( LONG nItem = 0; nItem < nCount; nItem++ )
  1934. {
  1935. sItemText.Empty();
  1936. GetLBText( nItem, sItemText );
  1937. CString sItemTextToCompare = sItemText;
  1938. for( INT nIndex = 0; nIndex < arrTextToRemove.GetSize(); nIndex++ ) 
  1939. {
  1940. CString sTextToRemove = arrTextToRemove[ nIndex ];
  1941. INT nLenght = sTextToRemove.GetLength();
  1942. CString sItemTextPart = sItemTextToCompare.Left( nLenght );
  1943. if( sItemTextPart.CompareNoCase( sTextToRemove ) == 0 )
  1944. sItemTextToCompare.Delete( 0, nLenght );
  1945. }
  1946. if( sFilterText.CompareNoCase( sItemTextToCompare.Left( nLenght ) ) == 0 )
  1947. {
  1948. INT nItemAdded = m_pPopupListWnd->AddString( sItemText );
  1949. CExtComboBoxFilterPopupListBox::LB_ITEM * pFLbItem = 
  1950. m_pPopupListWnd->LbItemGet( nItemAdded );
  1951. ASSERT( pFLbItem != NULL );
  1952. if( pFLbItem != NULL )
  1953. {
  1954. LB_ITEM * pLbItem = LbItemGet( nItem );
  1955. pFLbItem->LParamSet( (LPARAM) pLbItem  );
  1956. }
  1957. }
  1958. }
  1959. } // if( !sFilterText.IsEmpty() )
  1960. m_pPopupListWnd->SetRedraw( TRUE );
  1961. m_pPopupListWnd->Invalidate();
  1962. m_pPopupListWnd->UpdateWindow();
  1963. }
  1964. BOOL CExtComboBoxBase::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
  1965. {
  1966. ASSERT_VALID( this );
  1967. if( message == WM_COMMAND )
  1968. {
  1969. INT nCode = HIWORD(wParam);
  1970. switch( nCode )
  1971. {
  1972. case CBN_DROPDOWN:
  1973. OnFilterPopupListClose();
  1974. break;
  1975.         case CBN_SELENDOK:
  1976. {
  1977. DWORD dwWndStyle = GetStyle();
  1978. if( ( dwWndStyle & (CBS_OWNERDRAWFIXED|CBS_OWNERDRAWVARIABLE) ) == 0
  1979. || ( dwWndStyle & CBS_HASSTRINGS ) != 0
  1980. )
  1981. {
  1982. GetWindowText( m_sSavedText );
  1983. PostMessage( __EXT_COMBO_BOX_WM_USER_REALSELENDOK );
  1984. }
  1985. }
  1986. break;
  1987. case CBN_EDITUPDATE:
  1988. OnEditCtrlUpdate();
  1989.     break;
  1990. }
  1991. }
  1992. return CComboBox::OnChildNotify(message, wParam, lParam, pLResult);
  1993. }
  1994. LONG CExtComboBoxBase::FindItemExact(
  1995. __EXT_MFC_SAFE_LPCTSTR lpszString,
  1996. LONG nIndexStart // = -1
  1997. ) const
  1998. {
  1999. ASSERT_VALID( this );
  2000. LONG nCount = GetCount();
  2001. if( nIndexStart < -1 || nIndexStart >= nCount )
  2002. {
  2003. ASSERT( FALSE );
  2004. return CB_ERR;
  2005. }
  2006. LONG nItemsProcessed = 0;
  2007. LONG nItem = nIndexStart;
  2008. while( nItemsProcessed < nCount )
  2009. {
  2010. if( nItem == -1 )
  2011. nItem = 0;
  2012. else if( nItem < nCount - 1 )
  2013. nItem++;
  2014. else
  2015. nItem = 0;
  2016. CString sText;
  2017. GetLBText( nItem, sText );
  2018. if( sText.Compare( lpszString ) == 0 )
  2019. return nItem;
  2020. nItemsProcessed++;
  2021. }
  2022. return CB_ERR;
  2023. }
  2024. void CExtComboBoxBase::OnFilterPopupListSyncSelection( 
  2025. bool bSetEditSel // = true
  2026. )
  2027. {
  2028. ASSERT_VALID( this );
  2029. if( m_pPopupListWnd->GetSafeHwnd() == NULL 
  2030. || (!::IsWindow( m_pPopupListWnd->m_hWnd ))
  2031. )
  2032. return;
  2033. INT nItem = m_pPopupListWnd->GetCurSel();
  2034. CExtComboBoxFilterPopupListBox::LB_ITEM * pFLbItem = 
  2035. m_pPopupListWnd->LbItemGet( nItem );
  2036. ASSERT( pFLbItem != NULL );
  2037. CExtComboBoxBase::LB_ITEM * pLbItemNew = NULL;
  2038. if( pFLbItem != NULL )
  2039. pLbItemNew = (CExtComboBoxBase::LB_ITEM *) pFLbItem->LParamGet();
  2040. ASSERT( pLbItemNew != NULL );
  2041. INT nCount = GetCount();
  2042. for( LONG nIndex = 0; nIndex < nCount; nIndex++ )
  2043. {
  2044. LB_ITEM * pLbItem = LbItemGet( nIndex );
  2045. if( pLbItem == pLbItemNew )
  2046. {
  2047. CEdit * pEdit = GetInnerEditCtrl();
  2048. if( pEdit != NULL )
  2049. {
  2050. ASSERT_VALID( pEdit );
  2051. pEdit->SetRedraw( FALSE );
  2052. }
  2053. SetCurSel( nIndex );
  2054. // make text non-selected
  2055. if( ! bSetEditSel )
  2056. SetEditSel( -1, -1 );
  2057. if( pEdit != NULL )
  2058. {
  2059. ASSERT_VALID( pEdit );
  2060. pEdit->SetRedraw( TRUE );
  2061. pEdit->Invalidate();
  2062. pEdit->UpdateWindow();
  2063. }
  2064. break;
  2065. }
  2066. }
  2067. }
  2068. void CExtComboBoxBase::OnFilterPopupListSelChanged()
  2069. {
  2070. ASSERT_VALID( this );
  2071. OnFilterPopupListSyncSelection( false );
  2072. }
  2073. void CExtComboBoxBase::OnFilterPopupListSelEndOK()
  2074. {
  2075. ASSERT_VALID( this );
  2076. if( m_pPopupListWnd->GetSafeHwnd() == NULL 
  2077. || (!::IsWindow( m_pPopupListWnd->m_hWnd ))
  2078. )
  2079. return;
  2080. OnFilterPopupListSyncSelection( true );
  2081. OnFilterPopupListClose();
  2082. // send the CBN_SELENDOK notification
  2083. GetParent()->SendMessage( 
  2084. WM_COMMAND,
  2085. (WPARAM) MAKELONG( GetDlgCtrlID(), CBN_SELENDOK ),
  2086. (LPARAM) GetSafeHwnd()
  2087. );
  2088. }
  2089. void CExtComboBoxBase::_OnDrawComboImpl(
  2090. bool bPressed,
  2091. bool bHover,
  2092. CDC * pDC // = NULL
  2093. )
  2094. {
  2095. bPressed; bHover; pDC;
  2096. }
  2097. BOOL CExtComboBoxBase::PreTranslateMessage(MSG* pMsg) 
  2098. {
  2099. if( !CExtPopupMenuWnd::IsMenuTracking() )
  2100. {
  2101. InitToolTip();
  2102. m_wndToolTip.RelayEvent(pMsg);
  2103. }
  2104. if( m_pPopupListWnd->GetSafeHwnd() != NULL 
  2105. && ::IsWindow( m_pPopupListWnd->m_hWnd )
  2106. && m_pPopupListWnd->IsWindowVisible()
  2107. )
  2108. {
  2109. if( pMsg->message == WM_KEYDOWN 
  2110. && ( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN )
  2111. )
  2112. {
  2113. HWND hWndFocus = ::GetFocus();
  2114. if( hWndFocus != NULL
  2115. && ( m_hWnd == hWndFocus
  2116. || ::IsChild( m_hWnd, hWndFocus )
  2117. )
  2118. )
  2119. {
  2120. if( pMsg->wParam == VK_ESCAPE )
  2121. OnFilterPopupListClose();
  2122. else if( pMsg->wParam == VK_RETURN )
  2123. {
  2124. INT nItem = m_pPopupListWnd->GetCurSel();
  2125. if( nItem == LB_ERR 
  2126. && m_pPopupListWnd->GetCount() > 0
  2127. m_pPopupListWnd->SetCurSel( 0 );
  2128. OnFilterPopupListSelEndOK();
  2129. }
  2130. return TRUE;
  2131. }
  2132. }
  2133. if( ( pMsg->message == WM_KEYDOWN 
  2134. && ( pMsg->wParam == VK_DOWN 
  2135. || pMsg->wParam == VK_UP 
  2136. || pMsg->wParam == VK_PRIOR 
  2137. || pMsg->wParam == VK_NEXT
  2138. )
  2139. )
  2140. || pMsg->message == WM_MOUSEWHEEL
  2141. )
  2142. {
  2143. INT nCurSelOld = m_pPopupListWnd->GetCurSel();
  2144. m_pPopupListWnd->SetRedraw( FALSE );
  2145. m_pPopupListWnd->SendMessage( 
  2146. pMsg->message,
  2147. pMsg->wParam,
  2148. pMsg->lParam
  2149. );
  2150. m_pPopupListWnd->SetRedraw( TRUE );
  2151. m_pPopupListWnd->RedrawWindow(
  2152. NULL,
  2153. NULL,
  2154. RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ERASENOW|RDW_FRAME
  2155. );
  2156. //_OnDrawComboImpl( false, false );
  2157. INT nCurSelNew = m_pPopupListWnd->GetCurSel();
  2158. if( nCurSelOld != nCurSelNew )
  2159. OnFilterPopupListSelChanged();
  2160. return TRUE;
  2161. }
  2162. }
  2163. if( m_bEnableAutoComplete )
  2164. {
  2165. if( pMsg->message == WM_SYSCHAR )
  2166. return FALSE;
  2167. if( pMsg->message == WM_KEYDOWN )
  2168. {
  2169. if( pMsg->wParam == VK_DELETE
  2170. || pMsg->wParam == VK_BACK
  2171. )
  2172. m_bAutoComplete = false;
  2173. else
  2174. m_bAutoComplete = true;
  2175. }
  2176. }
  2177. else
  2178. {
  2179. m_bAutoComplete = false;
  2180. }
  2181. return CComboBox::PreTranslateMessage(pMsg);
  2182. }
  2183. void CExtComboBoxBase::OnEditCtrlUpdate() 
  2184. {
  2185. if( m_bEnableAutoFilter )
  2186. {
  2187. CEdit * pEdit = GetInnerEditCtrl();
  2188. if( pEdit != NULL )
  2189. {
  2190. ASSERT_VALID( pEdit );
  2191. CString sFilterText;
  2192. pEdit->GetWindowText( sFilterText );
  2193. INT nStartChar = 0;
  2194. INT nEndChar = 0;
  2195. pEdit->GetSel(
  2196. nStartChar,
  2197. nEndChar 
  2198. ) ;
  2199. if( nStartChar < nEndChar )
  2200. sFilterText.Delete( nStartChar, nEndChar - nStartChar );
  2201. sFilterText.TrimLeft();
  2202. if( ! GetDroppedState() )
  2203. {
  2204. CExtSafeString _sFilterText = LPCTSTR(sFilterText);
  2205. ShowFilterPopupList( _sFilterText );
  2206. }
  2207. }
  2208. }
  2209. if( ! m_bEnableAutoComplete )
  2210. {
  2211. Default();
  2212. return;
  2213. }
  2214. PostMessage( __EXT_COMBO_BOX_WM_USER_AUTOCOMPLETE, m_bAutoComplete ? 1L : 0L, 0L );
  2215. }
  2216. void CExtComboBoxBase::OnSize(UINT nType, int cx, int cy) 
  2217. {
  2218. AnimationSite_ClientProgressStop( this );
  2219. AnimationClient_StateGet( false ).Empty();
  2220. AnimationClient_StateGet( true ).Empty();
  2221. CRect rcClient;
  2222. GetClientRect( &rcClient );
  2223. AnimationClient_TargetRectSet( rcClient );
  2224. CComboBox::OnSize( nType, cx, cy );
  2225. }
  2226. void CExtComboBoxBase::OnDestroy() 
  2227. {
  2228. HookSpyUnregister();
  2229. LbItemRemoveAll();
  2230. CComboBox::OnDestroy();
  2231. }
  2232. int CExtComboBoxBase::OnCharToItem(UINT nChar, CListBox* pListBox, UINT nIndex) 
  2233. {
  2234. INT nRet = CComboBox::OnCharToItem( nChar, pListBox, nIndex );
  2235. if( nRet >= 0 
  2236. && ( !LbItemIsEnabled( nRet ) )
  2237. )
  2238. return -2;
  2239. else
  2240. return nRet;
  2241. }
  2242. LRESULT CExtComboBoxBase::OnCtlColor(WPARAM wParam, LPARAM lParam)
  2243. {
  2244. ASSERT_VALID( this );
  2245. wParam;
  2246. bool bSimpleMode = false;
  2247. DWORD dwStyle = GetStyle();
  2248. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  2249. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  2250. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST 
  2251. )
  2252. bSimpleMode = true;
  2253. if( (!bSimpleMode)
  2254. && lParam != 0L 
  2255. && lParam != (LPARAM)m_hWnd
  2256. && FromHandlePermanent( (HWND)lParam ) == NULL
  2257. )
  2258. OnComboBoxPopupListBoxQuery( (HWND)lParam );
  2259. return Default();
  2260. }
  2261. void CExtComboBoxBase::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) 
  2262. {
  2263. ASSERT_VALID( this );
  2264. if( ! GetDroppedState() )
  2265. {
  2266. bool bSelChanged = false;
  2267. switch( nChar )
  2268. {
  2269. case VK_LEFT:
  2270. case VK_UP:
  2271. {
  2272. // Go up until we find a valid selection
  2273. // then set the current selection to that one
  2274. INT nCurSel = GetCurSel();
  2275. INT nSel = nCurSel;
  2276. bool bInitSelection = false;
  2277. INT nCount = GetCount();
  2278. if( nSel < 0 && nCount > 0 )
  2279. {
  2280. nSel = nCount - 1;
  2281. bInitSelection = true;
  2282. }
  2283. if( nSel != CB_ERR )
  2284. {
  2285. while( nSel > 0 )
  2286. {
  2287. INT nItem = nSel - ( bInitSelection ? 0 : 1 );
  2288. if( LbItemIsEnabled( nItem ) )
  2289. {
  2290. if( nCurSel != nItem )
  2291. {
  2292. INT nRealSel = SetCurSel( nItem );
  2293. if( nCurSel != nRealSel )
  2294. bSelChanged = true;
  2295. }
  2296. break;
  2297. }
  2298. nSel--;
  2299. }
  2300. }
  2301. }
  2302. break;
  2303. case VK_RIGHT:
  2304. case VK_DOWN:
  2305. {
  2306. // Go down until we find a valid selection
  2307. // then set the current selection to that one
  2308. INT nCurSel = GetCurSel();
  2309. INT nSel = nCurSel;
  2310. bool bInitSelection = false;
  2311. INT nCount = GetCount();
  2312. if( nSel < 0 && nCount > 0 )
  2313. {
  2314. nSel = 0;
  2315. bInitSelection = true;
  2316. }
  2317. if( nSel != CB_ERR )
  2318. {
  2319. while( nSel < nCount - 1 )
  2320. {
  2321. INT nItem = nSel + ( bInitSelection ? 0 : 1 );
  2322. if( nItem == nCount )
  2323. break;
  2324. if( LbItemIsEnabled( nItem ) )
  2325. {
  2326. if( nCurSel != nItem )
  2327. {
  2328. INT nRealSel = SetCurSel( nItem );
  2329. if( nCurSel != nRealSel )
  2330. bSelChanged = true;
  2331. }
  2332. break;
  2333. }
  2334. nSel++;
  2335. }
  2336. }
  2337. }
  2338. break;
  2339. case VK_HOME:
  2340. case VK_PRIOR:
  2341. {
  2342. // Select first non-disabled item
  2343. INT nCurSel = GetCurSel();
  2344. INT nSel = 0;
  2345. INT nCount = GetCount();
  2346. while( nSel < nCount - 1 )
  2347. {
  2348. INT nItem = nSel;
  2349. if( LbItemIsEnabled( nItem ) )
  2350. {
  2351. if( nCurSel != nItem )
  2352. {
  2353. INT nRealSel = SetCurSel( nItem );
  2354. if( nCurSel != nRealSel )
  2355. bSelChanged = true;
  2356. }
  2357. break;
  2358. }
  2359. nSel++;
  2360. }
  2361. }
  2362. break;
  2363. case VK_END:
  2364. case VK_NEXT:
  2365. {
  2366. // Select last non-disabled item
  2367. INT nCurSel = GetCurSel();
  2368. INT nCount = GetCount();
  2369. INT nSel = nCount;
  2370. while( nSel > 0 )
  2371. {
  2372. INT nItem = nSel - 1;
  2373. if( LbItemIsEnabled( nItem ) )
  2374. {
  2375. if( nCurSel != nItem )
  2376. {
  2377. INT nRealSel = SetCurSel( nItem );
  2378. if( nCurSel != nRealSel )
  2379. bSelChanged = true;
  2380. }
  2381. break;
  2382. }
  2383. nSel--;
  2384. }
  2385. }
  2386. break;
  2387. default:
  2388. CComboBox::OnKeyDown( nChar, nRepCnt, nFlags );
  2389. return;
  2390. }
  2391. if( bSelChanged )
  2392. {
  2393. // The CBN_SELCHANGE notification message is not sent when the selection 
  2394. // is changed using the CB_SETCURSEL message. 
  2395. if( ! m_bEnableSelChangeWorkaround  )
  2396. {
  2397. CWnd * pWnd = GetParent();
  2398. if( pWnd->GetSafeHwnd() != NULL )
  2399. {
  2400. ASSERT_VALID( pWnd );
  2401. pWnd->SendMessage(
  2402. WM_COMMAND,
  2403. MAKEWPARAM( GetDlgCtrlID(), CBN_SELENDOK ),
  2404. (LPARAM) m_hWnd
  2405. );
  2406. pWnd->SendMessage(
  2407. WM_COMMAND,
  2408. MAKEWPARAM( GetDlgCtrlID(), CBN_SELCHANGE ),
  2409. (LPARAM) m_hWnd
  2410. );
  2411. }
  2412. }
  2413. }
  2414. return;
  2415. } // if( ! GetDroppedState() )
  2416. CComboBox::OnKeyDown( nChar, nRepCnt, nFlags );
  2417. }
  2418. bool CExtComboBoxBase::_CreateHelper()
  2419. {
  2420. if( m_bInitialized )
  2421. return true;
  2422. OnSubclassInnerEdit();
  2423. HookSpyRegister( __EHSEF_WND_PROC_IN|__EHSEF_KEYBOARD|__EHSEF_PRE_TRANSLATION );
  2424. m_bInitialized = true;
  2425. return true;
  2426. }
  2427. LRESULT CExtComboBoxBase::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
  2428. {
  2429. switch( message )
  2430. {
  2431. case WM_NOTIFY:
  2432. if( m_wndToolTip.GetSafeHwnd() != NULL
  2433. && IsWindow( m_wndToolTip.GetSafeHwnd() )
  2434. && ((LPNMHDR)lParam) != NULL
  2435. && ((LPNMHDR)lParam)->hwndFrom == m_wndToolTip.GetSafeHwnd()
  2436. && ((LPNMHDR)lParam)->code == TTN_SHOW
  2437. )
  2438. ::SetWindowPos(
  2439. m_wndToolTip.GetSafeHwnd(),
  2440. HWND_TOP,
  2441. 0,0,0,0,
  2442. SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE
  2443. );
  2444. break;
  2445. case WM_ENABLE:
  2446. {
  2447. HWND hWndEdit =
  2448. ::GetWindow( GetSafeHwnd(), GW_CHILD );
  2449. if( hWndEdit == NULL || !::IsWindow(hWndEdit) )
  2450. break;
  2451. ::EnableWindow( hWndEdit, TRUE );
  2452. ::SendMessage( hWndEdit, EM_SETREADONLY, !wParam, 0L );
  2453. Invalidate();
  2454. }
  2455. break;
  2456. case WM_CREATE:
  2457. {
  2458. LRESULT lResult =
  2459. CComboBox::WindowProc(message, wParam, lParam);;
  2460. if( ! _CreateHelper() )
  2461. {
  2462. ASSERT( FALSE );
  2463. ::AfxThrowMemoryException();
  2464. }
  2465. return lResult;
  2466. }
  2467. case __EXT_COMBO_BOX_WM_USER_REALSELENDOK:
  2468. {
  2469. CString sCurrentText;
  2470. GetWindowText( sCurrentText );
  2471. INT nIndex = FindStringExact( -1, sCurrentText );
  2472. if( nIndex >=0 
  2473. &&  ( !LbItemIsEnabled( nIndex ) ) 
  2474. )
  2475. {
  2476. SetWindowText( m_sSavedText );
  2477. // send the CBN_SELCHANGE notification
  2478. GetParent()->SendMessage( 
  2479. WM_COMMAND,
  2480. (WPARAM) MAKELONG( GetDlgCtrlID(), CBN_SELCHANGE ),
  2481. (LPARAM) GetSafeHwnd()
  2482. );
  2483. }
  2484. return 0L;
  2485. }
  2486. case __EXT_COMBO_BOX_WM_USER_AUTOCOMPLETE:
  2487. {
  2488. bool bAutoComplete = ( wParam > 0L ) ? true : false;
  2489. DWORD dwCurSel = GetEditSel();
  2490. WORD dStart = LOWORD( dwCurSel );
  2491. WORD dEnd   = HIWORD( dwCurSel );
  2492. CString str;
  2493. GetWindowText( str );
  2494. INT nLength = INT( str.GetLength() );
  2495. INT nResult = FindString( -1, str );
  2496. if( m_bUseCaseSensitiveAutoComplete && nResult >= 0 )
  2497. {
  2498. CString sItem;
  2499. INT nCount = INT( GetCount() );
  2500. for( ; 0 <= nResult && nResult < nCount; nResult ++ )
  2501. {
  2502. GetLBText( nResult, sItem );
  2503. INT nItemLength = INT( sItem.GetLength() );
  2504. if( nItemLength >= nLength )
  2505. {
  2506. if( nItemLength > nLength )
  2507. sItem = sItem.Left( nLength );
  2508. if( str == sItem )
  2509. break;
  2510. }
  2511. }
  2512. if( ! ( 0 <= nResult && nResult < nCount ) )
  2513. nResult = -1;
  2514. }
  2515. CEdit * pEdit = GetInnerEditCtrl();
  2516. if( pEdit != NULL )
  2517. {
  2518. ASSERT_VALID( pEdit );
  2519. pEdit->SetRedraw( FALSE );
  2520. }
  2521. CExtComboBoxPopupListBox * pComboBoxPopupListBox = OnComboBoxPopupListBoxQuery();
  2522. if( pComboBoxPopupListBox != NULL )
  2523. {
  2524. ASSERT_VALID( pComboBoxPopupListBox );
  2525. // pComboBoxPopupListBox->SendMessage( LB_SETCURSEL, nResult, 0 );
  2526. INT nRealSel = (INT)pComboBoxPopupListBox->SendMessage( LB_SETCURSEL, nResult, 0 );
  2527. if( nRealSel == LB_ERR )
  2528. pComboBoxPopupListBox->SendMessage( LB_SETTOPINDEX, 0, 0 );
  2529. }
  2530. CString sItem;
  2531. if( nResult >= 0 )
  2532. {
  2533. GetLBText( nResult, sItem );
  2534. if( ! bAutoComplete )
  2535. SetWindowText( str );
  2536. else
  2537. SetWindowText( sItem );
  2538. }
  2539. else 
  2540. {
  2541. SetWindowText( str );
  2542. if( dwCurSel != CB_ERR )
  2543. SetEditSel( dStart, dEnd );
  2544. }
  2545. if( dEnd < nLength 
  2546. && dwCurSel != CB_ERR 
  2547. )
  2548. SetEditSel( dStart, dEnd );
  2549. else
  2550. SetEditSel( nLength, -1 );
  2551. if( pEdit != NULL )
  2552. {
  2553. ASSERT_VALID( pEdit );
  2554. pEdit->SetRedraw( TRUE );
  2555. pEdit->Invalidate();
  2556. pEdit->UpdateWindow();
  2557. }
  2558. return 0L;
  2559. }
  2560. } // switch( message )
  2561. return CComboBox::WindowProc(message, wParam, lParam);
  2562. }
  2563. void CExtComboBoxBase::PreSubclassWindow() 
  2564. {
  2565. CComboBox::PreSubclassWindow();
  2566. if( ! _CreateHelper() )
  2567. {
  2568. ASSERT( FALSE );
  2569. ::AfxThrowMemoryException();
  2570. }
  2571. bool bSimpleMode = false;
  2572. DWORD dwStyle = GetStyle();
  2573. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  2574. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  2575. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST 
  2576. )
  2577. bSimpleMode = true;
  2578. if( bSimpleMode )
  2579. {
  2580. HWND hWnd = ::GetWindow( m_hWnd, GW_CHILD );
  2581. for( ; hWnd != NULL; hWnd = ::GetWindow( hWnd, GW_HWNDNEXT ) )
  2582. {
  2583. TCHAR strClassName[ MAX_PATH + 1 ] = _T("");
  2584. ::GetClassName(
  2585. hWnd,
  2586. strClassName,
  2587. MAX_PATH
  2588. );
  2589. __EXT_MFC_STRLWR( strClassName, MAX_PATH );
  2590. if( _tcscmp( strClassName, _T("combolbox") ) == 0 )
  2591. {
  2592. OnComboBoxPopupListBoxQuery( hWnd );
  2593. break;
  2594. } // if( _tcscmp( strClassName, _T("combolbox") ) == 0 )
  2595. } // for( ; hWnd != NULL; hWnd = ::GetWindow( hWnd, GW_HWNDNEXT ) )
  2596. } // if( bSimpleMode )
  2597. if( (dwStyle&WS_CLIPCHILDREN) == 0 )
  2598. ModifyStyle( 0, WS_CLIPCHILDREN, SWP_FRAMECHANGED );
  2599. // INT nCount = GetCount();
  2600. //  for( LONG nItem = 0; nItem < nCount; nItem++ )
  2601. //  {
  2602. //  LB_ITEM * pLbItem = LbItemGet( nItem );
  2603. //  if( pLbItem == NULL )
  2604. //  {
  2605. //  CString sString;
  2606. //  GetLBText( nItem, sString );
  2607. //  LbItemSet( nItem, sString );
  2608. //  }
  2609. //  }
  2610.  
  2611. AnimationSite_ClientProgressStop( this );
  2612. AnimationClient_StateGet( false ).Empty();
  2613. AnimationClient_StateGet( true ).Empty();
  2614. CRect rectButton;
  2615. GetClientRect( &rectButton );
  2616. AnimationClient_TargetRectSet( rectButton );
  2617. }
  2618. void CExtComboBoxBase::PostNcDestroy() 
  2619. {
  2620. if( m_pWndPopupListBox != NULL )
  2621. {
  2622. if( m_hWndPopupListBox != NULL
  2623. && ::IsWindow( m_hWndPopupListBox )
  2624. && LPVOID( CWnd::FromHandlePermanent(m_hWndPopupListBox) ) == LPVOID( m_pWndPopupListBox )
  2625. )
  2626. m_pWndPopupListBox->m_pCB = NULL;
  2627. }
  2628. m_pWndPopupListBox = NULL;
  2629. m_hWndPopupListBox = NULL;
  2630. CComboBox::PostNcDestroy();
  2631. }
  2632. void CExtComboBoxBase::OnSubclassInnerEdit()
  2633. {
  2634. if( m_wndInnerEditHook.GetSafeHwnd() == NULL )
  2635. {
  2636. HWND hWnd = ::GetWindow( m_hWnd, GW_CHILD );
  2637. for( ; hWnd != NULL; hWnd = ::GetWindow( hWnd, GW_HWNDNEXT ) )
  2638. {
  2639. TCHAR strClassName[ MAX_PATH + 1 ] = _T("");
  2640. ::GetClassName(
  2641. hWnd,
  2642. strClassName,
  2643. MAX_PATH
  2644. );
  2645. __EXT_MFC_STRLWR( strClassName, MAX_PATH );
  2646. if( _tcscmp( strClassName, _T("edit") ) == 0 )
  2647. {
  2648. m_wndInnerEditHook.m_bHandleCtxMenus = m_bHandleCtxMenus;
  2649. VERIFY( m_wndInnerEditHook.SubclassWindow( hWnd ) );
  2650. break;
  2651. } // if( _tcscmp( strClassName, _T("edit") ) == 0 )
  2652. } // for( ; hWnd != NULL; hWnd = ::GetWindow( hWnd, GW_HWNDNEXT ) )
  2653. } // if( m_wndInnerEditHook.GetSafeHwnd() == NULL )
  2654. }
  2655. __EXT_MFC_INT_PTR CExtComboBoxBase::OnToolHitTest(
  2656. CPoint point,
  2657. TOOLINFO * pTI
  2658. ) const
  2659. {
  2660. __PROF_UIS_MANAGE_STATE;
  2661. __EXT_MFC_IMPLEMENT_TT_REDIR_OnToolHitTest( CExtComboBoxBase, CExtToolControlBar );
  2662. return CComboBox::OnToolHitTest( point, pTI );
  2663. }
  2664. void CExtComboBoxBase::InitToolTip()
  2665. {
  2666. if( m_wndToolTip.m_hWnd == NULL )
  2667. {
  2668. m_wndToolTip.Create(this);
  2669. m_wndToolTip.Activate(FALSE);
  2670. }
  2671. }
  2672. void CExtComboBoxBase::ActivateTooltip(BOOL bActivate)
  2673. {
  2674. if( m_wndToolTip.GetToolCount() == 0 )
  2675. return;
  2676. m_wndToolTip.Activate(bActivate);
  2677. }
  2678. int CExtComboBoxBase::OnQueryMaxTipWidth( 
  2679. __EXT_MFC_SAFE_LPCTSTR lpszText 
  2680. )
  2681. {
  2682. lpszText;
  2683. return 250;
  2684. }
  2685. void CExtComboBoxBase::SetTooltipText(
  2686. CExtSafeString * spText,
  2687. BOOL bActivate // = TRUE
  2688. )
  2689. {
  2690. if( spText == NULL )
  2691. return;
  2692. InitToolTip();
  2693. if( m_wndToolTip.GetToolCount() == 0 )
  2694. {
  2695. CRect rectBtn; 
  2696. GetClientRect(rectBtn);
  2697. m_wndToolTip.AddTool( this, *spText, rectBtn, 1 );
  2698. }
  2699. CWnd::CancelToolTips();
  2700. m_wndToolTip.UpdateTipText( *spText, this, 1 );
  2701. m_wndToolTip.SetMaxTipWidth( -1 );
  2702. if( spText->Find( _T("r") ) >= 0 )
  2703. m_wndToolTip.SetMaxTipWidth( OnQueryMaxTipWidth( *spText ) );
  2704. m_wndToolTip.Activate(bActivate);
  2705. }
  2706. void CExtComboBoxBase::SetTooltipText(
  2707. CExtSafeString & sText,
  2708. BOOL bActivate // = TRUE
  2709. )
  2710. {
  2711. if( sText.IsEmpty() )
  2712. return;
  2713. InitToolTip();
  2714. if( m_wndToolTip.GetToolCount() == 0 )
  2715. {
  2716. CRect rectBtn; 
  2717. GetClientRect(rectBtn);
  2718. m_wndToolTip.AddTool( this, sText, rectBtn, 1 );
  2719. }
  2720. CWnd::CancelToolTips();
  2721. m_wndToolTip.UpdateTipText( sText, this, 1 );
  2722. m_wndToolTip.SetMaxTipWidth( -1 );
  2723. if( sText.Find( _T("r") ) >= 0 )
  2724. m_wndToolTip.SetMaxTipWidth( OnQueryMaxTipWidth( sText ) );
  2725. m_wndToolTip.Activate( bActivate );
  2726. }
  2727. void CExtComboBoxBase::SetTooltipText(
  2728. __EXT_MFC_SAFE_LPCTSTR sText,
  2729. BOOL bActivate // = TRUE
  2730. )
  2731. {
  2732. if( sText == NULL
  2733. || _tcslen( sText ) == 0
  2734. )
  2735. return;
  2736. InitToolTip();
  2737. if( m_wndToolTip.GetToolCount() == 0 )
  2738. {
  2739. CRect rectBtn; 
  2740. GetClientRect(rectBtn);
  2741. m_wndToolTip.AddTool(this,sText,rectBtn,1);
  2742. }
  2743. CWnd::CancelToolTips();
  2744. m_wndToolTip.UpdateTipText(sText,this,1);
  2745. m_wndToolTip.SetMaxTipWidth( -1 );
  2746. CString strText( sText );
  2747. if( strText.Find( _T("r") ) >= 0 )
  2748. m_wndToolTip.SetMaxTipWidth( OnQueryMaxTipWidth( sText ) );
  2749. m_wndToolTip.Activate(bActivate);
  2750. }
  2751. void CExtComboBoxBase::SetTooltipText(
  2752. int nId,
  2753. BOOL bActivate // = TRUE
  2754. )
  2755. {
  2756. CExtSafeString sText;
  2757. g_ResourceManager->LoadString( sText, nId );
  2758. if( ! sText.IsEmpty() )
  2759. SetTooltipText( &sText, bActivate );
  2760. }
  2761. COLORREF CExtComboBoxBase::OnQueryBackColor() const
  2762. ASSERT_VALID( this );
  2763. return m_clrBack; 
  2764. }
  2765. COLORREF CExtComboBoxBase::OnQueryTextColor() const
  2766. ASSERT_VALID( this );
  2767. return m_clrText; 
  2768. }
  2769. void CExtComboBoxBase::SetBkColor( 
  2770. COLORREF clrBk 
  2771. )
  2772. ASSERT_VALID( this );
  2773. m_clrBack = clrBk; 
  2774. if( GetSafeHwnd() != NULL )
  2775. RedrawWindow(
  2776. NULL,
  2777. NULL,
  2778. RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ERASENOW | RDW_FRAME | RDW_ALLCHILDREN
  2779. );
  2780. }
  2781. COLORREF CExtComboBoxBase::GetBkColor() const
  2782. ASSERT_VALID( this );
  2783. return OnQueryBackColor(); 
  2784. }
  2785. void CExtComboBoxBase::SetTextColor( 
  2786. COLORREF clrText 
  2787. )
  2788. ASSERT_VALID( this );
  2789. m_clrText = clrText; 
  2790. if( GetSafeHwnd() != NULL )
  2791. Invalidate();
  2792. }
  2793. COLORREF CExtComboBoxBase::GetTextColor() const
  2794. ASSERT_VALID( this );
  2795. return OnQueryTextColor(); 
  2796. }
  2797. HBRUSH CExtComboBoxBase::CtlColor( CDC* pDC, UINT nCtlColor )
  2798. {
  2799. ASSERT_VALID( this );
  2800. if( nCtlColor == CTLCOLOR_EDIT 
  2801. || nCtlColor == CTLCOLOR_MSGBOX
  2802. || nCtlColor == CTLCOLOR_STATIC
  2803. )
  2804. {
  2805. bool bDisabled = IsWindowEnabled() ? false : true;
  2806. CExtPaintManager * pPM = PmBridge_GetPM();
  2807. ASSERT_VALID( pPM );
  2808. COLORREF clrText = GetTextColor();
  2809. if( clrText == COLORREF(-1L) )
  2810. clrText = pPM->GetColor( bDisabled ? CExtPaintManager::CLR_TEXT_DISABLED : COLOR_WINDOWTEXT );
  2811. COLORREF clrBk = GetBkColor();
  2812. if( clrBk == COLORREF(-1L) )
  2813. clrBk = pPM->GetColor( bDisabled ? COLOR_3DFACE : COLOR_WINDOW, this );
  2814. pDC->SetBkColor( clrBk );
  2815. pDC->SetTextColor( clrText );
  2816. if( m_clrBackPrev != clrBk )
  2817. {
  2818. if( m_brBack.GetSafeHandle() != NULL )
  2819. m_brBack.DeleteObject();
  2820. m_brBack.CreateSolidBrush( clrBk );
  2821. m_clrBackPrev = clrBk;
  2822. }
  2823. return m_brBack;
  2824. }
  2825. else
  2826. return (HBRUSH)Default();
  2827. }
  2828. CEdit * CExtComboBoxBase::OnQueryInnerEditCtrl() const
  2829. {
  2830. ASSERT_VALID( this );
  2831. CEdit * pEdit = NULL;
  2832. DWORD dwWndStyle = GetStyle();
  2833. DWORD dwComboBoxType = dwWndStyle & 0x0003L;
  2834. if( dwComboBoxType != CBS_DROPDOWNLIST )
  2835. {
  2836. ( const_cast < CExtComboBoxBase * > ( this ) ) -> OnSubclassInnerEdit();
  2837. if( m_wndInnerEditHook.GetSafeHwnd() != NULL )
  2838. pEdit = (CEdit *)&m_wndInnerEditHook;
  2839. }
  2840. return pEdit;
  2841. }
  2842. CEdit * CExtComboBoxBase::GetInnerEditCtrl() const
  2843. {
  2844. ASSERT_VALID( this );
  2845. return OnQueryInnerEditCtrl();
  2846. }
  2847. INT CExtComboBoxBase::AddStringUnique( 
  2848. __EXT_MFC_SAFE_LPCTSTR lpszString 
  2849. )
  2850. {
  2851. ASSERT_VALID( this );
  2852. if( CB_ERR == FindStringExact( 0, lpszString ) )
  2853. return AddString( lpszString );
  2854. return CB_ERR;
  2855. }
  2856. LRESULT CExtComboBoxBase::OnCBAddString( WPARAM wParam, LPARAM lParam )
  2857. {
  2858. ASSERT_VALID( this );
  2859. LRESULT lResult = DefWindowProc( CB_ADDSTRING, wParam, lParam );
  2860. if( lResult != CB_ERR )
  2861. LbItemInsert( __EXT_MFC_SAFE_LPCTSTR ( LPCTSTR(LPVOID(lParam)) ), (INT)lResult );
  2862. return lResult;
  2863. }
  2864. LRESULT CExtComboBoxBase::OnCBInsertString( WPARAM wParam, LPARAM lParam )
  2865. {
  2866. ASSERT_VALID( this );
  2867. LRESULT lResult = DefWindowProc( CB_INSERTSTRING, wParam, lParam );
  2868. if( lResult != CB_ERR )
  2869. LbItemInsert( __EXT_MFC_SAFE_LPCTSTR ( LPCTSTR(LPVOID(lParam)) ), (INT)lResult );
  2870. return lResult;
  2871. }
  2872. LRESULT CExtComboBoxBase::OnCBDeleteString( WPARAM wParam, LPARAM lParam )
  2873. {
  2874. ASSERT_VALID( this );
  2875. LRESULT lResult = DefWindowProc( CB_DELETESTRING, wParam, lParam );
  2876. if( lResult != LB_ERR )
  2877. LbItemRemove( (LONG)wParam );
  2878. return lResult;
  2879. }
  2880. LRESULT CExtComboBoxBase::OnCBResetContent( WPARAM wParam, LPARAM lParam )
  2881. {
  2882. ASSERT_VALID( this );
  2883. LRESULT lResult = DefWindowProc( CB_RESETCONTENT, wParam, lParam );
  2884. LbItemRemoveAll();
  2885. // Workaround for the following issue:
  2886. // The CBN_SELCHANGE notification message is not sent when the 
  2887. // current selection is unset using the CB_RESETCONTENT message. 
  2888. if( m_bEnableSelChangeWorkaround )
  2889. {
  2890. CWnd * pWnd = GetParent();
  2891. if( pWnd->GetSafeHwnd() != NULL )
  2892. {
  2893. ASSERT_VALID( pWnd );
  2894. pWnd->SendMessage(
  2895. WM_COMMAND,
  2896. MAKEWPARAM( GetDlgCtrlID(), CBN_SELCHANGE ),
  2897. (LPARAM) m_hWnd
  2898. );
  2899. }
  2900. }
  2901. return lResult;
  2902. }
  2903. LRESULT CExtComboBoxBase::OnCBSetCurSel( WPARAM wParam, LPARAM lParam )
  2904. {
  2905. ASSERT_VALID( this );
  2906. INT nCurSel = GetCurSel();
  2907. LRESULT lResult = DefWindowProc( CB_SETCURSEL, wParam, lParam );
  2908. // Workaround for the following issue:
  2909. // The CBN_SELCHANGE notification message is not sent when the 
  2910. // current selection is set using the CB_SETCURSEL message. 
  2911. if( m_bEnableSelChangeWorkaround )
  2912. {
  2913. if( lResult != CB_ERR 
  2914. && lResult != nCurSel 
  2915. )
  2916. {
  2917. CWnd * pWnd = GetParent();
  2918. if( pWnd->GetSafeHwnd() != NULL )
  2919. {
  2920. ASSERT_VALID( pWnd );
  2921. pWnd->SendMessage(
  2922. WM_COMMAND,
  2923. MAKEWPARAM( GetDlgCtrlID(), CBN_SELENDOK ),
  2924. (LPARAM) m_hWnd
  2925. );
  2926. pWnd->SendMessage(
  2927. WM_COMMAND,
  2928. MAKEWPARAM( GetDlgCtrlID(), CBN_SELCHANGE ),
  2929. (LPARAM) m_hWnd
  2930. );
  2931. }
  2932. }
  2933. }
  2934. return lResult;
  2935. }
  2936. void CExtComboBoxBase::DeleteItem( LPDELETEITEMSTRUCT lpDIS ) 
  2937. {
  2938. ASSERT_VALID( this );
  2939. ASSERT( lpDIS->CtlType == ODT_COMBOBOX );
  2940. lpDIS;
  2941. }
  2942. int CExtComboBoxBase::CompareItem( LPCOMPAREITEMSTRUCT lpCIS )
  2943. {
  2944. ASSERT_VALID( this );
  2945. if( INT( lpCIS->itemID1 ) >= 0 
  2946. && INT( lpCIS->itemID2 ) >= 0
  2947. )
  2948. {
  2949. ASSERT( lpCIS->CtlType == ODT_COMBOBOX );
  2950. LPCTSTR lpszText1 = (LPCTSTR) lpCIS->itemData1;
  2951. ASSERT(lpszText1 != NULL);
  2952. LPCTSTR lpszText2 = (LPCTSTR) lpCIS->itemData2;
  2953. ASSERT(lpszText2 != NULL);
  2954. return lstrcmp( lpszText2, lpszText1 );
  2955. }
  2956. return 0;
  2957. }
  2958. CSize CExtComboBoxBase::OnPopupListBoxCalcItemExtraSizes(
  2959. LONG nItem
  2960. ) const
  2961. {
  2962. ASSERT_VALID( this );
  2963. nItem;
  2964. return CSize( 2, 0 );
  2965. }
  2966. CSize CExtComboBoxBase::OnPopupListBoxCalcItemCellExtraSizes() const
  2967. {
  2968. ASSERT_VALID( this );
  2969. return CSize( 4, 0 );
  2970. }
  2971. LONG CExtComboBoxBase::OnPopupListBoxQueryColumnWidth(
  2972. LONG nColNo
  2973. ) const
  2974. {
  2975. ASSERT_VALID( this );
  2976. LONG nColWidth = LbColumnWidthGet( nColNo );
  2977. if( nColWidth != 0L )
  2978. nColWidth = max( 25, nColWidth ); // minimum width
  2979. return nColWidth;
  2980. }
  2981. void CExtComboBoxBase::DrawItem( LPDRAWITEMSTRUCT lpDIS ) 
  2982. {
  2983. ASSERT_VALID( this );
  2984. ASSERT( lpDIS != NULL && lpDIS->hDC != NULL );
  2985. if( (GetStyle() & CBS_HASSTRINGS) == 0 
  2986. && (GetStyle() & LBS_HASSTRINGS) == 0 
  2987. )
  2988. return;
  2989. INT nCount = GetCount();
  2990. INT nItem = lpDIS->itemID;
  2991. if( nItem < 0 || nItem >= nCount )
  2992. return;
  2993. CDC dc;
  2994. dc.Attach( lpDIS->hDC );
  2995. if( lpDIS->itemAction & (ODA_DRAWENTIRE | ODA_SELECT) )
  2996. {
  2997. CRect rcErase( lpDIS->rcItem );
  2998. if( nItem == ( nCount - 1 ) )
  2999. {
  3000. CRect rcClient;
  3001. GetClientRect( &rcClient );
  3002. if( rcErase.bottom < rcClient.bottom )
  3003. rcErase.bottom = rcClient.bottom;
  3004. }
  3005. COLORREF clrBk = COLORREF(-1L);
  3006. if( ( lpDIS->itemState & ODS_COMBOBOXEDIT ) != 0 ) 
  3007. clrBk = GetBkColor();
  3008. if( clrBk == COLORREF(-1L) )
  3009. clrBk = PmBridge_GetPM()->GetColor( ( ! IsWindowEnabled() ) ? COLOR_3DFACE : COLOR_WINDOW, this );
  3010. dc.FillSolidRect( rcErase,  clrBk );
  3011. }
  3012. LB_ITEM * pLbItem = LbItemGet( nItem );
  3013. if( pLbItem != NULL )
  3014. {
  3015. OnPopupListBoxDrawItem( 
  3016. dc,
  3017. lpDIS->rcItem,
  3018. OnPopupListBoxCalcItemExtraSizes( nItem ),
  3019. lpDIS->itemState,
  3020. pLbItem 
  3021. );
  3022. }
  3023. else
  3024. {
  3025. CRect rcDrawItem( lpDIS->rcItem );
  3026. bool bSelected = ( lpDIS->itemState & ODS_SELECTED ) ? true : false;
  3027. if( bSelected )
  3028. dc.FillSolidRect( &rcDrawItem, PmBridge_GetPM()->GetColor( COLOR_HIGHLIGHT, this ) );
  3029. CString sText;
  3030. GetLBText( nItem, sText );
  3031. if( ! sText.IsEmpty() )
  3032. {
  3033. COLORREF clrTextOld = dc.SetTextColor( PmBridge_GetPM()->GetColor( bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT, this ) );
  3034. int nOldBkMode = dc.SetBkMode( TRANSPARENT );
  3035. CRect rcText( rcDrawItem );
  3036. rcText.DeflateRect( 2, 0 );
  3037. UINT nFormat = 
  3038. DT_SINGLELINE
  3039. | DT_LEFT
  3040. | DT_VCENTER
  3041. | DT_NOPREFIX
  3042. ;
  3043. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  3044. nFormat |= DT_EXPANDTABS;
  3045. HFONT hFont = OnQueryFont();
  3046. if( hFont == NULL )
  3047. hFont = (HFONT)PmBridge_GetPM()->m_FontNormal.GetSafeHandle();
  3048. ASSERT( hFont != NULL );
  3049. HFONT hOldFont = (HFONT)::SelectObject( dc.m_hDC, hFont );
  3050. dc.DrawText( sText, &rcText, nFormat );
  3051. ::SelectObject( dc.m_hDC, hOldFont );
  3052. dc.SetBkMode( nOldBkMode );
  3053. dc.SetTextColor( clrTextOld );
  3054. } // if( ! sText.IsEmpty() )
  3055. if( bSelected )
  3056. {
  3057. COLORREF clrTextOld = dc.SetTextColor( RGB(255,255,255) );
  3058. COLORREF clrBkOld = dc.SetBkColor( RGB(0,0,0) );
  3059. dc.DrawFocusRect( &rcDrawItem );
  3060. dc.SetBkColor( clrBkOld );
  3061. dc.SetTextColor( clrTextOld );
  3062. }
  3063. }
  3064. dc.Detach();
  3065. }
  3066. void CExtComboBoxBase::MeasureItem( LPMEASUREITEMSTRUCT lpMIS ) 
  3067. {
  3068. ASSERT_VALID( this );
  3069. ASSERT( lpMIS != NULL );
  3070. if( (GetStyle() & CBS_HASSTRINGS) == 0 
  3071. && (GetStyle() & LBS_HASSTRINGS) == 0 
  3072. )
  3073. return;
  3074. lpMIS->itemWidth = lpMIS->itemHeight = 16;
  3075. INT nItem = lpMIS->itemID;
  3076. if( nItem < 0 || nItem >= GetCount() )
  3077. return;
  3078. OnPopupListBoxMeasureItem( lpMIS );
  3079. }
  3080. void CExtComboBoxBase::OnPopupListBoxDrawItem( 
  3081. CDC & dc,
  3082. const RECT & rcItem,
  3083. const CSize & szExtra,
  3084. UINT nState,
  3085. const CExtComboBoxBase::LB_ITEM * pLbItem
  3086. )
  3087. {
  3088. ASSERT_VALID( this );
  3089. ASSERT( dc.GetSafeHdc() != NULL );
  3090. if( (GetStyle() & CBS_HASSTRINGS) == 0 
  3091. && (GetStyle() & LBS_HASSTRINGS) == 0 
  3092. )
  3093. return;
  3094. bool bEnabled = true;
  3095. if( ( ! GetDroppedState() )
  3096. && ( ! IsWindowEnabled() )
  3097. )
  3098. bEnabled = false;
  3099. else if( pLbItem != NULL )
  3100. bEnabled = pLbItem->IsEnabled();
  3101. CRect rcDrawItem( rcItem );
  3102. bool bSelected = ( nState & ODS_SELECTED ) ? true : false;
  3103. if( bSelected && bEnabled )
  3104. dc.FillSolidRect( &rcDrawItem, PmBridge_GetPM()->GetColor( COLOR_HIGHLIGHT, this ) );
  3105. INT nOldBkMode = dc.SetBkMode( TRANSPARENT );
  3106. CRect rcText( rcDrawItem );
  3107. rcText.DeflateRect( szExtra );
  3108. // draw item cells
  3109. if( pLbItem != NULL )
  3110. {
  3111. INT nCount = pLbItem->LbItemCellGetCount();
  3112. for( INT nCellItem = 0; nCellItem < nCount; nCellItem++ )
  3113. {
  3114. LB_ITEM::CELL * pItemCell = pLbItem->LbItemCellGet( nCellItem );
  3115. ASSERT( pItemCell != NULL );
  3116. LONG nColWidth = OnPopupListBoxQueryColumnWidth( nCellItem );
  3117. if( nColWidth > 0L )
  3118. {
  3119. COLORREF clrBk = COLORREF(-1L);
  3120. if( ( nState & ODS_COMBOBOXEDIT ) != 0 ) 
  3121. clrBk = GetBkColor();
  3122. if( clrBk == COLORREF(-1L) )
  3123. clrBk = pItemCell->m_clrBack;
  3124. if( clrBk != COLORREF(-1L)
  3125. && ( (!bSelected) || (!bEnabled) )
  3126. )
  3127. {
  3128. dc.FillSolidRect(
  3129. &rcText,
  3130. clrBk
  3131. );
  3132. }
  3133. CString sText = pItemCell->m_sItemText;
  3134. if( !sText.IsEmpty() )
  3135. {
  3136. COLORREF clrText = COLORREF(-1L);
  3137. if( !bSelected )
  3138. clrText = pItemCell->m_clrText;
  3139. if( clrText == COLORREF(-1L) )
  3140. clrText = GetTextColor();
  3141. if( clrText == COLORREF(-1L) )
  3142. clrText = 
  3143. PmBridge_GetPM()->GetColor( 
  3144. ( bSelected && bEnabled )
  3145. ? COLOR_HIGHLIGHTTEXT 
  3146. : bEnabled
  3147. ? COLOR_BTNTEXT 
  3148. : COLOR_GRAYTEXT, 
  3149. this
  3150. );
  3151. COLORREF clrTextOld = dc.SetTextColor( clrText );
  3152. UINT nFormat = 
  3153. DT_SINGLELINE
  3154. | DT_LEFT
  3155. | DT_VCENTER
  3156. | DT_NOPREFIX
  3157. ;
  3158. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  3159. nFormat |= DT_EXPANDTABS;
  3160. CRect rcItemText( rcText );
  3161. if( nColWidth > 0L 
  3162. && nCellItem < nCount - 1
  3163. )
  3164. rcItemText.right = rcItemText.left + nColWidth;
  3165. HFONT hFont = OnQueryFont();
  3166. if( hFont == NULL )
  3167. hFont = (HFONT)PmBridge_GetPM()->m_FontNormal.GetSafeHandle();
  3168. ASSERT( hFont != NULL );
  3169. HFONT hOldFont = (HFONT)::SelectObject( dc.m_hDC, hFont );
  3170. dc.DrawText(
  3171. sText,
  3172. &rcItemText,
  3173. (nFormat|DT_END_ELLIPSIS)
  3174. );
  3175. ::SelectObject( dc.m_hDC, hOldFont );
  3176. dc.SetTextColor( clrTextOld );
  3177. } // if( ! sText.IsEmpty() )
  3178. if( nColWidth > 0 )
  3179. rcText.left += nColWidth;
  3180. }
  3181. } // for( ...
  3182. } // if( pLbItem != NULL )
  3183. dc.SetBkMode( nOldBkMode );
  3184. if( bSelected && bEnabled )
  3185. {
  3186. COLORREF clrTextOld = 
  3187. dc.SetTextColor( RGB(255,255,255) );
  3188. COLORREF clrBkOld = dc.SetBkColor( RGB(0,0,0) );
  3189. ::DrawFocusRect( dc, &rcDrawItem );
  3190. dc.SetBkColor( clrBkOld );
  3191. dc.SetTextColor( clrTextOld );
  3192. }
  3193. }
  3194. void CExtComboBoxBase::OnPopupListBoxMeasureItem( LPMEASUREITEMSTRUCT lpMIS )
  3195. {
  3196. ASSERT_VALID( this );
  3197. ASSERT( lpMIS != NULL );
  3198. if( (GetStyle() & CBS_HASSTRINGS) == 0 
  3199. && (GetStyle() & LBS_HASSTRINGS) == 0 
  3200. )
  3201. return;
  3202. lpMIS->itemWidth = lpMIS->itemHeight = 16;
  3203. INT nItem = lpMIS->itemID;
  3204. if( nItem < 0 || nItem >= GetCount() )
  3205. return;
  3206. HFONT hFont = OnQueryFont();
  3207. if( hFont == NULL )
  3208. hFont = (HFONT)PmBridge_GetPM()->m_FontNormal.GetSafeHandle();
  3209. ASSERT( hFont != NULL );
  3210. INT nHeight = 0;
  3211. INT nWidth = 0;
  3212. LB_ITEM * pLbItem = LbItemGet( nItem );
  3213. if( pLbItem != NULL )
  3214. {
  3215. INT nCount = pLbItem->LbItemCellGetCount();
  3216. for( INT nCellItem = 0; nCellItem < nCount; nCellItem++ )
  3217. {
  3218. LB_ITEM::CELL * pItemCell = pLbItem->LbItemCellGet( nCellItem );
  3219. if( pItemCell != NULL )
  3220. {
  3221. CExtSafeString sText = pItemCell->m_sItemText;
  3222. if( !sText.IsEmpty() )
  3223. {
  3224. UINT nFormat = 
  3225. DT_SINGLELINE
  3226. | DT_LEFT
  3227. | DT_VCENTER
  3228. | DT_NOPREFIX
  3229. ;
  3230. if( sText.Find( _T('t') ) != -1 ) // do tabs expanding
  3231. nFormat |= DT_EXPANDTABS;
  3232. CWindowDC dc( NULL );
  3233. CRect rcMeasure =
  3234. CExtPaintManager::stat_CalcTextDimension( 
  3235. dc, 
  3236. *CFont::FromHandle( hFont ), 
  3237. sText,
  3238. nFormat
  3239. );
  3240. nHeight = max( nHeight, rcMeasure.Height() );
  3241. nWidth += rcMeasure.Width();
  3242. CSize szExtra = 
  3243. OnPopupListBoxCalcItemCellExtraSizes();
  3244. nWidth += szExtra.cx;
  3245. }
  3246. } // if( pItemCell != NULL )
  3247. }
  3248. }
  3249. else
  3250. {
  3251. CExtSafeString sMeasure;
  3252. GetLBText( nItem, sMeasure );
  3253. if( sMeasure.IsEmpty() )
  3254. return;
  3255. CWindowDC dc( NULL );
  3256. CRect rcMeasure =
  3257. CExtPaintManager::stat_CalcTextDimension( 
  3258. dc, 
  3259. *CFont::FromHandle( hFont ), 
  3260. sMeasure,
  3261. DT_SINGLELINE | DT_LEFT | DT_NOPREFIX
  3262. );
  3263. nWidth = rcMeasure.Width();
  3264. nHeight = rcMeasure.Height();
  3265. }
  3266. lpMIS->itemWidth = nWidth;
  3267. lpMIS->itemHeight = max( nHeight, (INT)lpMIS->itemHeight );
  3268. CSize szExtra = 
  3269. OnPopupListBoxCalcItemExtraSizes( nItem );
  3270. lpMIS->itemWidth += szExtra.cx * 2;
  3271. lpMIS->itemHeight += szExtra.cy * 2;
  3272. }
  3273. HFONT CExtComboBoxBase::OnQueryFont() const
  3274. {
  3275. ASSERT_VALID( this );
  3276. HFONT hFont = NULL;
  3277. if( GetSafeHwnd() != NULL )
  3278. hFont = (HFONT) ::SendMessage( m_hWnd, WM_GETFONT, 0L, 0L );
  3279. if( hFont == NULL )
  3280. {
  3281. HWND hWndParent = ::GetParent( m_hWnd );
  3282. if( hWndParent != NULL )
  3283. hFont = (HFONT)
  3284. ::SendMessage( hWndParent, WM_GETFONT, 0L, 0L );
  3285. } // if( hFont == NULL )
  3286. if( hFont == NULL )
  3287. {
  3288. hFont = (HFONT)::GetStockObject( DEFAULT_GUI_FONT );
  3289. if( hFont == NULL )
  3290. hFont = (HFONT)::GetStockObject( SYSTEM_FONT );
  3291. } // if( hFont == NULL )
  3292. return hFont;
  3293. }
  3294. INT CExtComboBoxBase::LbItemSet(
  3295. INT nIndex,
  3296. __EXT_MFC_SAFE_LPCTSTR lpszItem
  3297. )
  3298. {
  3299. INT nCount = INT( m_arrLBItems.GetSize() );
  3300. if( nIndex < 0 || nIndex > nCount )
  3301. return CB_ERR;
  3302. LB_ITEM * pLbItem = new LB_ITEM();
  3303. ASSERT( pLbItem != NULL );
  3304. m_arrLBItems.SetAtGrow( nIndex, pLbItem );
  3305. INT nItem = pLbItem->LbItemCellInsert( lpszItem );
  3306. LB_ITEM::CELL * pItemCell = 
  3307. pLbItem->LbItemCellGet( nItem );
  3308. ASSERT( pItemCell != NULL );
  3309. return nIndex;
  3310. }
  3311. INT CExtComboBoxBase::LbItemInsert(
  3312. __EXT_MFC_SAFE_LPCTSTR lpszItem,
  3313. INT nIndex // = -1
  3314. )
  3315. {
  3316. INT nCount = INT( m_arrLBItems.GetSize() );
  3317. if( nIndex < 0 || nIndex > nCount )
  3318. nIndex = nCount; // append
  3319. LB_ITEM * pLbItem = new LB_ITEM();
  3320. ASSERT( pLbItem != NULL );
  3321. m_arrLBItems.InsertAt( nIndex, pLbItem );
  3322. INT nItem = pLbItem->LbItemCellInsert( lpszItem );
  3323. LB_ITEM::CELL * pItemCell = 
  3324. pLbItem->LbItemCellGet( nItem );
  3325. ASSERT( pItemCell != NULL );
  3326. return nIndex;
  3327. }
  3328. bool CExtComboBoxBase::LbItemRemove(
  3329. LONG nIndex
  3330. )
  3331. {
  3332. INT nCount = INT( m_arrLBItems.GetSize() );
  3333. if( nIndex < 0 || nIndex >= nCount )
  3334. return false;
  3335. LB_ITEM * pLbItem = m_arrLBItems.GetAt( nIndex );
  3336. ASSERT( pLbItem != NULL );
  3337. if( pLbItem != NULL )
  3338. {
  3339. delete pLbItem;
  3340. pLbItem = NULL;
  3341. }
  3342. m_arrLBItems.RemoveAt( nIndex );
  3343. return true;
  3344. }
  3345. void CExtComboBoxBase::LbItemRemoveAll()
  3346. {
  3347. while( m_arrLBItems.GetSize() > 0 )
  3348. {
  3349. LB_ITEM * pLbItem = m_arrLBItems[0];
  3350. if( pLbItem != NULL ) 
  3351. {
  3352. delete pLbItem;
  3353. pLbItem = NULL;
  3354. }
  3355. m_arrLBItems.RemoveAt(0);
  3356. }
  3357. }
  3358. CExtComboBoxBase::LB_ITEM * CExtComboBoxBase::LbItemGet( 
  3359. LONG nItem
  3360. ) const
  3361. {
  3362. ASSERT_VALID( this );
  3363. INT nCount = INT( m_arrLBItems.GetSize() );
  3364. if( nItem < 0 || nItem >= nCount )
  3365. return NULL;
  3366. LB_ITEM * pLbItem = m_arrLBItems.GetAt( nItem );
  3367. ASSERT( pLbItem != NULL );
  3368. return pLbItem;
  3369. }
  3370. LONG CExtComboBoxBase::LbColumnWidthGet( 
  3371. LONG nColNo
  3372. ) const
  3373. {
  3374. ASSERT_VALID( this );
  3375. LONG nWidth = -1L;
  3376. if( ! m_mapColumnsWidth.Lookup( nColNo, nWidth ) )
  3377. return -1L;
  3378. return nWidth;
  3379. }
  3380. void CExtComboBoxBase::LbColumnWidthSet( 
  3381. LONG nColNo,
  3382. LONG nWidth
  3383. )
  3384. {
  3385. ASSERT_VALID( this );
  3386. m_mapColumnsWidth.SetAt( nColNo, nWidth );
  3387. }
  3388. bool CExtComboBoxBase::LbItemIsEnabled(
  3389. LONG nItem
  3390. ) const
  3391. {
  3392. ASSERT_VALID( this );
  3393. if( nItem < 0L 
  3394. || nItem >= GetCount() 
  3395. )
  3396. return false;
  3397. bool bEnabled = true;
  3398. LB_ITEM * pLbItem = LbItemGet( nItem );
  3399. if( pLbItem != NULL )
  3400. bEnabled = pLbItem->IsEnabled();
  3401. return bEnabled;
  3402. }
  3403. void CExtComboBoxBase::LbItemEnable(
  3404. LONG nItem,
  3405. bool bEnable // = true
  3406. )
  3407. {
  3408. ASSERT_VALID( this );
  3409. if( nItem < 0L 
  3410. || nItem >= GetCount() 
  3411. )
  3412. return;
  3413. LB_ITEM * pLbItem = LbItemGet( nItem );
  3414. if( pLbItem != NULL )
  3415. pLbItem->Enable( bEnable );
  3416. }
  3417. #define UPDATE_TIMER 1
  3418. #define UPDATE_TIMER_PERIOD 100
  3419. /////////////////////////////////////////////////////////////////////////////
  3420. // CExtComboBox
  3421. IMPLEMENT_DYNCREATE( CExtComboBox, CExtComboBoxBase );
  3422. CExtComboBox::CExtComboBox()
  3423. : CExtComboBoxBase()
  3424. , m_bLButtonDown( false )
  3425. , m_bPainted( false )
  3426. , m_dwLastStateCode( 0 )
  3427. {
  3428. }
  3429. CExtComboBox::~CExtComboBox()
  3430. {
  3431. CExtAnimationSite * pAcAS = AnimationClient_SiteGet();
  3432. if( pAcAS != NULL )
  3433. pAcAS->AnimationSite_ClientRemove( this );
  3434. }
  3435. BEGIN_MESSAGE_MAP(CExtComboBox, CExtComboBoxBase)
  3436. //{{AFX_MSG_MAP(CExtComboBox)
  3437. ON_WM_LBUTTONDOWN()
  3438. ON_WM_LBUTTONUP()
  3439. ON_WM_TIMER()
  3440. ON_WM_PAINT()
  3441. ON_WM_SETCURSOR()
  3442. ON_WM_ERASEBKGND()
  3443. ON_WM_SETFOCUS()
  3444. ON_WM_KILLFOCUS()
  3445. //}}AFX_MSG_MAP
  3446. END_MESSAGE_MAP()
  3447. /////////////////////////////////////////////////////////////////////////////
  3448. // CExtComboBox message handlers
  3449. BOOL CExtComboBox::OnSetCursor( CWnd * pWnd, UINT nHitTest, UINT message )
  3450. {
  3451. if( message == WM_MOUSEMOVE )
  3452. {
  3453. CRect rcWnd;
  3454. GetWindowRect( &rcWnd );
  3455. if( rcWnd.PtInRect( GetCurrentMessage()->pt ) )
  3456. {
  3457. SetTimer( UPDATE_TIMER, UPDATE_TIMER_PERIOD, NULL );
  3458. OnTimer( UPDATE_TIMER );
  3459. }
  3460. }
  3461. return CExtComboBoxBase::OnSetCursor(pWnd, nHitTest, message);
  3462. }
  3463. void CExtComboBox::OnLButtonDown(UINT nFlags, CPoint point)
  3464. {
  3465. m_bLButtonDown = true;
  3466. CExtComboBoxBase::OnLButtonDown(nFlags, point);
  3467. }
  3468. void CExtComboBox::OnLButtonUp(UINT nFlags, CPoint point)
  3469. {
  3470. m_bLButtonDown = false;
  3471. Invalidate();
  3472. CExtComboBoxBase::OnLButtonUp(nFlags, point);
  3473. }
  3474. bool CExtComboBox::IsFocused() const
  3475. {
  3476. bool bFocused = false;
  3477. HWND hWndFocus = ::GetFocus();
  3478. if( hWndFocus == GetSafeHwnd()
  3479. || ::IsChild( GetSafeHwnd(), hWndFocus )
  3480. )
  3481. bFocused = true;
  3482. return bFocused;
  3483. }
  3484. bool CExtComboBox::IsHovered() const
  3485. {
  3486. CPoint ptCursorPos( 0, 0 );
  3487. ::GetCursorPos( &ptCursorPos );
  3488. CRect rcItem;
  3489. GetWindowRect( &rcItem );
  3490. bool bHovered = false;
  3491. if( rcItem.PtInRect(ptCursorPos) )
  3492. bHovered = true;
  3493. return bHovered;
  3494. }
  3495. void CExtComboBox::OnSetFocus( CWnd * pOldWnd ) 
  3496. {
  3497. HWND hWndOwn = m_hWnd;
  3498. CExtComboBoxBase::OnSetFocus( pOldWnd );
  3499. if( ! ::IsWindow( hWndOwn ) )
  3500. return;
  3501. Invalidate();     
  3502. }
  3503. void CExtComboBox::OnKillFocus( CWnd * pNewWnd ) 
  3504. {
  3505. HWND hWndOwn = m_hWnd;
  3506. CExtComboBoxBase::OnKillFocus( pNewWnd );
  3507. if( ! ::IsWindow( hWndOwn ) )
  3508. return;
  3509. Invalidate();     
  3510. }
  3511. void CExtComboBox::OnTimer( __EXT_MFC_UINT_PTR nIDEvent )
  3512. {
  3513. if( UPDATE_TIMER == nIDEvent )
  3514. {
  3515. CClientDC dc( this );
  3516. if( m_bLButtonDown )
  3517. {
  3518. KillTimer( UPDATE_TIMER );
  3519. if( m_bPainted )
  3520. {
  3521. _OnDrawComboImpl( 
  3522. GetDroppedState() ? true : false, 
  3523. IsHovered(), 
  3524. &dc 
  3525. );
  3526. m_bPainted = false;
  3527. }
  3528. }
  3529. else if( !IsHovered() && !IsFocused() )
  3530. {
  3531. KillTimer( UPDATE_TIMER );
  3532. if( m_bPainted == TRUE )
  3533. {
  3534. _OnDrawComboImpl( 
  3535. false, 
  3536. false, 
  3537. &dc 
  3538. );
  3539. m_bPainted = false;
  3540. }
  3541. }
  3542. else
  3543. {
  3544. if( !m_bPainted )
  3545. {
  3546. m_bPainted = true;
  3547. _OnDrawComboImpl( 
  3548. GetDroppedState() ? true : false, 
  3549. true, 
  3550. &dc 
  3551. );
  3552. }
  3553. else
  3554. return;
  3555. }
  3556. return;
  3557. }
  3558. if( AnimationSite_OnHookTimer( UINT(nIDEvent) ) )
  3559. return;
  3560. CExtComboBoxBase::OnTimer( nIDEvent );
  3561. }
  3562. BOOL CExtComboBox::OnEraseBkgnd(CDC* pDC)
  3563. {
  3564. pDC;
  3565. return TRUE;
  3566. }
  3567. void CExtComboBox::OnPaint()
  3568. {
  3569. if( ( GetExStyle() & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE|WS_EX_STATICEDGE) ) != 0 )
  3570. ModifyStyleEx( WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE|WS_EX_STATICEDGE, 0, SWP_FRAMECHANGED );
  3571. COLORREF clrFillClientArea = COLORREF(-1L);
  3572. DWORD dwStyle = GetStyle();
  3573. CPaintDC dcPaint( this );
  3574. CExtPaintManager::stat_ExcludeChildAreas( dcPaint.GetSafeHdc(), GetSafeHwnd() );
  3575. CRect rcClient;
  3576. GetClientRect( &rcClient );
  3577. CExtMemoryDC dc( &dcPaint, &rcClient );
  3578. CRgn _rgn;
  3579. if( ( dwStyle & ( CBS_OWNERDRAWFIXED|CBS_OWNERDRAWVARIABLE ) ) != 0 )
  3580. {
  3581. CRect rcRgn = rcClient;
  3582. rcRgn.right -= ::GetSystemMetrics( SM_CXVSCROLL );
  3583. if( _rgn.CreateRectRgnIndirect( &rcRgn ) )
  3584. dc.SelectClipRgn( &_rgn );
  3585. }
  3586. DefWindowProc( WM_PAINT, (WPARAM)dc.GetSafeHdc(), (LPARAM)0 );
  3587. if( _rgn.GetSafeHandle() != NULL )
  3588. dc.SelectClipRgn( NULL );
  3589. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  3590. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  3591. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST
  3592. )
  3593. {
  3594. if( (! PmBridge_GetPM()->GetCb2DbTransparentMode(this) )
  3595. || (! PmBridge_GetPM()->PaintDockerBkgnd( true, dc, this ) )
  3596. )
  3597. clrFillClientArea = PmBridge_GetPM()->GetColor( CExtPaintManager::CLR_3DFACE_OUT, this );
  3598. }
  3599. if( clrFillClientArea != COLORREF(-1L) )
  3600. dc.FillSolidRect( &rcClient, clrFillClientArea );
  3601. _OnDrawComboImpl( GetDroppedState() ? true : false, IsHovered(), &dc );
  3602. }
  3603. void CExtComboBox::_OnDrawComboImpl(
  3604. bool bPressed,
  3605. bool bHover,
  3606. CDC * pDC // = NULL
  3607. )
  3608. {
  3609. if( pDC != NULL )
  3610. {
  3611. if( AnimationClient_StatePaint( *pDC ) )
  3612. return;
  3613. }
  3614. bool bCallReleaseDC = false;
  3615. if( pDC == NULL )
  3616. {
  3617. pDC = GetDC();
  3618. ASSERT( pDC != NULL );
  3619. bCallReleaseDC = true;
  3620. }
  3621. CRect rcClient;
  3622. GetClientRect( &rcClient );
  3623. bool bEnabled = IsWindowEnabled() ? true : false;
  3624. bool bPushed = ( bPressed || GetDroppedState() ) ? true : false;
  3625. if( ! bEnabled )
  3626. {
  3627. bPushed = false;
  3628. bHover = false;
  3629. }
  3630. if( CExtPopupMenuWnd::IsMenuTracking() )
  3631. bHover = false;
  3632. else if( (!IsHovered()) && IsFocused() )
  3633. bHover = true;
  3634. DWORD dwStyle = GetStyle();
  3635. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  3636. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  3637. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST
  3638. )
  3639. {
  3640. HWND hWndFocus = ::GetFocus();
  3641. CEdit * pEdit = GetInnerEditCtrl();
  3642. CExtComboBoxPopupListBox * pLB = OnComboBoxPopupListBoxQuery();
  3643. HWND hWndEdit = pEdit->GetSafeHwnd();
  3644. ASSERT( hWndEdit != NULL );
  3645. HWND hWndLB = pLB->GetSafeHwnd();
  3646. ASSERT( hWndLB != NULL );
  3647. bool bFocus = false;
  3648. if( hWndFocus != NULL
  3649. && ( hWndFocus == hWndEdit
  3650. || hWndFocus == hWndLB
  3651. )
  3652. )
  3653. bFocus = true;
  3654. bool bReadOnly = ( ( pEdit->GetStyle() & ES_READONLY ) != 0 ) ? true : false;
  3655. bool bMouseOver = false;
  3656. CRect _rcClient;
  3657. pLB->GetWindowRect( &_rcClient );
  3658. ScreenToClient( &_rcClient );
  3659. _rcClient.InflateRect( 3, 3, 3, 2 );
  3660. pDC->FillSolidRect( &_rcClient, PmBridge_GetPM()->GetColor( COLOR_WINDOW ) );
  3661. pEdit->GetClientRect( &_rcClient );
  3662. pEdit->ClientToScreen( &_rcClient );
  3663. ScreenToClient( &_rcClient );
  3664. _rcClient.InflateRect( 3, 3 );
  3665. CExtPaintManager::PAINTCONTROLFRAMEDATA _pcfdEdit(
  3666. pEdit,
  3667. _rcClient,
  3668. true,
  3669. bMouseOver,
  3670. bEnabled,
  3671. bFocus,
  3672. bReadOnly
  3673. );
  3674. PmBridge_GetPM()->PaintControlFrame( *pDC, _pcfdEdit );
  3675. }
  3676. else
  3677. {
  3678. bool bRightText = false;
  3679. if( (GetExStyle()&WS_EX_RIGHT) != 0 )
  3680. bRightText = true;
  3681. // erase are of the button that contains the drop-down arrow
  3682. CRect rcDDButton( rcClient );
  3683. if( bRightText )
  3684. {
  3685. rcDDButton.right = rcDDButton.left + ::GetSystemMetrics( SM_CXHTHUMB );
  3686. rcDDButton.right += 2;
  3687. }
  3688. else
  3689. {
  3690. rcDDButton.left = rcDDButton.right - ::GetSystemMetrics( SM_CXHTHUMB );
  3691. rcDDButton.left -= 2;
  3692. if( rcDDButton.left > rcDDButton.right )
  3693. rcDDButton.left = rcDDButton.right;
  3694. }
  3695. COLORREF clrBk = GetBkColor();
  3696. if( clrBk == COLORREF(-1L) )
  3697. clrBk = PmBridge_GetPM()->GetColor( ( ! bEnabled ) ? COLOR_3DFACE : COLOR_WINDOW, this );
  3698. pDC->FillSolidRect( &rcDDButton, clrBk );
  3699. // fix for disabled edit border inside combo box
  3700. if( (!bEnabled)
  3701. && (dwStyle&CBS_DROPDOWN) == CBS_DROPDOWN 
  3702. )
  3703. {
  3704. CWnd * pWndChild = GetWindow( GW_CHILD );
  3705. if( pWndChild != NULL )
  3706. {
  3707. ASSERT_VALID( pWndChild );
  3708. static const TCHAR szEdit[] = _T("edit");
  3709. TCHAR szCompare[ sizeof(szEdit)/sizeof(szEdit[0]) + 1 ] = _T("");
  3710. ::GetClassName( pWndChild->GetSafeHwnd(), szCompare, sizeof(szCompare)/sizeof(szCompare[0]) );
  3711. if( ! lstrcmpi( szCompare, szEdit ) )
  3712. {
  3713. CRect rcChild;
  3714. pWndChild->GetWindowRect( &rcChild );
  3715. ScreenToClient( rcChild );
  3716. rcChild.InflateRect( 1, 1 );
  3717. pDC->Draw3dRect( &rcChild, clrBk, clrBk );
  3718. }
  3719. }
  3720. }
  3721. CExtPaintManager::PAINTCOMBOFRAMEDATA _pcfd( this, rcClient, bHover, bPushed, bEnabled, bRightText );
  3722. PmBridge_GetPM()->PaintComboFrame( *pDC, _pcfd );
  3723. DWORD dwLastStateCode = 0;
  3724. if( m_bLButtonDown )
  3725. dwLastStateCode |= 0x01;
  3726. if( IsHovered() )
  3727. dwLastStateCode |= 0x02;
  3728. if( IsFocused() )
  3729. dwLastStateCode |= 0x04;
  3730. if( bPressed )
  3731. dwLastStateCode |= 0x08;
  3732. if( m_dwLastStateCode != dwLastStateCode )
  3733. {
  3734. if( AnimationClient_StateGet( true ).FromSurface( pDC->m_hDC, rcClient ) )
  3735. {
  3736. if( AnimationClient_StateGet( false ).IsEmpty() )
  3737. AnimationClient_StateGet( false ) = AnimationClient_StateGet( true );
  3738. else
  3739. AnimationSite_OnClientStateChanged( this, 0 );
  3740. }
  3741. m_dwLastStateCode = dwLastStateCode;
  3742. }
  3743. }
  3744. if( bCallReleaseDC )
  3745. ReleaseDC( pDC );
  3746. }
  3747. BOOL CExtComboBox::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) 
  3748. {
  3749. ASSERT_VALID( this );
  3750. if( message == WM_COMMAND )
  3751. {
  3752. INT nCode = HIWORD(wParam);
  3753. switch( nCode )
  3754. {
  3755. case CBN_CLOSEUP:
  3756. Invalidate();
  3757. break;
  3758. }
  3759. }
  3760. return CExtComboBoxBase::OnChildNotify(message, wParam, lParam, pLResult);
  3761. }
  3762. LRESULT CExtComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
  3763. {
  3764. if( message == WM_PRINT || message == WM_PRINTCLIENT )
  3765. {
  3766. CExtComboBoxBase::WindowProc( message, wParam, lParam );
  3767. CDC * pDC = CDC::FromHandle( (HDC)wParam );
  3768. CRect rcClient;
  3769. GetClientRect( &rcClient );
  3770. CExtMemoryDC dc( pDC, &rcClient, CExtMemoryDC::MDCOPT_TO_MEMORY|CExtMemoryDC::MDCOPT_FILL_BITS|CExtMemoryDC::MDCOPT_RTL_COMPATIBILITY );
  3771. DWORD dwStyle = GetStyle();
  3772. if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  3773. && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  3774. && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST
  3775. )
  3776. {
  3777. if( (! PmBridge_GetPM()->GetCb2DbTransparentMode(this) )
  3778. || (! PmBridge_GetPM()->PaintDockerBkgnd( true, dc, this ) )
  3779. )
  3780. dc.FillSolidRect( &rcClient, PmBridge_GetPM()->GetColor( CExtPaintManager::CLR_3DFACE_OUT, this ) );
  3781. }
  3782. _OnDrawComboImpl( GetDroppedState() ? true : false, IsHovered(), &dc );
  3783. if( (lParam&PRF_CHILDREN) != 0 )
  3784. CExtPaintManager::stat_PrintChildren( m_hWnd, message, dc.GetSafeHdc(), lParam, false );
  3785. return (!0);
  3786. }
  3787. return CExtComboBoxBase::WindowProc( message, wParam, lParam );
  3788. }
  3789. void CExtComboBox::AnimationSite_OnProgressShutdownTimer( UINT nTimerID )
  3790. {
  3791. ASSERT_VALID( this );
  3792. CExtComboBoxBase::AnimationSite_OnProgressShutdownTimer( nTimerID );
  3793. }
  3794. const CExtAnimationParameters *
  3795. CExtComboBox::AnimationClient_OnQueryAnimationParameters(
  3796. INT eAPT // __EAPT_*** animation type
  3797. ) const
  3798. {
  3799. ASSERT_VALID( this );
  3800. eAPT;
  3801. return (&PmBridge_GetPM()->g_DefAnimationParametersEmpty);
  3802. // const CExtAnimationParameters * pAnimationParameters =
  3803. //  PmBridge_GetPM()->Animation_GetParameters(
  3804. //  eAPT,
  3805. //  (CObject*)this,
  3806. //  this
  3807. //  );
  3808. //  return pAnimationParameters;
  3809. }
  3810. //bool CExtComboBox::AnimationClient_CacheNextState(
  3811. // CDC & dc,
  3812. // const RECT & rcAcAnimationTarget,
  3813. // bool bAnimate,
  3814. // INT eAPT // __EAPT_*** animation type
  3815. // )
  3816. //{
  3817. // ASSERT_VALID( this );
  3818. // ASSERT_VALID( (&dc) );
  3819. // ASSERT( dc.GetSafeHdc() != NULL );
  3820. // ASSERT( AnimationClient_CacheGeneratorIsLocked() );
  3821. //
  3822. //DWORD dwWndStyle = GetStyle();
  3823. // if( (dwWndStyle&(CBS_OWNERDRAWFIXED|CBS_OWNERDRAWVARIABLE)) != 0 
  3824. // && (dwWndStyle & 0x0003L) == CBS_DROPDOWNLIST
  3825. // )
  3826. // {
  3827. // DefWindowProc( WM_PAINT, (WPARAM)dc.GetSafeHdc(), (LPARAM)0 );
  3828. // _OnDrawComboImpl( 
  3829. // GetDroppedState() ? true : false, 
  3830. // IsHovered(), 
  3831. // &dc 
  3832. // );
  3833. // return
  3834. // CExtComboBoxBase::AnimationClient_CacheNextState(
  3835. // dc,
  3836. // rcAcAnimationTarget,
  3837. // bAnimate,
  3838. // eAPT
  3839. // );
  3840. // }
  3841. //
  3842. // CExtPaintManager::stat_ExcludeChildAreas(
  3843. // dc.GetSafeHdc(),
  3844. // GetSafeHwnd()
  3845. // );
  3846. //CRect rcClient;
  3847. // GetClientRect( &rcClient );
  3848. // DefWindowProc( WM_PAINT, (WPARAM)dc.GetSafeHdc(), (LPARAM)0 );
  3849. //
  3850. //DWORD dwStyle = GetStyle();
  3851. // if( (dwStyle&CBS_SIMPLE) == CBS_SIMPLE 
  3852. // && (dwStyle&CBS_DROPDOWN) != CBS_DROPDOWN
  3853. // && (dwStyle&CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST
  3854. // )
  3855. // {
  3856. // if( (! PmBridge_GetPM()->GetCb2DbTransparentMode(this) )
  3857. // || (! PmBridge_GetPM()->PaintDockerBkgnd( true, dc, this ) )
  3858. // )
  3859. // dc.FillSolidRect(
  3860. // &rcClient,
  3861. // PmBridge_GetPM()->GetColor(
  3862. // CExtPaintManager::CLR_3DFACE_OUT, this
  3863. // )
  3864. // );
  3865. // }
  3866. //
  3867. // _OnDrawComboImpl( 
  3868. // GetDroppedState() ? true : false, 
  3869. // IsHovered(), 
  3870. // &dc 
  3871. // );
  3872. //
  3873. // return
  3874. // CExtComboBoxBase::AnimationClient_CacheNextState(
  3875. // dc,
  3876. // rcAcAnimationTarget,
  3877. // bAnimate,
  3878. // eAPT
  3879. // );
  3880. //}
  3881. /////////////////////////////////////////////////////////////////////////////
  3882. // CExtCheckComboBox window
  3883. IMPLEMENT_DYNCREATE( CExtCheckComboBox, CExtComboBox );
  3884. CExtCheckComboBox::CExtCheckComboBox()
  3885. : m_bHaveText( false )
  3886. , m_bHaveItemHeight( false )
  3887. {
  3888. }
  3889. CExtCheckComboBox::~CExtCheckComboBox()
  3890. {
  3891. }
  3892. BEGIN_MESSAGE_MAP( CExtCheckComboBox, CExtComboBox )
  3893. //{{AFX_MSG_MAP(CExtCheckComboBox)
  3894. ON_MESSAGE( WM_GETTEXT, OnGetText )
  3895. ON_MESSAGE( WM_GETTEXTLENGTH, OnGetTextLength )
  3896. //}}AFX_MSG_MAP
  3897. END_MESSAGE_MAP()
  3898. BOOL CExtCheckComboBox::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
  3899. {
  3900. dwStyle &= ~0xF;
  3901. dwStyle |= CBS_DROPDOWNLIST|CBS_OWNERDRAWVARIABLE|CBS_HASSTRINGS;
  3902. return CExtComboBox::Create( dwStyle, rect, pParentWnd, nID );
  3903. }
  3904. LRESULT CExtCheckComboBox::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
  3905. {
  3906. if( message == CB_RESETCONTENT )
  3907. m_bHaveItemHeight = m_bHaveText = false;
  3908. else
  3909. if( WM_KEYFIRST <= message && message <= WM_KEYLAST
  3910. && ( wParam == VK_UP || wParam == VK_DOWN || wParam == VK_LEFT || wParam == VK_RIGHT || wParam == VK_PRIOR || wParam == VK_NEXT || wParam == VK_HOME || wParam == VK_END )
  3911. )
  3912. {
  3913. if( ! GetDroppedState() )
  3914. {
  3915. ShowDropDown();
  3916. return 0L;
  3917. }
  3918. SetRedraw( FALSE );
  3919. LRESULT lResult = CExtComboBox::WindowProc( message, wParam, lParam );
  3920. SetRedraw( TRUE );
  3921. Invalidate( TRUE );
  3922. UpdateWindow();
  3923. //_OnDrawComboImpl( false, false );
  3924. return lResult;
  3925. }
  3926. return CExtComboBox::WindowProc( message, wParam, lParam );
  3927. }
  3928. BOOL CExtCheckComboBox::PreTranslateMessage( MSG * pMsg )
  3929. {
  3930. if( pMsg->message == WM_MOUSEWHEEL )
  3931. return TRUE;
  3932. return CExtComboBox::PreTranslateMessage( pMsg );
  3933. }
  3934. void CExtCheckComboBox::PreSubclassWindow()
  3935. {
  3936. ASSERT_VALID( this );
  3937. m_bHaveItemHeight = m_bHaveText = false;
  3938. CExtComboBox::PreSubclassWindow();
  3939. }
  3940. void CExtCheckComboBox::PostNcDestroy()
  3941. {
  3942. ASSERT_VALID( this );
  3943. m_bHaveItemHeight = m_bHaveText = false;
  3944. CExtComboBox::PostNcDestroy();
  3945. }
  3946. void CExtCheckComboBox::_OnDrawComboImpl(
  3947. bool bPressed,
  3948. bool bHover,
  3949. CDC * pDC // = NULL
  3950. )
  3951. {
  3952. if( pDC != NULL )
  3953. {
  3954. if( AnimationClient_StatePaint( *pDC ) )
  3955. return;
  3956. }
  3957. bool bCallReleaseDC = false;
  3958. if( pDC == NULL )
  3959. {
  3960. pDC = GetDC();
  3961. ASSERT( pDC != NULL );
  3962. bCallReleaseDC = true;
  3963. }
  3964. DRAWITEMSTRUCT dis;
  3965. ::memset( &dis, 0, sizeof( DRAWITEMSTRUCT ) );
  3966. dis.CtlType = ODT_LISTBOX;
  3967. dis.CtlID = GetDlgCtrlID();
  3968. dis.itemID = UINT(-1);
  3969. dis.hDC = pDC->GetSafeHdc();
  3970. CRect rc;
  3971. GetClientRect( &rc );
  3972. rc.DeflateRect(
  3973. 3,
  3974. 3,
  3975. 3 + ::GetSystemMetrics( SM_CXVSCROLL ), // + PmBridge_GetPM()->GetDropDownButtonWidth(),
  3976. 3
  3977. );
  3978. ::CopyRect( &dis.rcItem, &rc );
  3979. dis.itemAction = ODA_DRAWENTIRE;
  3980. dis.hwndItem = GetSafeHwnd();
  3981. if( ::GetFocus() == m_hWnd )
  3982. dis.itemState |= ODS_FOCUS|ODS_SELECTED;
  3983. SendMessage( 
  3984. WM_DRAWITEM, 
  3985. (WPARAM)GetDlgCtrlID(), 
  3986. (LPARAM)&dis 
  3987. );
  3988. CExtComboBox::_OnDrawComboImpl( bPressed, bHover, pDC );
  3989. if( bCallReleaseDC )
  3990. ReleaseDC( pDC );
  3991. }
  3992. void CExtCheckComboBox::OnPaintItemCheck( CDC & dc, const RECT & rcCheck, INT nIndex )
  3993. {
  3994. ASSERT_VALID( this );
  3995. ASSERT( dc.GetSafeHdc() != NULL );
  3996. if( ! dc.RectVisible(&rcCheck) )
  3997. return;
  3998. ASSERT( nIndex >= 0 && nIndex < GetCount() );
  3999. bool bCheck = CheckGet( nIndex );
  4000. bool bDefaultDrawing = true;
  4001. if( g_PaintManager.m_UxTheme.IsControlsThemed()
  4002. && g_PaintManager.m_UxTheme.OpenThemeData( GetSafeHwnd(), L"BUTTON" ) != NULL
  4003. )
  4004. {
  4005. INT nState = 0;
  4006. INT nPartID = 0;
  4007. nPartID = BP_CHECKBOX;
  4008. if( bCheck )
  4009. nState = CBS_CHECKEDNORMAL;
  4010. else
  4011. nState = CBS_UNCHECKEDNORMAL;
  4012. if( g_PaintManager.m_UxTheme. DrawThemeBackground( dc.GetSafeHdc(), nPartID, nState, &rcCheck, &rcCheck ) == S_OK )
  4013. bDefaultDrawing = false;
  4014. g_PaintManager.m_UxTheme.CloseThemeData( true );
  4015. }
  4016. if( bDefaultDrawing )
  4017. {
  4018. UINT nState = DFCS_BUTTONCHECK;
  4019. if( bCheck )
  4020. nState |= DFCS_CHECKED;
  4021. dc.DrawFrameControl( (RECT *)&rcCheck, DFC_BUTTON, nState );
  4022. } // if( bDefaultDrawing )
  4023. }
  4024. void CExtCheckComboBox::DrawItem( LPDRAWITEMSTRUCT pDIS )
  4025. {
  4026. ASSERT_VALID( this );
  4027. ASSERT( GetSafeHwnd() != NULL );
  4028. CExtPaintManager * pPM = PmBridge_GetPM();
  4029. ASSERT_VALID( pPM );
  4030. CRect rcCheck( pDIS->rcItem ), rcText( pDIS->rcItem );
  4031. CString strText;
  4032. bool bCheckPresent = true;
  4033. bool bFR = ( (pDIS->itemState & (ODS_FOCUS|ODS_SELECTED)) == (ODS_FOCUS|ODS_SELECTED) ) ? true : false;
  4034. if( LONG( pDIS->itemID ) < 0L )
  4035. {
  4036. _UpdateText();
  4037. strText = LPCTSTR(m_strText);
  4038. bCheckPresent = false;
  4039. }
  4040. else
  4041. {
  4042. CSize _sizeBox( 13, 13 );
  4043. _sizeBox.cx = pPM->UiScalingDo( _sizeBox.cx, CExtPaintManager::__EUIST_X );
  4044. _sizeBox.cy = pPM->UiScalingDo( _sizeBox.cy, CExtPaintManager::__EUIST_Y );
  4045. GetLBText( pDIS->itemID, strText );
  4046. TEXTMETRIC _tm;
  4047. ::memset( &_tm, 0, sizeof(TEXTMETRIC) );
  4048. ::GetTextMetrics( pDIS->hDC, &_tm);
  4049. rcCheck.left ++;
  4050. rcCheck.right = rcCheck.left + _sizeBox.cx;
  4051. rcCheck.bottom = rcCheck.top + _sizeBox.cy;
  4052. rcCheck.OffsetRect( 0, ( rcText.Height() - rcCheck.Height() ) / 2 );
  4053. rcText.left = rcCheck.right + 2;
  4054. }
  4055. if( bCheckPresent )
  4056. OnPaintItemCheck( *CDC::FromHandle( pDIS->hDC ), rcCheck, pDIS->itemID );
  4057. if( pDIS->itemState & ODS_SELECTED )
  4058. {
  4059. ::SetBkColor( pDIS->hDC, pPM->GetColor( COLOR_HIGHLIGHT, this ) );
  4060. ::SetTextColor( pDIS->hDC, pPM->GetColor( COLOR_HIGHLIGHTTEXT, this ) );
  4061. }
  4062. else
  4063. {
  4064. ::SetBkColor( pDIS->hDC, pPM->GetColor( COLOR_WINDOW, this ) );
  4065. ::SetTextColor( pDIS->hDC, pPM->GetColor( COLOR_WINDOWTEXT, this ) );
  4066. }
  4067. HFONT hFont = OnQueryFont();
  4068. if( hFont == NULL )
  4069. hFont = (HFONT)PmBridge_GetPM()->m_FontNormal.GetSafeHandle();
  4070. ASSERT( hFont != NULL );
  4071. HFONT hOldFont = (HFONT)::SelectObject( pDIS->hDC, hFont );
  4072. ::ExtTextOut( pDIS->hDC, 0, 0, ETO_OPAQUE, &rcText, 0, 0, 0 );
  4073. ::DrawText( pDIS->hDC, _T(" ") + strText, strText.GetLength() + 1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS );
  4074. if( bFR )
  4075. ::DrawFocusRect( pDIS->hDC, &rcText );
  4076. ::SelectObject( pDIS->hDC, hOldFont );
  4077. }
  4078. void CExtCheckComboBox::MeasureItem( LPMEASUREITEMSTRUCT pMIS )
  4079. {
  4080. ASSERT_VALID( this );
  4081. ASSERT( GetSafeHwnd() != NULL );
  4082. CClientDC dc(this);
  4083. HFONT hFont = OnQueryFont();
  4084. if( hFont == NULL )
  4085. hFont = (HFONT)PmBridge_GetPM()->m_FontNormal.GetSafeHandle();
  4086. ASSERT( hFont != NULL );
  4087. HFONT hOldFont = (HFONT)dc.SelectObject( hFont );
  4088. TEXTMETRIC _tm;
  4089. ::memset( &_tm, 0, sizeof(TEXTMETRIC) );
  4090. dc.GetTextMetrics( &_tm );
  4091. pMIS->itemWidth = 20;
  4092. pMIS->itemHeight = _tm.tmHeight + _tm.tmExternalLeading;
  4093. pMIS->itemHeight += 2;
  4094. if( ! m_bHaveItemHeight )
  4095. {
  4096. m_bHaveItemHeight = true;
  4097. SetItemHeight( -1, pMIS->itemHeight );
  4098. }
  4099. dc.SelectObject( hOldFont );
  4100. }
  4101. LRESULT CExtCheckComboBox::OnGetText( WPARAM wParam, LPARAM lParam )
  4102. {
  4103. ASSERT_VALID( this );
  4104. ASSERT( GetSafeHwnd() != NULL );
  4105. _UpdateText();
  4106. if( lParam == 0 )
  4107. return 0;
  4108. __EXT_MFC_STRCPY( (LPTSTR)lParam, (INT)wParam, LPCTSTR(m_strText) );
  4109. LRESULT lr = LRESULT( m_strText.GetLength() );
  4110. return lr;
  4111. }
  4112. LRESULT CExtCheckComboBox::OnGetTextLength(WPARAM, LPARAM)
  4113. {
  4114. ASSERT_VALID( this );
  4115. ASSERT( GetSafeHwnd() != NULL );
  4116. _UpdateText();
  4117. LRESULT lr = LRESULT( m_strText.GetLength() );
  4118. return lr;
  4119. }
  4120. void CExtCheckComboBox::_UpdateText()
  4121. {
  4122. ASSERT_VALID( this );
  4123. ASSERT( GetSafeHwnd() != NULL );
  4124. if(  m_bHaveText )
  4125. return;
  4126. INT nIndex, nCount = GetCount();
  4127. TCHAR szBuffer[10] = _T("");
  4128. g_ResourceManager->GetLocaleInfo( LOCALE_SLIST, szBuffer, sizeof(szBuffer) );
  4129. CExtSafeString strSeparator = szBuffer;
  4130. if( strSeparator.GetLength() == 0 )
  4131. strSeparator = _T(";");
  4132. strSeparator.TrimRight();
  4133. strSeparator += _T(' ');
  4134. m_strText.Empty();
  4135. for( nIndex = 0; nIndex < nCount; nIndex++ )
  4136. {
  4137. if( ! CheckGet( nIndex ) )
  4138. continue;
  4139. CString strItem;
  4140. GetLBText( nIndex, strItem );
  4141. if( ! m_strText.IsEmpty() )
  4142. m_strText += LPCTSTR(strSeparator);
  4143. m_strText += LPCTSTR(strItem);
  4144. }
  4145. m_bHaveText = true;
  4146. }
  4147. void CExtCheckComboBox::CheckSet(
  4148. INT nIndex,
  4149. bool bCheck // = true
  4150. )
  4151. {
  4152. ASSERT_VALID( this );
  4153. if( GetSafeHwnd() == NULL )
  4154. return;
  4155. INT nResult = SetItemData( nIndex, bCheck ? 1 : 0 );
  4156. if( nResult < 0 )
  4157. return;
  4158. m_bHaveText = false;
  4159. Invalidate( FALSE );
  4160. }
  4161. bool CExtCheckComboBox::CheckGet( INT nIndex ) const
  4162. {
  4163. ASSERT_VALID( this );
  4164. if( GetSafeHwnd() == NULL )
  4165. return false;
  4166. bool bCheck = ( GetItemData( nIndex ) != 0 ) ? true : false;
  4167. return bCheck;
  4168. }
  4169. void CExtCheckComboBox::CheckAll(
  4170. bool bCheck // = true
  4171. )
  4172. {
  4173. ASSERT_VALID( this );
  4174. if( GetSafeHwnd() == NULL )
  4175. return;
  4176. INT nIndex, nCount = GetCount();
  4177. for( nIndex = 0; nIndex < nCount; nIndex++ )
  4178. CheckSet( nIndex, bCheck );
  4179. }
  4180. bool CExtCheckComboBox::_OnCbLbPreWndProc( LRESULT & lResult, UINT message, WPARAM wParam, LPARAM lParam )
  4181. {
  4182. lResult; lParam;
  4183. switch( message )
  4184. {
  4185. case WM_CHAR:
  4186. {
  4187. if( wParam == VK_SPACE)
  4188. {
  4189. CExtComboBoxPopupListBox * pLB = OnComboBoxPopupListBoxQuery();
  4190. ASSERT_VALID( pLB );
  4191. INT nIndex = INT( pLB->SendMessage( LB_GETCURSEL ) );
  4192. CRect rcItem;
  4193. pLB->SendMessage( LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem );
  4194. pLB->InvalidateRect( rcItem, FALSE );
  4195. CheckSet( nIndex, ! CheckGet( nIndex ) );
  4196. GetParent()->SendMessage(
  4197. WM_COMMAND,
  4198. MAKELONG( ::__EXT_MFC_GetWindowLong( m_hWnd, GWL_ID ), CBN_SELCHANGE ),
  4199. (LPARAM)m_hWnd
  4200. );
  4201. lResult = 0L;
  4202. return true;
  4203. }
  4204. }
  4205. break;
  4206. case WM_LBUTTONDOWN:
  4207. {
  4208. CExtComboBoxPopupListBox * pLB = OnComboBoxPopupListBoxQuery();
  4209. ASSERT_VALID( pLB );
  4210. CRect rcClient;
  4211. pLB->GetClientRect( &rcClient );
  4212. CPoint pt( LOWORD(lParam), HIWORD(lParam) );
  4213. if( PtInRect( rcClient, pt ) )
  4214. {
  4215. INT nItemHeight = INT( pLB->SendMessage( LB_GETITEMHEIGHT, 0, 0 ) );
  4216. INT nTopIndex   = INT( pLB->SendMessage( LB_GETTOPINDEX, 0, 0 ) );
  4217. INT nIndex = nTopIndex + pt.y / nItemHeight;
  4218. CRect rcItem;
  4219. pLB->SendMessage( LB_GETITEMRECT, nIndex, (LONG)(VOID *)&rcItem );
  4220. if( PtInRect( rcItem, pt ) )
  4221. {
  4222. pLB->InvalidateRect( rcItem, FALSE );
  4223. CheckSet(nIndex, ! CheckGet( nIndex ) );
  4224. GetParent()->SendMessage(
  4225. WM_COMMAND,
  4226. MAKELONG( ::__EXT_MFC_GetWindowLong( m_hWnd, GWL_ID ), CBN_SELCHANGE ),
  4227. (LPARAM)m_hWnd
  4228. );
  4229. }
  4230. }
  4231. }
  4232. break;
  4233. case WM_LBUTTONUP:
  4234. lResult = 0L;
  4235. return true;
  4236. } // switch( message )
  4237. return false;
  4238. }