AdvComboBox.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. /////////////////////////////////////////////////////////////////////////////
  2. // AdvComboBox.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 "AdvComboBox.h"
  23. #include "VisualStylesXP.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. #define IDC_COMBOEDIT 108
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CAdvComboBox
  32. IMPLEMENT_DYNAMIC(CAdvComboBox, CWnd)
  33. CAdvComboBox::CAdvComboBox( BOOL bInst, CWnd * pParent ) :
  34. m_pDropWnd(0),
  35. m_bDropListVisible(0),
  36. m_bInst( bInst ),
  37. m_pParent(pParent)
  38. {
  39. XLISTCTRL_TRACE(_T("in CAdvComboBox::CAdvComboBox\n"));
  40. RegisterWindowClass();
  41. m_pEdit = NULL;
  42. m_zDelta = 0;
  43. m_nCurSel = -1;
  44. m_bDropRectStored= false;
  45. m_bHasFocus = false;
  46. m_bHasSentFocus = false;
  47. m_bSelItem = false;
  48. m_bFirstPaint = true;
  49. m_nMinVisItems = 5;
  50. m_bCodeCreate = false;
  51. m_bAutoAppend = TRUE;
  52. m_bDropButtonHot = false;
  53. m_bTrackMouseLeave = false;
  54. m_nDefaultDropItems = -1;
  55. m_dwACBStyle = 0;
  56. m_dwACBStyle |= ACBS_STANDARD;
  57. m_pFont = NULL;
  58. }
  59. CAdvComboBox::~CAdvComboBox()
  60. {
  61. XLISTCTRL_TRACE(_T("in CAdvComboBox::~CAdvComboBox\n"));
  62. delete m_pFont;
  63. if( m_pDropWnd )
  64. {
  65. m_pDropWnd->ShowWindow( SW_HIDE );
  66. m_bDropListVisible = FALSE;
  67. m_pDropWnd->DestroyWindow();
  68. delete m_pDropWnd;
  69. m_pDropWnd = NULL;
  70. }
  71. if( m_pEdit )
  72. {
  73. m_pEdit->DestroyWindow();
  74. delete m_pEdit;
  75. }
  76. }
  77. BEGIN_MESSAGE_MAP(CAdvComboBox, CWnd)
  78. //{{AFX_MSG_MAP(CAdvComboBox)
  79. ON_WM_CREATE()
  80. ON_WM_PAINT()
  81. ON_WM_ERASEBKGND()
  82. ON_WM_LBUTTONDOWN()
  83. ON_WM_MOUSEWHEEL()
  84. ON_WM_SIZE()
  85. ON_WM_SETFOCUS()
  86. ON_WM_KILLFOCUS()
  87. ON_WM_SHOWWINDOW()
  88. ON_WM_ENABLE()
  89. ON_WM_CHILDACTIVATE()
  90. ON_WM_MOUSEMOVE()
  91. ON_WM_TIMER()
  92. ON_WM_CHAR()
  93. ON_WM_KEYDOWN()
  94. //ON_WM_ACTIVATEAPP()
  95. //}}AFX_MSG_MAP
  96. ON_MESSAGE( WM_SELECTED_ITEM, OnSelectedItem )
  97. ON_MESSAGE( WM_ON_DROPDOWN_BUTTON, OnDropdownButton )
  98. ON_MESSAGE( WM_DESTROY_DROPLIST, OnDestroyDropdownList )
  99. ON_EN_KILLFOCUS(IDC_COMBOEDIT, OnKillfocusEdit)
  100. ON_EN_SETFOCUS(IDC_COMBOEDIT, OnSetfocusEdit)
  101. ON_EN_CHANGE(IDC_COMBOEDIT, OnChangeEdit)
  102. ON_EN_UPDATE(IDC_COMBOEDIT, OnUpdateEdit)
  103. ON_MESSAGE( CB_ADDSTRING, OnAddString )
  104. ON_MESSAGE( CB_SETCURSEL, OnSetCurSel )
  105. ON_MESSAGE( CB_GETCURSEL, OnGetCurSel )
  106. ON_MESSAGE( CB_SELECTSTRING, OnSelectString )
  107. ON_MESSAGE( CB_GETCOUNT, OnGetCount )
  108. ON_MESSAGE( CB_RESETCONTENT, OnResetContent )
  109. ON_MESSAGE( CB_GETLBTEXT, OnGetLBText )
  110. ON_MESSAGE( CB_GETLBTEXTLEN, OnGetLBTextLen )
  111. ON_MESSAGE( CB_GETTOPINDEX, OnGetTopIndex )
  112. ON_MESSAGE( CB_SETTOPINDEX, OnSetTopIndex )
  113. END_MESSAGE_MAP()
  114. /////////////////////////////////////////////////////////////////////////////
  115. // CAdvComboBox message handlers
  116. LONG CAdvComboBox::OnAddString( WPARAM /*wParam*/, LPARAM lString )
  117. {
  118. TCHAR* pStr = (TCHAR*)lString;
  119. return AddString( pStr );
  120. }
  121. LONG CAdvComboBox::OnSetCurSel( WPARAM wIndex, LPARAM /*lParam*/ )
  122. {
  123. int nIndex = (int)wIndex;
  124. return SetCurSel( nIndex );
  125. }
  126. LONG CAdvComboBox::OnGetCurSel( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  127. {
  128. return GetCurSel();
  129. }
  130. LONG CAdvComboBox::OnSelectString( WPARAM wItemStart, LPARAM lString )
  131. {
  132. int nItem = (int)wItemStart;
  133. TCHAR* pStr = (TCHAR*)lString;
  134. int nIndex = FindStringExact( nItem, pStr );
  135. return SetCurSel( nIndex );
  136. }
  137. LONG CAdvComboBox::OnGetCount( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  138. {
  139. return GetCount();
  140. }
  141. LONG CAdvComboBox::OnResetContent( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  142. {
  143. m_list.clear();
  144. m_strEdit = _T("");
  145. m_nCurSel = -1;
  146. SetWindowText( _T("") );
  147. if( m_pEdit )
  148. {
  149. m_pEdit->SetWindowText( _T("") );
  150. }
  151. Invalidate();
  152. return CB_OKAY;
  153. }
  154. LONG CAdvComboBox::OnGetLBText( WPARAM wIndex, LPARAM lString )
  155. {
  156. int nIndex = (int)wIndex;
  157. TCHAR* pOutStr = (TCHAR*)lString;
  158. return GetLBText( nIndex, pOutStr );
  159. }
  160. LONG CAdvComboBox::OnGetLBTextLen( WPARAM wIndex, LPARAM /*lParam*/ )
  161. {
  162. int nIndex = (int)wIndex;
  163. return GetLBTextLen( nIndex );
  164. }
  165. LONG CAdvComboBox::OnGetTopIndex( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  166. {
  167. return GetTopIndex();
  168. }
  169. LONG CAdvComboBox::OnSetTopIndex( WPARAM wIndex, LPARAM /*lParam*/ )
  170. {
  171. return SetTopIndex(wIndex);
  172. }
  173. BOOL CAdvComboBox::RegisterWindowClass()
  174. {
  175. WNDCLASS wndcls;
  176. HINSTANCE hInst;
  177. hInst = AfxGetInstanceHandle();
  178. ASSERT( hInst != 0 );
  179. if( !(::GetClassInfo(hInst, ADVCOMBOBOXCTRL_CLASSNAME, &wndcls)) )
  180. {
  181. wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  182. wndcls.lpfnWndProc = ::DefWindowProc;
  183. wndcls.cbClsExtra = 0;
  184. wndcls.cbWndExtra = 0;
  185. wndcls.hInstance = hInst;
  186. wndcls.hIcon = NULL;
  187. wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
  188. wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW);
  189. wndcls.lpszMenuName = NULL;
  190. wndcls.lpszClassName = ADVCOMBOBOXCTRL_CLASSNAME;
  191. if( !AfxRegisterClass(&wndcls) )
  192. {
  193. AfxThrowResourceException();
  194. return FALSE;
  195. }
  196. }
  197. return TRUE;
  198. }
  199. BOOL CAdvComboBox::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID )
  200. {
  201. XLISTCTRL_TRACE(_T("in CAdvComboBox::Create\n"));
  202. m_rcCombo = rect;
  203. m_bCodeCreate = true;
  204. m_dwACBStyle |= ACBS_STANDARD;
  205. m_dwStyle = dwStyle;
  206. LoadString( nID );
  207. BOOL bRet = CWnd::Create(NULL, _T(""), dwStyle, m_rcCombo, pParentWnd, nID );
  208. return bRet;
  209. }
  210. void CAdvComboBox::LoadString( UINT nStringID )
  211. {
  212. UINT nIDS;
  213. if( nStringID )
  214. nIDS = nStringID;
  215. else
  216. {
  217. nIDS = GetWindowLong( GetSafeHwnd(), GWL_ID );
  218. }
  219. //
  220. // Load string from resources
  221. CString strItems;
  222. if( !strItems.LoadString( nIDS ) )
  223. {
  224. return;
  225. }
  226. //
  227. // Clear the list
  228. m_list.clear();
  229. //
  230. // Go through the string and look after '\n'.
  231. TCHAR seps[] = _T("\n");
  232. TCHAR *token;
  233. int nLen = strItems.GetLength();
  234. TCHAR* szTok = new TCHAR[nLen+5];
  235. memset( szTok, 0, (nLen+5)*sizeof(TCHAR) );
  236. _tcscpy( szTok, (LPCTSTR)strItems );
  237. token = _tcstok( szTok, seps );
  238. while( token != NULL )
  239. {
  240. AddString( token );
  241. token = _tcstok( NULL, seps );
  242. }
  243. //
  244. // Add item to list
  245. //+++
  246. delete [] szTok;
  247. }
  248. int CAdvComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
  249. {
  250. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnCreate\n"));
  251. if (CWnd::OnCreate(lpCreateStruct) == -1)
  252. return -1;
  253. if( !m_pFont )
  254. {
  255. LOGFONT logFont;
  256. memset( &logFont, 0, sizeof(LOGFONT) );
  257. CFont* pF = m_pParent->GetFont();
  258. ASSERT(pF);
  259. pF->GetLogFont( &logFont );
  260. m_pFont = new CFont;
  261. m_pFont->CreateFontIndirect(&logFont);
  262. SetFont( m_pFont );
  263. }
  264. return 0;
  265. }
  266. void CAdvComboBox::PreSubclassWindow()
  267. {
  268. XLISTCTRL_TRACE(_T("in CAdvComboBox::PreSubclassWindow\n"));
  269. if (m_pParent == NULL)
  270. m_pParent = GetParent();
  271. ASSERT(m_pParent);
  272. // TODO: Add your specialized code here and/or call the base class
  273. LoadString();
  274. if( !m_pFont )
  275. {
  276. LOGFONT logFont;
  277. memset( &logFont, 0, sizeof(LOGFONT) );
  278. CFont* pF = m_pParent->GetFont();
  279. ASSERT(pF);
  280. pF->GetLogFont( &logFont );
  281. m_pFont = new CFont;
  282. m_pFont->CreateFontIndirect(&logFont);
  283. SetFont( m_pFont );
  284. }
  285. if( !m_bCodeCreate )
  286. {
  287. //
  288. // Do we need to show an edit control. (CBS_DROPDOWN)
  289. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  290. {
  291. if( !m_pEdit )
  292. {
  293. CRect rect;
  294. GetClientRect(rect);
  295. rect.right = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
  296. if( m_dwACBStyle & ACBS_STANDARD )
  297. {
  298. rect.DeflateRect( 2, 2 );
  299. rect.left += 1;
  300. rect.top += 2;
  301. //rect.bottom += 2;
  302. }
  303. XLISTCTRL_TRACE(_T("creating edit\n"));
  304. m_pEdit = new CAdvComboEdit; //+++
  305. ASSERT(m_pEdit);
  306. DWORD dwStyle = 0;
  307. dwStyle = WS_VISIBLE | WS_CHILD;
  308. if( GetStyle() & CBS_AUTOHSCROLL )
  309. {
  310. dwStyle |= ES_AUTOHSCROLL;
  311. }
  312. VERIFY(m_pEdit->Create( dwStyle, rect, this, IDC_COMBOEDIT ));
  313. m_pEdit->SetFont( m_pFont );
  314. m_pEdit->SetWindowText( m_strEdit.c_str() );
  315. }
  316. }
  317. }
  318. CWnd::PreSubclassWindow();
  319. }
  320. void CAdvComboBox::OnChildActivate()
  321. {
  322. CWnd::OnChildActivate();
  323. // TODO: Add your message handler code here
  324. if( !m_pFont )
  325. {
  326. LOGFONT logFont;
  327. memset( &logFont, 0, sizeof(LOGFONT) );
  328. CFont* pF = m_pParent->GetFont();
  329. pF->GetLogFont( &logFont );
  330. m_pFont = new CFont;
  331. m_pFont->CreateFontIndirect(&logFont);
  332. SetFont( m_pFont );
  333. }
  334. if( m_bCodeCreate )
  335. {
  336. //
  337. // Do we need to show an edit control. (CBS_DROPDOWN)
  338. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  339. {
  340. if( !m_pEdit )
  341. {
  342. CRect rect;
  343. GetClientRect(rect);
  344. rect.right = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
  345. if( m_dwACBStyle & ACBS_STANDARD )
  346. {
  347. rect.DeflateRect( 2, 2 );
  348. rect.left += 1;
  349. rect.top += 2;
  350. //rect.bottom += 2;
  351. }
  352. m_pEdit = new CAdvComboEdit; //+++
  353. DWORD dwStyle = 0;
  354. dwStyle = WS_VISIBLE | WS_CHILD;
  355. if( GetStyle() & CBS_AUTOHSCROLL )
  356. {
  357. dwStyle |= ES_AUTOHSCROLL;
  358. }
  359. m_pEdit->Create( dwStyle, rect, this, IDC_COMBOEDIT );
  360. m_pEdit->SetFont( m_pFont );
  361. m_pEdit->SetWindowText( m_strEdit.c_str() );
  362. }
  363. }
  364. }
  365. }
  366. void CAdvComboBox::OnPaint()
  367. {
  368. CPaintDC dc(this); // device context for painting
  369. if( m_nCurSel != -1 )
  370. {
  371. m_iter = m_list.begin();
  372. advance( m_iter, m_nCurSel );
  373. if( m_iter != m_list.end() )
  374. {
  375. m_strEdit = m_iter->strText;
  376. }
  377. if( m_bFirstPaint )
  378. {
  379. if( m_pEdit )
  380. {
  381. m_pEdit->SetWindowText( m_strEdit.c_str() );
  382. m_bFirstPaint = false;
  383. m_pEdit->EnableWindow( IsWindowEnabled() );
  384. }
  385. }
  386. }
  387. CRect rect;
  388. CRect rcText;
  389. GetClientRect(rect);
  390. rcText = rect;
  391. rect.left = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
  392. rcText.right = rect.left-1;
  393. m_rcDropButton = rect;
  394. GetClientRect(rect);
  395. BOOL bWndEnabled = IsWindowEnabled();
  396. COLORREF clrDisabledBkg = ::GetSysColor(COLOR_BTNFACE);
  397. COLORREF clrDisabledBorder = ::GetSysColor(COLOR_3DDKSHADOW);
  398. COLORREF clrDisabledText = ::GetSysColor(COLOR_GRAYTEXT);
  399. if( !bWndEnabled )
  400. {
  401. if( 1 ) // Draw disabled flat control with border? Change to '0'.
  402. {
  403. dc.FillSolidRect( rect, clrDisabledBkg );
  404. }
  405. else
  406. {
  407. CBrush brDisabled(clrDisabledBkg);
  408. CBrush* pOldBrush = dc.SelectObject(&brDisabled);
  409. CPen penDisabled( PS_SOLID, 0, clrDisabledBorder);
  410. CPen* pOldPen = dc.SelectObject(&penDisabled);
  411. dc.Rectangle(rect);
  412. dc.SelectObject(pOldBrush);
  413. dc.SelectObject(pOldPen);
  414. }
  415. }
  416. else
  417. {
  418. COLORREF clrEnabledBkg = ::GetSysColor(COLOR_WINDOW);
  419. dc.FillSolidRect( rect, clrEnabledBkg );
  420. }
  421. DWORD dwBtnStyle = 0;
  422. if( !bWndEnabled )
  423. {
  424. dwBtnStyle |= DFCS_INACTIVE;
  425. }
  426. dwBtnStyle |= m_bDropListVisible ? (DFCS_SCROLLDOWN|DFCS_PUSHED|DFCS_FLAT) : DFCS_SCROLLDOWN;
  427. BOOL bThemeActive = FALSE;
  428. HRESULT hr;
  429. bThemeActive = g_xpStyle.UseVisualStyles();
  430. HTHEME hTheme = NULL;
  431. if( bThemeActive )
  432. hTheme = g_xpStyle.OpenThemeData( m_hWnd, L"COMBOBOX" );
  433. // Theme drop btn style
  434. int nDropBtnThemeStyle = 0;
  435. if( m_bDropListVisible )
  436. {
  437. nDropBtnThemeStyle = CBXS_PRESSED;
  438. }
  439. else
  440. {
  441. nDropBtnThemeStyle = CBXS_NORMAL;
  442. if( m_bDropButtonHot )
  443. nDropBtnThemeStyle = CBXS_HOT;
  444. if( !bWndEnabled )
  445. nDropBtnThemeStyle = CBXS_DISABLED;
  446. }
  447. #if 0 // -----------------------------------------------------------
  448. if( m_dwACBStyle & ACBS_FLAT )
  449. {
  450. if( bThemeActive )
  451. {
  452. hr = g_xpStyle.DrawThemeBackground( hTheme, dc.m_hDC, CP_DROPDOWNBUTTON, nDropBtnThemeStyle, &m_rcDropButton, NULL);
  453. }
  454. else
  455. {
  456. dc.DrawFrameControl(m_rcDropButton, DFC_SCROLL, dwBtnStyle );
  457. }
  458. }
  459. else
  460. if( m_dwACBStyle & ACBS_STANDARD )
  461. #endif // -----------------------------------------------------------
  462. {
  463. if( bThemeActive )
  464. {
  465. COLORREF clrBorder;
  466. hr = g_xpStyle.GetThemeColor( hTheme, BP_PUSHBUTTON, bWndEnabled ? PBS_NORMAL : PBS_DISABLED, TMT_BORDERCOLOR, &clrBorder );
  467. if( FAILED( hr ) )
  468. {
  469. clrBorder = RGB(0,0,0);
  470. }
  471. CPen penBorder( PS_SOLID, 0, clrBorder );
  472. CPen* oldBorderPen = dc.SelectObject( &penBorder );
  473. dc.Rectangle( &rect );
  474. m_rcDropButton.DeflateRect(0,1,0,1);
  475. m_rcDropButton.left -= 1;
  476. m_rcDropButton.right -= 1;
  477. if( !bWndEnabled )
  478. {
  479. COLORREF clrDisabledLightBorder;
  480. COLORREF clrDisabledFill;
  481. hr = g_xpStyle.GetThemeColor( hTheme, BP_PUSHBUTTON, bWndEnabled ? PBS_NORMAL : PBS_DISABLED, TMT_FILLCOLOR, &clrDisabledLightBorder );
  482. if( FAILED( hr ) )
  483. {
  484. clrDisabledLightBorder = RGB(255,255,255);
  485. }
  486. hr = g_xpStyle.GetThemeColor( hTheme, WP_DIALOG, 0, TMT_FILLCOLOR, &clrDisabledFill );
  487. if( FAILED( hr ) )
  488. {
  489. clrDisabledFill = RGB(255,0,0);
  490. }
  491. CPen penDisBorder( PS_SOLID, 0, clrDisabledLightBorder );
  492. CBrush brFill( clrDisabledBkg );//clrDisabledFill );
  493. CRect rcl = rect;
  494. rcl.DeflateRect(1,1);
  495. rcl.right = m_rcDropButton.left;
  496. CBrush *oldBr = dc.SelectObject( &brFill );
  497. dc.SelectObject( &penDisBorder );
  498. dc.Rectangle( &rcl );
  499. dc.SelectObject( oldBr );
  500. }
  501. dc.SelectObject( &oldBorderPen );
  502. // Button
  503. hr = g_xpStyle.DrawThemeBackground( hTheme, dc.m_hDC, CP_DROPDOWNBUTTON, nDropBtnThemeStyle, &m_rcDropButton, NULL);
  504. }
  505. else
  506. {
  507. COLORREF clrTopLeft = ::GetSysColor(COLOR_3DSHADOW);
  508. COLORREF clrBottomRight = ::GetSysColor(COLOR_3DHILIGHT);
  509. dc.Draw3dRect( &rect, clrTopLeft, clrBottomRight );
  510. clrTopLeft = ::GetSysColor(COLOR_3DDKSHADOW);
  511. clrBottomRight = ::GetSysColor(COLOR_3DLIGHT);
  512. rect.DeflateRect(1,1);
  513. dc.Draw3dRect( &rect, clrTopLeft, clrBottomRight );
  514. m_rcDropButton.DeflateRect(0,2,0,2);
  515. m_rcDropButton.left -= 2;
  516. m_rcDropButton.right -= 2;
  517. // Button
  518. dc.DrawFrameControl(m_rcDropButton, DFC_SCROLL, dwBtnStyle );
  519. }
  520. //
  521. // Adjust rects
  522. rcText.DeflateRect(4,3,2,3);
  523. }
  524. if( bThemeActive )
  525. hr = g_xpStyle.CloseThemeData( hTheme );
  526. if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
  527. {
  528. //
  529. // Draw Text as selected
  530. COLORREF clrBackground;
  531. COLORREF clrOldBkColor;
  532. COLORREF clrOldTextColor;
  533. clrBackground = ::GetSysColor(COLOR_HIGHLIGHT);
  534. clrOldBkColor = dc.SetBkColor( clrBackground );
  535. // clrOldTextColor = dc.SetTextColor( ::GetSysColor(COLOR_HIGHLIGHTTEXT) );
  536. int nOldBkMode = dc.SetBkMode( TRANSPARENT );
  537. CFont* pOldFont = dc.SelectObject( m_pFont );
  538. rcText.top -= 2;
  539. rcText.bottom += 2;
  540. rcText.left -= 2;
  541. rcText.right += 1;
  542. if( m_bHasFocus && !m_bDropListVisible )
  543. {
  544. dc.FillSolidRect( rcText, bWndEnabled ? clrBackground : clrDisabledBkg );
  545. clrOldTextColor = dc.SetTextColor(
  546. bWndEnabled ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) : clrDisabledText );
  547. dc.DrawText( m_strEdit.c_str(), &rcText, DT_SINGLELINE|DT_VCENTER);
  548. }
  549. else
  550. {
  551. //+++dc.FillSolidRect( rcText,
  552. //+++ bWndEnabled ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) : clrDisabledBkg );
  553. dc.FillSolidRect( rcText,
  554. bWndEnabled ? ::GetSysColor(COLOR_WINDOW) : clrDisabledBkg );
  555. clrOldTextColor = dc.SetTextColor(
  556. bWndEnabled ? ::GetSysColor(COLOR_BTNTEXT) : clrDisabledText );
  557. dc.DrawText( m_strEdit.c_str(), &rcText, DT_SINGLELINE|DT_VCENTER);
  558. }
  559. dc.SelectObject( pOldFont );
  560. dc.SetBkMode( nOldBkMode );
  561. }
  562. else
  563. {
  564. if( m_pEdit )
  565. {
  566. m_pEdit->SetFont( m_pFont );
  567. }
  568. }
  569. // Do not call CWnd::OnPaint() for painting messages
  570. }
  571. BOOL CAdvComboBox::OnEraseBkgnd(CDC* pDC)
  572. {
  573. return CWnd::OnEraseBkgnd(pDC);
  574. // return TRUE;
  575. }
  576. int CAdvComboBox::SetItemHeight(int nIndex, int nHeight)
  577. {
  578. if( nIndex == -1 )
  579. {
  580. if( nHeight < 10 || nHeight > 50 )
  581. {
  582. return CB_ERR;
  583. }
  584. else
  585. {
  586. //
  587. // Button rect
  588. GetClientRect(m_rcDropButton);
  589. m_rcDropButton.left = m_rcDropButton.right - ::GetSystemMetrics(SM_CXHSCROLL);
  590. return 0;
  591. }
  592. }
  593. return CB_ERR;
  594. }
  595. void CAdvComboBox::OnLButtonDown(UINT nFlags, CPoint point)
  596. {
  597. if( GetFocus() != this )
  598. {
  599. SetFocus();
  600. }
  601. //
  602. // Is mouse over drop button?
  603. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  604. {
  605. if( m_rcDropButton.PtInRect( point ) )
  606. {
  607. SendMessage( WM_ON_DROPDOWN_BUTTON );
  608. InvalidateRect( m_rcDropButton );
  609. Invalidate();
  610. }
  611. }
  612. else
  613. if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
  614. {
  615. CRect rc = m_rcCombo;
  616. GetClientRect( &rc );
  617. if( rc.PtInRect( point ) )
  618. {
  619. SendMessage( WM_ON_DROPDOWN_BUTTON );
  620. Invalidate();
  621. }
  622. }
  623. CWnd::OnLButtonDown(nFlags, point);
  624. }
  625. LONG CAdvComboBox::OnSelectedItem( WPARAM wParam, LPARAM /*lParam*/ )
  626. {
  627. list<LIST_ITEM> itemlist;
  628. list<LIST_ITEM>::iterator itemiter;
  629. int nPos = (int)wParam;
  630. itemlist = m_pDropWnd->GetList();
  631. itemiter = itemlist.begin();
  632. advance( itemiter, nPos );
  633. m_strEdit = itemiter->strText;
  634. m_nCurSel = FindStringExact( 0, m_strEdit.c_str() );
  635. SetWindowText( m_strEdit.c_str() );
  636. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  637. {
  638. if( m_pEdit )
  639. {
  640. m_pEdit->SetWindowText( m_strEdit.c_str() );
  641. m_pEdit->SetFocus();
  642. m_pEdit->SetSel( 0, -1, TRUE );
  643. }
  644. }
  645. // Send message to parent(dialog)
  646. m_bSelItem = true;
  647. int nId = GetDlgCtrlID();
  648. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
  649. Invalidate();
  650. OnDestroyDropdownList(0,0);
  651. //
  652. // See to it that the drop button is redrawn
  653. InvalidateRect( m_rcDropButton );
  654. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
  655. return TRUE;
  656. }
  657. LONG CAdvComboBox::OnDropdownButton( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  658. {
  659. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnDropdownButton\n"));
  660. //
  661. //
  662. if( !m_bDropListVisible )
  663. {
  664. //
  665. // Button is pressed
  666. //
  667. // Create list
  668. if( !m_pDropWnd )
  669. {
  670. CreateDropList( m_list );
  671. }
  672. m_pDropWnd->ShowWindow( SW_SHOW );
  673. m_bDropListVisible = TRUE;
  674. }
  675. else
  676. {
  677. OnDestroyDropdownList(0,0);
  678. }
  679. // Return TRUE if OK to go back, else return FALSE.
  680. return TRUE;
  681. }
  682. LONG CAdvComboBox::OnDestroyDropdownList( WPARAM /*wParam*/, LPARAM /*lParam*/ )
  683. {
  684. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnDestroyDropdownList\n"));
  685. //
  686. //
  687. if( m_pDropWnd )
  688. {
  689. m_pDropWnd->GetWindowRect( &m_rcDropWnd );
  690. m_bDropRectStored = true;
  691. m_pDropWnd->ShowWindow( SW_HIDE );
  692. m_bDropListVisible = FALSE;
  693. m_pDropWnd->DestroyWindow();
  694. delete m_pDropWnd;
  695. m_pDropWnd = NULL;
  696. InvalidateRect( &m_rcDropButton );
  697. int nId = GetDlgCtrlID();
  698. if( !m_bSelItem )
  699. {
  700. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDCANCEL),
  701. (LPARAM)m_hWnd );
  702. }
  703. else
  704. {
  705. m_bSelItem = false;
  706. }
  707. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_CLOSEUP), (LPARAM)m_hWnd );
  708. }
  709. else
  710. {
  711. OnComboComplete();
  712. }
  713. return TRUE;
  714. }
  715. void CAdvComboBox::CreateDropList( list<LIST_ITEM> &droplist)
  716. {
  717. XLISTCTRL_TRACE(_T("in CAdvComboBox::CreateDropList\n"));
  718. CRect rc;
  719. if( m_pDropWnd )
  720. ASSERT(0);
  721. m_pDropWnd = new CDropWnd( this, droplist, m_dwACBStyle );
  722. GetWindowRect( &rc );
  723. rc.top = rc.bottom ;
  724. //
  725. // Get screen size
  726. CRect rcWorkArea;
  727. SystemParametersInfo( SPI_GETWORKAREA, 0, (LPRECT)rcWorkArea, 0) ;
  728. if( rc.bottom >= rcWorkArea.bottom )
  729. {
  730. rc.bottom = rcWorkArea.bottom;
  731. }
  732. else
  733. {
  734. }
  735. int nStyle = WS_CHILD|/*WS_BORDER|*/LBS_DISABLENOSCROLL|LBS_NOTIFY;
  736. m_pDropWnd->Create( 0, 0, nStyle , rc, 1 ? GetDesktopWindow() : this, 6 );
  737. //+++
  738. if (m_nCurSel > ((int)droplist.size() - 1))
  739. m_nCurSel = 0;
  740. m_pDropWnd->GetListBoxPtr()->SetCurSel( m_nCurSel );
  741. m_pDropWnd->SetFont( m_pFont );
  742. // Send message to parent(dialog)
  743. int nId = GetDlgCtrlID();
  744. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_DROPDOWN), (LPARAM)m_hWnd );
  745. }
  746. int CAdvComboBox::GetLBText(int nIndex, LPTSTR lpszText)
  747. {
  748. m_iter = m_list.begin();
  749. advance( m_iter, nIndex );
  750. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  751. {
  752. return CB_ERR;
  753. }
  754. _tcscpy( lpszText, m_iter->strText.c_str() );
  755. return m_iter->strText.length()+1;
  756. }
  757. void CAdvComboBox::GetLBText(int nIndex, CString &rString)
  758. {
  759. m_iter = m_list.begin();
  760. advance( m_iter, nIndex );
  761. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  762. {
  763. rString = "";
  764. return;
  765. }
  766. rString = m_iter->strText.c_str();
  767. }
  768. int CAdvComboBox::GetLBTextLen(int nIndex )
  769. {
  770. m_iter = m_list.begin();
  771. advance( m_iter, nIndex );
  772. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  773. {
  774. return CB_ERR;
  775. }
  776. return m_iter->strText.length()+1;
  777. }
  778. int CAdvComboBox::AddString(LPCTSTR lpszString) //+++
  779. {
  780. LIST_ITEM item;
  781. item.strText = lpszString;
  782. item.bChecked = false;
  783. item.bDisabled = false;
  784. item.vpItemData = NULL;
  785. m_list.push_back( item );
  786. // this takes too long -
  787. // sorting is handled in CXListCtrl::SetComboBox()
  788. //if( GetStyle() & CBS_SORT )
  789. //{
  790. // m_list.sort();
  791. // Find new item
  792. // return FindString( -1, item.strText.c_str() );
  793. //}
  794. //else
  795. return m_list.size()-1;
  796. }
  797. int CAdvComboBox::GetText(LPTSTR lpszText)
  798. {
  799. if( m_pEdit )
  800. {
  801. CString str;
  802. m_pEdit->GetWindowText( str );
  803. _tcscpy( lpszText, (LPCTSTR)str );
  804. return str.GetLength();
  805. }
  806. else
  807. {
  808. _tcscpy( lpszText, m_strEdit.c_str() );
  809. return m_strEdit.length();
  810. }
  811. }
  812. void CAdvComboBox::GetText(CString &rString)
  813. {
  814. if( m_pEdit )
  815. {
  816. m_pEdit->GetWindowText( rString );
  817. }
  818. else
  819. {
  820. rString = m_strEdit.c_str();
  821. }
  822. }
  823. void CAdvComboBox::SetText(LPCTSTR lpszText)
  824. {
  825. if( m_pEdit )
  826. {
  827. m_pEdit->SetWindowText( lpszText );
  828. }
  829. m_strEdit = lpszText;
  830. }
  831. BOOL CAdvComboBox::PointInWindow(CPoint ptScreenPoint)
  832. {
  833. CRect rc;
  834. GetWindowRect( &rc );
  835. return rc.PtInRect( ptScreenPoint );
  836. }
  837. BOOL CAdvComboBox::OnMouseWheel(UINT /*nFlags*/, short zDelta, CPoint /*pt*/)
  838. {
  839. // TODO: Add your message handler code here and/or call default
  840. if( !m_bDropListVisible )
  841. {
  842. string str;
  843. //
  844. // Select another string from the map
  845. m_zDelta += zDelta;
  846. if( m_zDelta >= WHEEL_DELTA )
  847. {
  848. //
  849. // Select item upwards
  850. m_zDelta = 0;
  851. SelPrevItem();
  852. }
  853. else
  854. if( m_zDelta <= -WHEEL_DELTA )
  855. {
  856. //
  857. // Select item downwards
  858. m_zDelta = 0;
  859. SelNextItem();
  860. }
  861. }
  862. else
  863. {
  864. //
  865. // Handle mousewheel for the droplist here
  866. //
  867. // Select another string from the map
  868. m_zDelta += zDelta;
  869. if( m_zDelta >= WHEEL_DELTA )
  870. {
  871. //
  872. // Scroll list upwards
  873. m_zDelta = 0;
  874. int nTop = m_pDropWnd->GetListBoxPtr()->GetTopIndex();
  875. nTop -= 3;
  876. nTop = nTop < 0 ? 0 : nTop;
  877. m_pDropWnd->GetListBoxPtr()->SetTopIdx( nTop, TRUE );
  878. }
  879. else
  880. if( m_zDelta <= -WHEEL_DELTA )
  881. {
  882. //
  883. // Scroll list downwards
  884. m_zDelta = 0;
  885. int nTop = m_pDropWnd->GetListBoxPtr()->GetTopIndex();
  886. nTop += 3;
  887. nTop = nTop > m_pDropWnd->GetListBoxPtr()->GetCount() ?
  888. m_pDropWnd->GetListBoxPtr()->GetCount() : nTop;
  889. m_pDropWnd->GetListBoxPtr()->SetTopIdx( nTop, TRUE );
  890. }
  891. }
  892. return TRUE;
  893. // return CWnd::OnMouseWheel(nFlags, zDelta, pt);
  894. }
  895. void CAdvComboBox::OnSize(UINT nType, int cx, int cy)
  896. {
  897. CWnd::OnSize(nType, cx, cy);
  898. //
  899. // Move Dropdown?
  900. }
  901. void CAdvComboBox::OnSetFocus(CWnd* pOldWnd)
  902. {
  903. CWnd::OnSetFocus(pOldWnd);
  904. // TODO: Add your message handler code here
  905. m_bHasFocus = true;
  906. Invalidate();
  907. //
  908. // Set focus to the edit control? (CBS_DROPDOWN)
  909. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  910. {
  911. if( m_pEdit )
  912. {
  913. m_pEdit->SetFocus();
  914. }
  915. }
  916. BOOL bDropdownList = (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE);
  917. if( bDropdownList )
  918. {
  919. // Send message to parent(dialog)
  920. int nId = GetDlgCtrlID();
  921. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SETFOCUS), (LPARAM)m_hWnd );
  922. }
  923. }
  924. void CAdvComboBox::OnSetfocusEdit()
  925. {
  926. m_bHasFocus = false;
  927. //CWnd* pWnd = GetFocus();
  928. //+++
  929. if (m_pEdit)
  930. {
  931. m_pEdit->PostMessage(EM_SETSEL, 0, -1);
  932. }
  933. if( !m_bHasSentFocus )
  934. {
  935. // Send message to parent(dialog)
  936. int nId = GetDlgCtrlID();
  937. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SETFOCUS), (LPARAM)m_hWnd );
  938. m_bHasSentFocus = true;
  939. }
  940. }
  941. void CAdvComboBox::OnKillFocus(CWnd* pNewWnd)
  942. {
  943. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnKillFocus\n"));
  944. CWnd::OnKillFocus(pNewWnd);
  945. OnEscapeKey();
  946. //+++
  947. #if 0 // -----------------------------------------------------------
  948. // Needed for keydown's like 'Alt-C'("&Cancel" button)
  949. if( m_pDropWnd )
  950. {
  951. OnDestroyDropdownList(0,0);
  952. //}
  953. m_bHasFocus = false;
  954. Invalidate();
  955. BOOL bDropdownList = (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE);
  956. if( bDropdownList && !m_pDropWnd )
  957. {
  958. // Send message to parent(dialog)
  959. int nId = GetDlgCtrlID();
  960. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDCANCEL), (LPARAM)m_hWnd );
  961. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_KILLFOCUS), (LPARAM)m_hWnd );
  962. }
  963. }
  964. else
  965. {
  966. OnEscapeKey();
  967. }
  968. #endif // -----------------------------------------------------------
  969. }
  970. void CAdvComboBox::OnKillfocusEdit()
  971. {
  972. m_bHasFocus = false;
  973. Invalidate();
  974. CWnd* pWnd = GetFocus();
  975. if( !m_pDropWnd && pWnd != this )
  976. {
  977. // Send message to parent(dialog)
  978. int nId = GetDlgCtrlID();
  979. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDCANCEL), (LPARAM)m_hWnd );
  980. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_KILLFOCUS), (LPARAM)m_hWnd );
  981. m_bHasSentFocus = false;
  982. m_pEdit->SetSel(0,0);
  983. }
  984. //+++
  985. if (m_pDropWnd)
  986. {
  987. OnDestroyDropdownList(0,0);
  988. }
  989. }
  990. void CAdvComboBox::OnShowWindow(BOOL bShow, UINT nStatus)
  991. {
  992. CWnd::OnShowWindow(bShow, nStatus);
  993. }
  994. void CAdvComboBox::ModifyACBStyle(UINT nRemoveStyle, UINT nAddStyle)
  995. {
  996. if( nAddStyle & ACBS_FLAT )
  997. {
  998. nRemoveStyle |= ACBS_STANDARD;
  999. }
  1000. else
  1001. if( nAddStyle & ACBS_STANDARD )
  1002. {
  1003. nRemoveStyle |= ACBS_FLAT;
  1004. }
  1005. m_dwACBStyle &= ~nRemoveStyle;
  1006. m_dwACBStyle |= nAddStyle;
  1007. Invalidate();
  1008. }
  1009. int CAdvComboBox::GetCount()
  1010. {
  1011. return m_list.size();
  1012. }
  1013. int CAdvComboBox::GetCurSel()
  1014. {
  1015. CString str;
  1016. GetText( str );
  1017. return FindStringExact( -1, str );
  1018. }
  1019. int CAdvComboBox::SetCurSel(int nSelect)
  1020. {
  1021. if( nSelect == -1 )
  1022. {
  1023. m_nCurSel = nSelect;
  1024. m_strEdit = _T("");
  1025. Invalidate();
  1026. return CB_ERR;
  1027. }
  1028. else
  1029. if( m_list.size() == 0 )
  1030. {
  1031. m_nCurSel = nSelect;
  1032. return CB_ERR;
  1033. }
  1034. else
  1035. if( nSelect < -1 || nSelect > (int)m_list.size()-1 )
  1036. {
  1037. return CB_ERR;
  1038. }
  1039. else
  1040. {
  1041. m_nCurSel = nSelect;
  1042. m_iter = m_list.begin();
  1043. advance( m_iter, nSelect );
  1044. m_strEdit = m_iter->strText;
  1045. Invalidate();
  1046. return m_nCurSel;
  1047. }
  1048. }
  1049. int CAdvComboBox::FindString(int nStartAfter, LPCTSTR lpszString)
  1050. {
  1051. int nPos = 0;
  1052. m_iter = m_list.begin();
  1053. if( nStartAfter != -1 )
  1054. {
  1055. advance( m_iter, nStartAfter );
  1056. nPos = nStartAfter;
  1057. }
  1058. for( m_iter; m_iter != m_list.end(); ++m_iter )
  1059. {
  1060. if( _tcsncmp( m_iter->strText.c_str(), lpszString, _tcslen(lpszString) ) == 0 )
  1061. {
  1062. return nPos;
  1063. }
  1064. nPos++;
  1065. }
  1066. return CB_ERR;
  1067. }
  1068. int CAdvComboBox::FindStringExact(int nIndexStart, LPCTSTR lpszFind)
  1069. {
  1070. TRACE(_T("in CAdvComboBox::FindStringExact: nIndexStart=%d\n"), nIndexStart);
  1071. if( nIndexStart > (int)m_list.size() && nIndexStart != -1 )
  1072. return CB_ERR;
  1073. int nPos = 0;
  1074. m_iter = m_list.begin();
  1075. if( nIndexStart != -1 )
  1076. {
  1077. advance( m_iter, nIndexStart );
  1078. nPos = nIndexStart;
  1079. }
  1080. for( m_iter; m_iter != m_list.end(); ++m_iter )
  1081. {
  1082. if( _tcscmp( m_iter->strText.c_str(), lpszFind ) == 0 )
  1083. {
  1084. XLISTCTRL_TRACE(_T("CAdvComboBox::FindStringExact returning %d\n"), nPos);
  1085. return nPos;
  1086. }
  1087. nPos++;
  1088. }
  1089. return CB_ERR;
  1090. }
  1091. int CAdvComboBox::SelectString(int nStartAfter, LPCTSTR lpszString)
  1092. {
  1093. if( nStartAfter > (int)m_list.size() )
  1094. return CB_ERR;
  1095. int nPos = 0;
  1096. m_iter = m_list.begin();
  1097. if( nStartAfter != -1 )
  1098. {
  1099. advance( m_iter, nStartAfter );
  1100. nPos = nStartAfter;
  1101. }
  1102. for( m_iter; m_iter != m_list.end(); ++m_iter )
  1103. {
  1104. if( _tcscmp( m_iter->strText.c_str(), lpszString ) == 0 )
  1105. {
  1106. m_nCurSel = nPos;
  1107. m_strEdit = m_iter->strText;
  1108. Invalidate();
  1109. return nPos;
  1110. }
  1111. nPos++;
  1112. }
  1113. return CB_ERR;
  1114. }
  1115. int CAdvComboBox::SetItemData(int nIndex, DWORD dwItemData)
  1116. {
  1117. m_iter = m_list.begin();
  1118. advance( m_iter, nIndex );
  1119. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  1120. {
  1121. return CB_ERR;
  1122. }
  1123. m_iter->vpItemData = (void*)dwItemData;
  1124. return CB_OKAY;
  1125. }
  1126. DWORD CAdvComboBox::GetItemData(int nIndex)
  1127. {
  1128. m_iter = m_list.begin();
  1129. advance( m_iter, nIndex );
  1130. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  1131. {
  1132. return (DWORD)CB_ERR;
  1133. }
  1134. return (DWORD)m_iter->vpItemData;
  1135. }
  1136. int CAdvComboBox::SetItemDataPtr(int nIndex, void *pData)
  1137. {
  1138. m_iter = m_list.begin();
  1139. advance( m_iter, nIndex );
  1140. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  1141. {
  1142. return (DWORD)CB_ERR;
  1143. }
  1144. m_iter->vpItemData = pData;
  1145. return CB_OKAY;
  1146. }
  1147. void* CAdvComboBox::GetItemDataPtr(int nIndex)
  1148. {
  1149. m_iter = m_list.begin();
  1150. advance( m_iter, nIndex );
  1151. if( m_iter == m_list.end() || nIndex > (int)m_list.size() )
  1152. {
  1153. return (void*)CB_ERR;
  1154. }
  1155. return m_iter->vpItemData;
  1156. }
  1157. void CAdvComboBox::ResetContent()
  1158. {
  1159. m_list.clear();
  1160. m_strEdit = _T("");
  1161. Invalidate();
  1162. }
  1163. void AFXAPI DDX_ACBIndex( CDataExchange* pDX, int nIDC, int& index )
  1164. {
  1165. /*HWND hWnd =*/ pDX->PrepareCtrl( nIDC );
  1166. if( pDX->m_bSaveAndValidate )
  1167. {
  1168. CAdvComboBox* pACB = (CAdvComboBox*)pDX->m_pDlgWnd->GetDlgItem( nIDC );
  1169. index = pACB->GetCurSel();
  1170. }
  1171. else
  1172. {
  1173. CAdvComboBox* pACB = (CAdvComboBox*)pDX->m_pDlgWnd->GetDlgItem( nIDC );
  1174. pACB->SetCurSel( index );
  1175. }
  1176. }
  1177. void AFXAPI DDX_ACBString( CDataExchange* pDX, int nIDC, CString& value )
  1178. {
  1179. /*HWND hWnd =*/ pDX->PrepareCtrl( nIDC );
  1180. if( pDX->m_bSaveAndValidate )
  1181. {
  1182. CAdvComboBox* pACB = (CAdvComboBox*)pDX->m_pDlgWnd->GetDlgItem( nIDC );
  1183. pACB->GetText( value );
  1184. }
  1185. else
  1186. {
  1187. CAdvComboBox* pACB = (CAdvComboBox*)pDX->m_pDlgWnd->GetDlgItem( nIDC );
  1188. pACB->SetText( value );
  1189. }
  1190. }
  1191. BOOL CAdvComboBox::GetItemDisabled( int nIndex )
  1192. {
  1193. if( nIndex > (int)m_list.size() )
  1194. return CB_ERR;
  1195. m_iter = m_list.begin();
  1196. advance( m_iter, nIndex );
  1197. return m_iter->bDisabled;
  1198. }
  1199. void CAdvComboBox::SetItemDisabled(int nIndex, BOOL bDisabled)
  1200. {
  1201. if( nIndex > (int)m_list.size() )
  1202. return;
  1203. m_iter = m_list.begin();
  1204. advance( m_iter, nIndex );
  1205. m_iter->bDisabled = bDisabled;
  1206. }
  1207. BOOL CAdvComboBox::GetItemChecked( int nIndex )
  1208. {
  1209. if( nIndex > (int)m_list.size() )
  1210. return CB_ERR;
  1211. m_iter = m_list.begin();
  1212. advance( m_iter, nIndex );
  1213. return m_iter->bChecked;
  1214. }
  1215. void CAdvComboBox::SetItemChecked(int nIndex, BOOL bChecked)
  1216. {
  1217. if( nIndex > (int)m_list.size() )
  1218. return;
  1219. m_iter = m_list.begin();
  1220. advance( m_iter, nIndex );
  1221. m_iter->bChecked = bChecked;
  1222. }
  1223. BOOL CAdvComboBox::PreTranslateMessage(MSG* pMsg)
  1224. {
  1225. if( pMsg->message == WM_KEYDOWN )
  1226. {
  1227. m_bAutoAppend = TRUE;
  1228. XLISTCTRL_TRACE(_T("CAdvComboBox: Key was pressed(AdvComboBox)\n"));
  1229. if( pMsg->wParam == VK_RETURN )
  1230. {
  1231. XLISTCTRL_TRACE(_T("CAdvComboBox: VK_RETURN\n"));
  1232. if( m_pDropWnd )
  1233. {
  1234. int nPos = m_pDropWnd->GetListBoxPtr()->GetCurSel();
  1235. if (nPos != LB_ERR) //+++
  1236. SendMessage( WM_SELECTED_ITEM, (WPARAM)nPos );
  1237. //else //+++
  1238. OnDestroyDropdownList(0,0); //+++
  1239. }
  1240. else
  1241. {
  1242. return CWnd::PreTranslateMessage(pMsg);
  1243. }
  1244. }
  1245. else
  1246. if( pMsg->wParam == VK_ESCAPE )
  1247. {
  1248. XLISTCTRL_TRACE(_T("CAdvComboBox: VK_ESCAPE\n"));
  1249. if( m_pDropWnd )
  1250. {
  1251. OnDestroyDropdownList(0,0);
  1252. Invalidate();
  1253. }
  1254. else //+++
  1255. {
  1256. OnEscapeKey();
  1257. return CWnd::PreTranslateMessage(pMsg);
  1258. }
  1259. }
  1260. else
  1261. if( pMsg->wParam == VK_F4 )
  1262. {
  1263. SendMessage( WM_ON_DROPDOWN_BUTTON );
  1264. Invalidate();
  1265. }
  1266. else
  1267. if( pMsg->wParam == VK_UP )
  1268. {
  1269. SelPrevItem();
  1270. }
  1271. else
  1272. if( pMsg->wParam == VK_DOWN )
  1273. {
  1274. SelNextItem();
  1275. }
  1276. else
  1277. if( pMsg->wParam == VK_PRIOR ) //+++
  1278. {
  1279. SelPrevPage();
  1280. }
  1281. else
  1282. if( pMsg->wParam == VK_NEXT ) //+++
  1283. {
  1284. SelNextPage();
  1285. }
  1286. else
  1287. if( pMsg->wParam == VK_DELETE || pMsg->wParam == VK_BACK )
  1288. {
  1289. m_bAutoAppend = FALSE;
  1290. return CWnd::PreTranslateMessage(pMsg);
  1291. }
  1292. else
  1293. if( pMsg->wParam == VK_RIGHT )
  1294. {
  1295. if( m_dwACBStyle & ACBS_AUTOAPPEND )
  1296. {
  1297. // If the cursor is at the end of the text, show autosuggest text
  1298. if( m_pEdit )
  1299. {
  1300. int nS, nE;
  1301. m_pEdit->GetSel( nS, nE );
  1302. if( nS == nE && nS == m_pEdit->LineLength() )
  1303. {
  1304. OnUpdateEdit();
  1305. }
  1306. else
  1307. {
  1308. return CWnd::PreTranslateMessage(pMsg);
  1309. }
  1310. }
  1311. }
  1312. else
  1313. {
  1314. return CWnd::PreTranslateMessage(pMsg);
  1315. }
  1316. }
  1317. else
  1318. {
  1319. return CWnd::PreTranslateMessage(pMsg);
  1320. }
  1321. return TRUE;
  1322. }
  1323. else
  1324. if( pMsg->message == WM_SYSKEYDOWN )
  1325. {
  1326. if( pMsg->wParam == VK_DOWN ||
  1327. pMsg->wParam == VK_UP )
  1328. {
  1329. SendMessage( WM_ON_DROPDOWN_BUTTON );
  1330. Invalidate();
  1331. }
  1332. }
  1333. return CWnd::PreTranslateMessage(pMsg);
  1334. }
  1335. void CAdvComboBox::SelPrevItem()
  1336. {
  1337. if( m_pDropWnd )
  1338. {
  1339. int nPos = m_pDropWnd->GetListBoxPtr()->GetCurSel();
  1340. if( nPos > 0 )
  1341. {
  1342. m_pDropWnd->GetListBoxPtr()->SetCurSel( --nPos );
  1343. }
  1344. }
  1345. else
  1346. {
  1347. m_iter = m_list.begin();
  1348. advance( m_iter, m_nCurSel );
  1349. --m_iter;
  1350. int nOldSel = m_nCurSel;
  1351. int nPos = m_nCurSel;
  1352. while( m_iter != m_list.end() )
  1353. {
  1354. nPos--;
  1355. if( !m_iter->bDisabled )
  1356. {
  1357. m_strEdit = m_iter->strText;
  1358. if( m_pEdit )
  1359. m_pEdit->SetWindowText( m_strEdit.c_str() );
  1360. m_nCurSel = nPos;
  1361. Invalidate();
  1362. break;
  1363. }
  1364. --m_iter;
  1365. }
  1366. if( nOldSel != m_nCurSel )
  1367. {
  1368. // Send message to parent(dialog)
  1369. int nId = GetDlgCtrlID();
  1370. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
  1371. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
  1372. }
  1373. }
  1374. }
  1375. void CAdvComboBox::SelNextItem()
  1376. {
  1377. if( m_pDropWnd )
  1378. {
  1379. int nPos = m_pDropWnd->GetListBoxPtr()->GetCurSel();
  1380. if( nPos < m_pDropWnd->GetListBoxPtr()->GetCount() )
  1381. {
  1382. m_pDropWnd->GetListBoxPtr()->SetCurSel( ++nPos );
  1383. }
  1384. }
  1385. else
  1386. {
  1387. m_iter = m_list.begin();
  1388. advance( m_iter, m_nCurSel );
  1389. ++m_iter;
  1390. int nOldSel = m_nCurSel;
  1391. int nPos = m_nCurSel;
  1392. while( m_iter != m_list.end() )
  1393. {
  1394. nPos++;
  1395. if( !m_iter->bDisabled )
  1396. {
  1397. m_strEdit = m_iter->strText;
  1398. if( m_pEdit )
  1399. m_pEdit->SetWindowText( m_strEdit.c_str() );
  1400. Invalidate();
  1401. m_nCurSel = nPos;
  1402. break;
  1403. }
  1404. ++m_iter;
  1405. }
  1406. if( nOldSel != m_nCurSel )
  1407. {
  1408. // Send message to parent(dialog)
  1409. int nId = GetDlgCtrlID();
  1410. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
  1411. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
  1412. }
  1413. }
  1414. }
  1415. //+++
  1416. void CAdvComboBox::SelNextPage()
  1417. {
  1418. XLISTCTRL_TRACE(_T("in CAdvComboBox::SelNextPage\n"));
  1419. if (m_pDropWnd)
  1420. {
  1421. CDropListBox * pListBox = m_pDropWnd->GetListBoxPtr();
  1422. ASSERT(pListBox);
  1423. int nPos = pListBox->GetCurSel();
  1424. int nCount = pListBox->GetCount();
  1425. int nMaxVisible = pListBox->GetMaxVisibleItems();
  1426. int nTop = pListBox->GetTopIndex();
  1427. if (nPos == LB_ERR) // no selection
  1428. nPos = 0;
  1429. else if (nPos == (nCount - 1)) // end of list
  1430. /*nPos = -1*/;
  1431. else if (nPos < (nTop + nMaxVisible - 1)) // middle of listbox window
  1432. nPos = nTop + nMaxVisible - 1;
  1433. else // at end of listbox window
  1434. nPos = nTop + nMaxVisible + nMaxVisible - 2;
  1435. if (nPos >= nCount) // moved past end, reset
  1436. nPos = nCount - 1;
  1437. pListBox->SetCurSel(nPos);
  1438. int nSel = pListBox->GetCurSel();
  1439. if (nSel == LB_ERR)
  1440. {
  1441. }
  1442. else
  1443. {
  1444. CString str = _T("");
  1445. pListBox->GetText(nSel, str);
  1446. SetWindowText(str);
  1447. }
  1448. }
  1449. else
  1450. {
  1451. // combo list not dropped
  1452. int nSize = m_list.size();
  1453. m_iter = m_list.begin();
  1454. if (m_nCurSel < 0 || m_nCurSel >= nSize)
  1455. m_nCurSel = 0;
  1456. advance(m_iter, m_nCurSel);
  1457. int nOldSel = m_nCurSel;
  1458. int nPos = m_nCurSel;
  1459. // Page Down goes forward by 10
  1460. for (int i = 0; i < 10; i++)
  1461. {
  1462. if (nPos >= (nSize-1))
  1463. {
  1464. nPos = nSize - 1;
  1465. break;
  1466. }
  1467. nPos++;
  1468. m_iter++;
  1469. }
  1470. if (nOldSel != nPos)
  1471. {
  1472. m_strEdit = m_iter->strText;
  1473. if (m_pEdit)
  1474. m_pEdit->SetWindowText(m_strEdit.c_str());
  1475. Invalidate();
  1476. m_nCurSel = nPos;
  1477. // Send message to parent(dialog)
  1478. int nId = GetDlgCtrlID();
  1479. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
  1480. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
  1481. }
  1482. }
  1483. }
  1484. //+++
  1485. void CAdvComboBox::SelPrevPage()
  1486. {
  1487. if (m_pDropWnd)
  1488. {
  1489. CDropListBox * pListBox = m_pDropWnd->GetListBoxPtr();
  1490. ASSERT(pListBox);
  1491. int nPos = pListBox->GetCurSel();
  1492. int nCount = pListBox->GetCount();
  1493. int nMaxVisible = pListBox->GetMaxVisibleItems();
  1494. int nTop = pListBox->GetTopIndex();
  1495. if (nPos <= 0)
  1496. return;
  1497. if (nPos == LB_ERR) // no selection
  1498. nPos = nCount - 1;
  1499. else if (nPos == 0) // top of list
  1500. /*nPos = -1*/;
  1501. else if (nPos == nTop) // at top of listbox window
  1502. {
  1503. nPos = nTop - nMaxVisible + 1; // this might be = -1
  1504. if (nPos < 0)
  1505. nPos = 0;
  1506. }
  1507. else // middle of listbox window
  1508. nPos = nTop;
  1509. pListBox->SetCurSel(nPos);
  1510. int nSel = pListBox->GetCurSel();
  1511. if (nSel == LB_ERR)
  1512. {
  1513. }
  1514. else
  1515. {
  1516. CString str = _T("");
  1517. pListBox->GetText(nSel, str);
  1518. SetWindowText(str);
  1519. }
  1520. }
  1521. else
  1522. {
  1523. // combo list not dropped
  1524. int nSize = m_list.size();
  1525. m_iter = m_list.begin();
  1526. if (m_nCurSel < 0 || m_nCurSel >= nSize)
  1527. m_nCurSel = 0;
  1528. advance(m_iter, m_nCurSel);
  1529. int nOldSel = m_nCurSel;
  1530. int nPos = m_nCurSel;
  1531. // Page Up goes back by 10
  1532. for (int i = 0; i < 10; i++)
  1533. {
  1534. if (nPos <= 0)
  1535. {
  1536. nPos = 0;
  1537. break;
  1538. }
  1539. nPos--;
  1540. m_iter--;
  1541. }
  1542. if (nOldSel != nPos)
  1543. {
  1544. m_strEdit = m_iter->strText;
  1545. if (m_pEdit)
  1546. m_pEdit->SetWindowText(m_strEdit.c_str());
  1547. Invalidate();
  1548. m_nCurSel = nPos;
  1549. // Send message to parent(dialog)
  1550. int nId = GetDlgCtrlID();
  1551. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELENDOK), (LPARAM)m_hWnd );
  1552. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_SELCHANGE), (LPARAM)m_hWnd );
  1553. }
  1554. }
  1555. }
  1556. int CAdvComboBox::GetTopIndex()
  1557. {
  1558. if( m_bDropListVisible )
  1559. {
  1560. if( m_pDropWnd )
  1561. {
  1562. return m_pDropWnd->GetListBoxPtr()->GetTopIndex();
  1563. }
  1564. }
  1565. return CB_ERR;
  1566. }
  1567. int CAdvComboBox::SetTopIndex(int nIndex)
  1568. {
  1569. if( m_bDropListVisible )
  1570. {
  1571. if( m_pDropWnd )
  1572. {
  1573. return m_pDropWnd->GetListBoxPtr()->SetTopIndex(nIndex);
  1574. }
  1575. }
  1576. return CB_ERR;
  1577. }
  1578. //
  1579. // Will not allocate anything. I can't see the need in doing that.
  1580. // Everything is stored in a STL list.
  1581. int CAdvComboBox::InitStorage(int nItems, UINT /*nBytes*/)
  1582. {
  1583. return nItems;
  1584. }
  1585. void CAdvComboBox::ShowDropDown(BOOL bShowIt)
  1586. {
  1587. if( bShowIt )
  1588. {
  1589. if( !m_bDropListVisible )
  1590. {
  1591. SendMessage( WM_ON_DROPDOWN_BUTTON );
  1592. Invalidate();
  1593. }
  1594. }
  1595. else
  1596. {
  1597. if( m_bDropListVisible )
  1598. {
  1599. SendMessage( WM_DESTROY_DROPLIST );
  1600. Invalidate();
  1601. }
  1602. }
  1603. }
  1604. void CAdvComboBox::GetDroppedControlRect(LPRECT lprect)
  1605. {
  1606. if( m_bDropListVisible )
  1607. {
  1608. m_pDropWnd->GetWindowRect( lprect );
  1609. }
  1610. }
  1611. BOOL CAdvComboBox::GetDroppedState()
  1612. {
  1613. return m_bDropListVisible;
  1614. }
  1615. int CAdvComboBox::SetExtendedUI(BOOL /*bExtended*/)
  1616. {
  1617. return CB_OKAY;
  1618. }
  1619. BOOL CAdvComboBox::GetExtendedUI()
  1620. {
  1621. return FALSE;
  1622. }
  1623. int CAdvComboBox::DeleteString(UINT nIndex)
  1624. {
  1625. m_iter = m_list.begin();
  1626. advance( m_iter, nIndex );
  1627. if( m_iter != m_list.end() || nIndex > m_list.size() )
  1628. {
  1629. m_list.erase( m_iter );
  1630. return m_list.size();
  1631. }
  1632. else
  1633. {
  1634. return CB_ERR;
  1635. }
  1636. }
  1637. int CAdvComboBox::InsertString(int nIndex, LPCTSTR lpszString)
  1638. {
  1639. LIST_ITEM item;
  1640. item.strText = lpszString;
  1641. if( nIndex == -1 || (nIndex > (int)m_list.size()) )
  1642. {
  1643. m_list.push_back( item );
  1644. return m_list.size()-1;
  1645. }
  1646. if( nIndex == 0 && (m_list.size()==0) )
  1647. {
  1648. m_list.push_back( item );
  1649. return 0;
  1650. }
  1651. m_iter = m_list.begin();
  1652. advance( m_iter, nIndex );
  1653. if( m_iter != m_list.end() )
  1654. {
  1655. m_iter = m_list.insert( m_iter, item );
  1656. int nPos = 0;
  1657. while( m_iter != m_list.begin() )
  1658. {
  1659. nPos++;
  1660. --m_iter;
  1661. }
  1662. if( nIndex <= m_nCurSel )
  1663. {
  1664. m_nCurSel++;
  1665. }
  1666. return nPos;
  1667. }
  1668. return CB_ERR;
  1669. }
  1670. DWORD CAdvComboBox::GetEditSel()
  1671. {
  1672. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  1673. {
  1674. if( m_pEdit )
  1675. {
  1676. return m_pEdit->GetSel();
  1677. }
  1678. }
  1679. return (DWORD)CB_ERR;
  1680. }
  1681. BOOL CAdvComboBox::SetEditSel(int nStartChar, int nEndChar)
  1682. {
  1683. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  1684. {
  1685. if( m_pEdit )
  1686. {
  1687. m_pEdit->SetSel( nStartChar, nEndChar, TRUE );
  1688. return TRUE;
  1689. }
  1690. }
  1691. return CB_ERR;
  1692. }
  1693. void CAdvComboBox::OnChangeEdit()
  1694. {
  1695. if( !m_pDropWnd )
  1696. {
  1697. // Send message to parent(dialog)
  1698. int nId = GetDlgCtrlID();
  1699. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_EDITCHANGE), (LPARAM)m_hWnd );
  1700. }
  1701. }
  1702. void CAdvComboBox::OnUpdateEdit()
  1703. {
  1704. static bool bAutoAppendInProgress;
  1705. CString strEdit;
  1706. m_pEdit->GetWindowText( strEdit );
  1707. if( GetFocus() == m_pEdit )
  1708. {
  1709. if( !bAutoAppendInProgress )
  1710. {
  1711. // m_nCurSel = -1;
  1712. if( m_dwACBStyle & ACBS_AUTOAPPEND && m_bAutoAppend )
  1713. {
  1714. tstring str = (LPCTSTR)strEdit;
  1715. int nEditLen = str.length();
  1716. if( !nEditLen )
  1717. return;
  1718. int nStartSel;
  1719. int nEndSel;
  1720. m_pEdit->GetSel( nStartSel, nEndSel );
  1721. LIST_ITEM item;
  1722. m_iter = m_list.begin();
  1723. while( m_iter != m_list.end() )
  1724. {
  1725. item = *m_iter;
  1726. int nPos = m_iter->strText.find( str, 0 );
  1727. if( nPos == 0 )
  1728. {
  1729. bAutoAppendInProgress = true;
  1730. m_pEdit->SetWindowText( m_iter->strText.c_str() );
  1731. m_pEdit->SetSel( nEditLen, m_iter->strText.length(), TRUE );
  1732. bAutoAppendInProgress = false;
  1733. break;
  1734. }
  1735. ++m_iter;
  1736. }
  1737. }
  1738. }
  1739. if( !bAutoAppendInProgress )
  1740. {
  1741. if( m_dwACBStyle & ACBS_AUTOSUGGEST )
  1742. {
  1743. list<LIST_ITEM> suggestlist;
  1744. list<LIST_ITEM>::iterator suggestiter;
  1745. tstring str = (LPCTSTR)strEdit;
  1746. int nEditLen = str.length();
  1747. if( !nEditLen )
  1748. {
  1749. if( m_pDropWnd )
  1750. SendMessage( WM_DESTROY_DROPLIST );
  1751. return;
  1752. }
  1753. int nStartSel;
  1754. int nEndSel;
  1755. m_pEdit->GetSel( nStartSel, nEndSel );
  1756. LIST_ITEM item;
  1757. m_iter = m_list.begin();
  1758. while( m_iter != m_list.end() )
  1759. {
  1760. item = *m_iter;
  1761. int nPos = m_iter->strText.find( str, 0 );
  1762. if( nPos == 0 )
  1763. {
  1764. if (m_iter->strText != str) //+++
  1765. suggestlist.push_back( item );
  1766. }
  1767. ++m_iter;
  1768. }
  1769. if( m_pDropWnd )
  1770. SendMessage( WM_DESTROY_DROPLIST );
  1771. //+++if( suggestlist.size() != 0 )
  1772. if( suggestlist.size() > 1 ) //+++
  1773. {
  1774. m_nCurSel = 0; //+++
  1775. CreateDropList( suggestlist );
  1776. }
  1777. }
  1778. }
  1779. }
  1780. if( !m_pDropWnd )
  1781. {
  1782. // Send message to parent(dialog)
  1783. int nId = GetDlgCtrlID();
  1784. m_pParent->SendMessage( WM_COMMAND, MAKEWPARAM(nId,CBN_EDITUPDATE), (LPARAM)m_hWnd );
  1785. }
  1786. }
  1787. void CAdvComboBox::OnEnable(BOOL bEnable)
  1788. {
  1789. CWnd::OnEnable(bEnable);
  1790. Invalidate();
  1791. if( m_pEdit )
  1792. {
  1793. m_pEdit->EnableWindow( bEnable );
  1794. }
  1795. }
  1796. BOOL CAdvComboBox::LimitText(int nMaxChars)
  1797. {
  1798. if( m_pEdit )
  1799. {
  1800. int nCh = !nMaxChars ? 65535 : nMaxChars;
  1801. m_pEdit->SetLimitText( nCh );
  1802. return TRUE;
  1803. }
  1804. else
  1805. {
  1806. return CB_ERR;
  1807. }
  1808. }
  1809. void CAdvComboBox::SetMinVisibleItems(int nMinItems)
  1810. {
  1811. m_nMinVisItems = nMinItems;
  1812. }
  1813. int CAdvComboBox::GetMinVisibleItems()
  1814. {
  1815. return m_nMinVisItems;
  1816. }
  1817. void CAdvComboBox::OnMouseMove(UINT nFlags, CPoint point)
  1818. {
  1819. bool bChange = m_bDropButtonHot;
  1820. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  1821. {
  1822. if( m_rcDropButton.PtInRect( point ) )
  1823. {
  1824. m_bDropButtonHot = true;
  1825. }
  1826. else
  1827. {
  1828. m_bDropButtonHot = false;
  1829. }
  1830. }
  1831. else
  1832. if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
  1833. {
  1834. GetClientRect( &m_rcCombo );
  1835. if( m_rcCombo.PtInRect( point ) )
  1836. {
  1837. m_bDropButtonHot = true;
  1838. }
  1839. else
  1840. {
  1841. m_bDropButtonHot = false;
  1842. }
  1843. }
  1844. if( bChange != m_bDropButtonHot )
  1845. {
  1846. if( !m_bTrackMouseLeave )
  1847. {
  1848. //
  1849. // Could not use TrackMouseEvent() under Release. A bug appeared
  1850. // the second time the dropwindow was shown, and I did not
  1851. // have to strenght to go look for it. :)
  1852. /* TRACKMOUSEEVENT tme;
  1853. tme.cbSize = sizeof(tme);
  1854. tme.dwFlags = TME_LEAVE;
  1855. tme.hwndTrack = m_hWnd;
  1856. TrackMouseEvent(&tme);*/
  1857. m_bTrackMouseLeave = true;
  1858. SetTimer(1, 50, NULL);
  1859. }
  1860. InvalidateRect( &m_rcDropButton );
  1861. }
  1862. CWnd::OnMouseMove(nFlags, point);
  1863. }
  1864. void CAdvComboBox::OnMouseLeave()
  1865. {
  1866. // TODO: Add your message handler code here and/or call default
  1867. bool bChange = m_bDropButtonHot;
  1868. m_bDropButtonHot = false;
  1869. m_bTrackMouseLeave = false;
  1870. if( bChange != m_bDropButtonHot )
  1871. InvalidateRect( &m_rcDropButton );
  1872. }
  1873. void CAdvComboBox::OnTimer(UINT nIDEvent)
  1874. {
  1875. if( nIDEvent == 1 )
  1876. {
  1877. CPoint point;
  1878. GetCursorPos( &point );
  1879. ScreenToClient( &point );
  1880. if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
  1881. {
  1882. if( !m_rcDropButton.PtInRect( point ) )
  1883. {
  1884. KillTimer( 1 );
  1885. OnMouseLeave();
  1886. }
  1887. }
  1888. else
  1889. if( (GetStyle() & CBS_DROPDOWN) && (GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWNLIST
  1890. {
  1891. GetClientRect( &m_rcCombo );
  1892. if( !m_rcCombo.PtInRect( point ) )
  1893. {
  1894. KillTimer( 1 );
  1895. OnMouseLeave();
  1896. }
  1897. }
  1898. }
  1899. CWnd::OnTimer(nIDEvent);
  1900. }
  1901. int CAdvComboBox::GetDefaultVisibleItems()
  1902. {
  1903. return m_nDefaultDropItems;
  1904. }
  1905. void CAdvComboBox::SetDefaultVisibleItems(int nItems)
  1906. {
  1907. m_nDefaultDropItems = nItems;
  1908. }
  1909. //+++
  1910. // function to get combo width based on strings
  1911. UINT CAdvComboBox::GetComboWidth()
  1912. {
  1913. CDC * pDC = GetDC();
  1914. CFont * pFont = GetFont();
  1915. CFont* pOldFont = pDC->SelectObject(pFont);
  1916. TEXTMETRIC tm;
  1917. pDC->GetTextMetrics(&tm);
  1918. CString str = _T("");
  1919. CSize sz;
  1920. UINT dx = 0;
  1921. for (int i = 0; i < GetCount(); i++)
  1922. {
  1923. GetLBText(i, str);
  1924. sz = pDC->GetTextExtent(str);
  1925. sz.cx += tm.tmAveCharWidth;
  1926. if (sz.cx > (int)dx)
  1927. dx = sz.cx;
  1928. }
  1929. pDC->SelectObject(pOldFont);
  1930. ReleaseDC(pDC);
  1931. dx += ::GetSystemMetrics(SM_CXVSCROLL) + 2*::GetSystemMetrics(SM_CXEDGE) + 5;
  1932. return dx;
  1933. }
  1934. //+++
  1935. void CAdvComboBox::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  1936. {
  1937. // handle escape and return, in case combo's edit does NOT have focus
  1938. if (m_pParent)
  1939. {
  1940. if (nChar == VK_ESCAPE)
  1941. {
  1942. OnEscapeKey();
  1943. return;
  1944. }
  1945. else if (nChar == VK_RETURN)
  1946. {
  1947. OnComboComplete();
  1948. return;
  1949. }
  1950. else if (nChar == VK_DOWN)
  1951. {
  1952. SelNextItem();
  1953. }
  1954. }
  1955. CWnd::OnChar(nChar, nRepCnt, nFlags);
  1956. }
  1957. void CAdvComboBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  1958. {
  1959. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnKeyDown\n"));
  1960. if (nChar == VK_DOWN)
  1961. SelNextItem();
  1962. else if (nChar == VK_UP)
  1963. SelPrevItem();
  1964. else if (nChar == VK_NEXT)
  1965. SelNextPage();
  1966. else if (nChar == VK_PRIOR)
  1967. SelPrevPage();
  1968. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  1969. }
  1970. void CAdvComboBox::OnActivateApp(BOOL bActive, DWORD hTask)
  1971. {
  1972. XLISTCTRL_TRACE(_T("in CAdvComboBox::OnActivateApp\n"));
  1973. CWnd::OnActivateApp(bActive, hTask);
  1974. }