DropListBox.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /////////////////////////////////////////////////////////////////////////////
  2. // DropListBox.cpp : implementation file
  3. //
  4. // CAdvComboBox Control
  5. // Version: 2.1
  6. // Date: September 2002
  7. // Author: Mathias Tunared
  8. // Email: Mathias@inorbit.com
  9. // Copyright (c) 2002. All Rights Reserved.
  10. //
  11. // This code, in compiled form or as source code, may be redistributed
  12. // unmodified PROVIDING it is not sold for profit without the authors
  13. // written consent, and providing that this notice and the authors name
  14. // and all copyright notices remains intact.
  15. //
  16. // This file is provided "as is" with no expressed or implied warranty.
  17. // The author accepts no liability for any damage/loss of business that
  18. // this product may cause.
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #include "stdafx.h"
  22. #include "DropListBox.h"
  23. #include "AdvComboBox.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CDropListBox
  31. CDropListBox::CDropListBox( CWnd* pComboParent, CDropScrollBar* pScroll )
  32. :
  33. m_pComboParent( pComboParent ),
  34. m_pScroll( pScroll )
  35. {
  36. m_pListFont = new CFont;
  37. LOGFONT logFont;
  38. memset( &logFont, 0, sizeof(LOGFONT) );
  39. _tcscpy( logFont.lfFaceName, _T("MS Sans Serif") );
  40. logFont.lfHeight = 20;
  41. m_pListFont->CreateFontIndirect(&logFont);
  42. m_nLastTopIdx = 0;
  43. m_dwACBStyle = 0;
  44. m_bSelectDisabled = FALSE;
  45. }
  46. CDropListBox::~CDropListBox()
  47. {
  48. delete m_pListFont;
  49. }
  50. BEGIN_MESSAGE_MAP(CDropListBox, CListBox)
  51. //{{AFX_MSG_MAP(CDropListBox)
  52. ON_WM_CREATE()
  53. ON_WM_MOUSEMOVE()
  54. ON_WM_LBUTTONUP()
  55. //}}AFX_MSG_MAP
  56. ON_MESSAGE( WM_VRC_SETCAPTURE, OnSetCapture )
  57. ON_MESSAGE( WM_VRC_RELEASECAPTURE, OnReleaseCapture )
  58. END_MESSAGE_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CDropListBox message handlers
  61. int CDropListBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
  62. {
  63. if (CListBox::OnCreate(lpCreateStruct) == -1)
  64. return -1;
  65. // Because this window doesn't have an owner, there will appear
  66. // a 'blank' button on the taskbar. The following are to hide
  67. // that 'blank' button on the taskbar
  68. ShowWindow( SW_HIDE );
  69. ModifyStyleEx( 0, WS_EX_TOOLWINDOW );// |WS_VSCROLL );//| WS_EX_NOACTIVATE ); // WS_EX_CONTROLPARENT
  70. ShowWindow( SW_SHOW );
  71. SetWindowPos( &wndTopMost, lpCreateStruct->x, lpCreateStruct->y,
  72. lpCreateStruct->cx, lpCreateStruct->cy, SWP_SHOWWINDOW );
  73. SetFont( static_cast<CAdvComboBox*>(m_pComboParent)->GetFont() );
  74. return 0;
  75. }
  76. LONG CDropListBox::OnSetCapture( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  77. {
  78. SetCapture();
  79. return FALSE;
  80. }
  81. LONG CDropListBox::OnReleaseCapture( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  82. {
  83. ReleaseCapture();
  84. return FALSE;
  85. }
  86. void CDropListBox::OnMouseMove(UINT nFlags, CPoint point)
  87. {
  88. //
  89. // Is mouse within listbox
  90. CRect rcClient;
  91. GetClientRect( rcClient );
  92. if( !rcClient.PtInRect( point ) )
  93. {
  94. ReleaseCapture();
  95. GetParent()->SendMessage( WM_VRC_SETCAPTURE );
  96. }
  97. //
  98. // Set selection item under mouse
  99. int nPos = point.y / GetItemHeight(0) + GetTopIndex();
  100. PLIST_ITEM pItem = (PLIST_ITEM)GetItemDataPtr(nPos);
  101. if( (DWORD)pItem != -1 )
  102. {
  103. if( GetCurSel() != nPos && !pItem->bDisabled )
  104. {
  105. SetCurSel( nPos );
  106. }
  107. }
  108. //
  109. // Check if we have autoscrolled
  110. if( m_nLastTopIdx != GetTopIndex() )
  111. {
  112. //int nDiff = m_nLastTopIdx - GetTopIndex();
  113. m_nLastTopIdx = GetTopIndex();
  114. SCROLLINFO info;
  115. info.cbSize = sizeof(SCROLLINFO);
  116. if( m_pScroll->GetScrollInfo( &info, SIF_ALL|SIF_DISABLENOSCROLL ) )
  117. {
  118. info.nPos = m_nLastTopIdx;
  119. m_pScroll->SetScrollInfo( &info );
  120. }
  121. }
  122. CListBox::OnMouseMove(nFlags, point);
  123. }
  124. void CDropListBox::OnLButtonUp(UINT nFlags, CPoint point)
  125. {
  126. OnLButtonDown(nFlags, point);
  127. // CListBox::OnLButtonUp(nFlags, point);
  128. }
  129. void CDropListBox::OnLButtonDown(UINT /*nFlags*/, CPoint point)
  130. {
  131. //
  132. // Is mouse within listbox
  133. CRect rcClient;
  134. GetClientRect( rcClient );
  135. if( !rcClient.PtInRect( point ) )
  136. {
  137. ReleaseCapture();
  138. GetParent()->SendMessage( WM_VRC_SETCAPTURE );
  139. }
  140. //
  141. // Set selection item under mouse
  142. int nPos = point.y / GetItemHeight(0) + GetTopIndex();
  143. PLIST_ITEM pItem = (PLIST_ITEM)GetItemDataPtr(nPos);
  144. if( (DWORD)pItem != -1 )
  145. {
  146. if( pItem->bDisabled )
  147. {
  148. return;
  149. }
  150. }
  151. nPos = GetCurSel();
  152. //
  153. // Is selected item disabled
  154. if( nPos != LB_ERR )
  155. {
  156. PLIST_ITEM pItem;
  157. pItem = (PLIST_ITEM)GetItemDataPtr( nPos );
  158. if( pItem->bDisabled )
  159. {
  160. return;
  161. }
  162. }
  163. //
  164. // Send current selection to comboedit
  165. if( nPos != -1 )
  166. m_pComboParent->PostMessage( WM_SELECTED_ITEM, (WPARAM)nPos, 0 );
  167. //
  168. // Destroy dropdown
  169. ReleaseCapture();
  170. m_pComboParent->PostMessage( WM_DESTROY_DROPLIST );
  171. // CListBox::OnLButtonDown(nFlags, point);
  172. }
  173. int CDropListBox::GetBottomIndex()
  174. {
  175. int nTop = GetTopIndex();
  176. CRect rc;
  177. GetClientRect( &rc );
  178. int nVisCount = rc.Height() / GetItemHeight(0);
  179. return nTop + nVisCount;
  180. }
  181. void CDropListBox::SetTopIdx(int nPos, BOOL bUpdateScrollbar)
  182. {
  183. m_nLastTopIdx = nPos;
  184. SetTopIndex( nPos );
  185. if( bUpdateScrollbar )
  186. {
  187. SCROLLINFO info;
  188. info.cbSize = sizeof(SCROLLINFO);
  189. if( m_pScroll->GetScrollInfo( &info, SIF_ALL|SIF_DISABLENOSCROLL ) )
  190. {
  191. info.nPos = m_nLastTopIdx;
  192. m_pScroll->SetScrollInfo( &info );
  193. }
  194. }
  195. }
  196. void CDropListBox::GetTextSize(LPCTSTR lpszText, int nCount, CSize &size)
  197. {
  198. CClientDC dc(this);
  199. int nSave = dc.SaveDC();
  200. dc.SelectObject( static_cast<CAdvComboBox*>(m_pComboParent)->GetFont() );
  201. size = dc.GetTextExtent( lpszText, nCount );
  202. if( m_dwACBStyle & ACBS_CHECKED )
  203. {
  204. size.cx += 14;
  205. }
  206. dc.RestoreDC(nSave);
  207. }
  208. int CDropListBox::AddListItem( LIST_ITEM& item )
  209. {
  210. PLIST_ITEM pItem = new LIST_ITEM;
  211. *pItem = item;
  212. int nPos = AddString( pItem->strText.c_str() );
  213. SetItemDataPtr( nPos, (void*)pItem );
  214. return nPos;
  215. }
  216. BOOL CDropListBox::DestroyWindow()
  217. {
  218. PLIST_ITEM pItem;
  219. for( int i = 0; i < GetCount(); i++ )
  220. {
  221. pItem = (PLIST_ITEM)GetItemDataPtr( i );
  222. delete pItem;
  223. }
  224. return CListBox::DestroyWindow();
  225. }
  226. void CDropListBox::SetDLBStyle(DWORD dwStyle)
  227. {
  228. m_dwACBStyle = dwStyle;
  229. }
  230. int CDropListBox::SetCurSel(int nSelect)
  231. {
  232. PLIST_ITEM pItem = NULL;
  233. int nCur = GetCurSel();
  234. int nWay = nSelect - nCur;
  235. int nTmp = nSelect;
  236. if( !m_bSelectDisabled )
  237. {
  238. // Select the next in list the is NOT disabled
  239. if( nWay < 0 )
  240. {
  241. // Select previous in list
  242. pItem = (PLIST_ITEM)GetItemDataPtr( nTmp );
  243. while( (DWORD)pItem != -1 )
  244. {
  245. if( !pItem->bDisabled )
  246. {
  247. nSelect = nTmp;
  248. break;
  249. }
  250. nTmp--;
  251. pItem = (PLIST_ITEM)GetItemDataPtr( nTmp );
  252. }
  253. }
  254. else
  255. if( nWay > 0 )
  256. {
  257. // Select next in list
  258. pItem = (PLIST_ITEM)GetItemDataPtr( nTmp );
  259. while( (DWORD)pItem != -1 )
  260. {
  261. if( !pItem->bDisabled )
  262. {
  263. nSelect = nTmp;
  264. break;
  265. }
  266. nTmp++;
  267. pItem = (PLIST_ITEM)GetItemDataPtr( nTmp );
  268. }
  269. }
  270. }
  271. pItem = (PLIST_ITEM)GetItemDataPtr( nSelect);
  272. if( (DWORD)pItem != -1 )
  273. {
  274. if( pItem->bDisabled )
  275. {
  276. return nSelect;
  277. }
  278. }
  279. int nr = CListBox::SetCurSel( nSelect );
  280. if( nr != -1 )
  281. {
  282. //
  283. // Set scrollbar
  284. int nTopIdx = GetTopIndex();
  285. SCROLLINFO info;
  286. info.cbSize = sizeof(SCROLLINFO);
  287. if( m_pScroll->GetScrollInfo( &info, SIF_ALL|SIF_DISABLENOSCROLL ) )
  288. {
  289. info.nPos = nTopIdx;
  290. m_pScroll->SetScrollInfo( &info );
  291. }
  292. }
  293. return nr;
  294. }
  295. int CDropListBox::GetMaxVisibleItems()
  296. {
  297. CRect rectClient;
  298. GetClientRect(&rectClient);
  299. int n = rectClient.Height() / GetItemHeight(0);
  300. return n;
  301. }