UICombo.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. #include "StdAfx.h"
  2. namespace DuiLib {
  3. /////////////////////////////////////////////////////////////////////////////////////
  4. //
  5. //
  6. class CComboWnd : public CWindowWnd
  7. {
  8. public:
  9. void Init(CComboUI* pOwner);
  10. LPCTSTR GetWindowClassName() const;
  11. void OnFinalMessage(HWND hWnd);
  12. LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
  13. void EnsureVisible(int iIndex);
  14. void Scroll(int dx, int dy);
  15. #if(_WIN32_WINNT >= 0x0501)
  16. virtual UINT GetClassStyle() const;
  17. #endif
  18. public:
  19. CPaintManagerUI m_pm;
  20. CComboUI* m_pOwner;
  21. CVerticalLayoutUI* m_pLayout;
  22. int m_iOldSel;
  23. };
  24. void CComboWnd::Init(CComboUI* pOwner)
  25. {
  26. m_pOwner = pOwner;
  27. m_pLayout = NULL;
  28. m_iOldSel = m_pOwner->GetCurSel();
  29. // Position the popup window in absolute space
  30. SIZE szDrop = m_pOwner->GetDropBoxSize();
  31. RECT rcOwner = pOwner->GetPos();
  32. RECT rc = rcOwner;
  33. rc.top = rc.bottom; // 父窗口left、bottom位置作为弹出窗口起点
  34. rc.bottom = rc.top + szDrop.cy; // 计算弹出窗口高度
  35. if( szDrop.cx > 0 ) rc.right = rc.left + szDrop.cx; // 计算弹出窗口宽度
  36. SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };
  37. int cyFixed = 0;
  38. for( int it = 0; it < pOwner->GetCount(); it++ ) {
  39. CControlUI* pControl = static_cast<CControlUI*>(pOwner->GetItemAt(it));
  40. if( !pControl->IsVisible() ) continue;
  41. SIZE sz = pControl->EstimateSize(szAvailable);
  42. cyFixed += sz.cy;
  43. }
  44. cyFixed += 4; // CVerticalLayoutUI 默认的Inset 调整
  45. rc.bottom = rc.top + MIN(cyFixed, szDrop.cy);
  46. ::MapWindowRect(pOwner->GetManager()->GetPaintWindow(), HWND_DESKTOP, &rc);
  47. MONITORINFO oMonitor = {};
  48. oMonitor.cbSize = sizeof(oMonitor);
  49. ::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
  50. CDuiRect rcWork = oMonitor.rcWork;
  51. if( rc.bottom > rcWork.bottom ) {
  52. rc.left = rcOwner.left;
  53. rc.right = rcOwner.right;
  54. if( szDrop.cx > 0 ) rc.right = rc.left + szDrop.cx;
  55. rc.top = rcOwner.top - MIN(cyFixed, szDrop.cy);
  56. rc.bottom = rcOwner.top;
  57. ::MapWindowRect(pOwner->GetManager()->GetPaintWindow(), HWND_DESKTOP, &rc);
  58. }
  59. Create(pOwner->GetManager()->GetPaintWindow(), NULL, WS_POPUP, WS_EX_TOOLWINDOW, rc);
  60. // HACK: Don't deselect the parent's caption
  61. HWND hWndParent = m_hWnd;
  62. while( ::GetParent(hWndParent) != NULL ) hWndParent = ::GetParent(hWndParent);
  63. ::ShowWindow(m_hWnd, SW_SHOW);
  64. ::SendMessage(hWndParent, WM_NCACTIVATE, TRUE, 0L);
  65. }
  66. LPCTSTR CComboWnd::GetWindowClassName() const
  67. {
  68. return _T("ComboWnd");
  69. }
  70. void CComboWnd::OnFinalMessage(HWND hWnd)
  71. {
  72. m_pOwner->m_pWindow = NULL;
  73. m_pOwner->m_uButtonState &= ~ UISTATE_PUSHED;
  74. m_pOwner->Invalidate();
  75. delete this;
  76. }
  77. LRESULT CComboWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  78. {
  79. if( uMsg == WM_CREATE ) {
  80. m_pm.SetForceUseSharedRes(true);
  81. m_pm.Init(m_hWnd);
  82. // The trick is to add the items to the new container. Their owner gets
  83. // reassigned by this operation - which is why it is important to reassign
  84. // the items back to the righfull owner/manager when the window closes.
  85. m_pLayout = new CVerticalLayoutUI;
  86. m_pLayout->SetManager(&m_pm, NULL, true);
  87. LPCTSTR pDefaultAttributes = m_pOwner->GetManager()->GetDefaultAttributeList(_T("VerticalLayout"));
  88. if( pDefaultAttributes ) {
  89. m_pLayout->ApplyAttributeList(pDefaultAttributes);
  90. }
  91. m_pLayout->SetInset(CDuiRect(1, 1, 1, 1));
  92. m_pLayout->SetBkColor(0xFFFFFFFF);
  93. m_pLayout->SetBorderColor(0xFFC6C7D2);
  94. m_pLayout->SetBorderSize(1);
  95. m_pLayout->SetAutoDestroy(false);
  96. m_pLayout->EnableScrollBar();
  97. m_pLayout->ApplyAttributeList(m_pOwner->GetDropBoxAttributeList());
  98. for( int i = 0; i < m_pOwner->GetCount(); i++ ) {
  99. m_pLayout->Add(static_cast<CControlUI*>(m_pOwner->GetItemAt(i)));
  100. }
  101. m_pm.AttachDialog(m_pLayout);
  102. return 0;
  103. }
  104. else if( uMsg == WM_CLOSE ) {
  105. m_pOwner->SetManager(m_pOwner->GetManager(), m_pOwner->GetParent(), false);
  106. if( !m_pOwner->IsFloat() ) m_pOwner->SetPos(m_pOwner->GetPos(), false);
  107. else m_pOwner->SetPos(m_pOwner->GetRelativePos(), false);
  108. m_pOwner->SetFocus();
  109. }
  110. else if( uMsg == WM_LBUTTONUP ) {
  111. POINT pt = { 0 };
  112. ::GetCursorPos(&pt);
  113. ::ScreenToClient(m_pm.GetPaintWindow(), &pt);
  114. CControlUI* pControl = m_pm.FindControl(pt);
  115. if( pControl && _tcscmp(pControl->GetClass(), _T("ScrollBarUI")) != 0 ) PostMessage(WM_KILLFOCUS);
  116. }
  117. else if( uMsg == WM_KEYDOWN ) {
  118. switch( wParam ) {
  119. case VK_ESCAPE:
  120. m_pOwner->SelectItem(m_iOldSel, true);
  121. EnsureVisible(m_iOldSel);
  122. // FALL THROUGH...
  123. case VK_RETURN:
  124. PostMessage(WM_KILLFOCUS);
  125. break;
  126. default:
  127. TEventUI event;
  128. event.Type = UIEVENT_KEYDOWN;
  129. event.chKey = (TCHAR)wParam;
  130. m_pOwner->DoEvent(event);
  131. EnsureVisible(m_pOwner->GetCurSel());
  132. return 0;
  133. }
  134. }
  135. else if( uMsg == WM_MOUSEWHEEL ) {
  136. int zDelta = (int) (short) HIWORD(wParam);
  137. TEventUI event = { 0 };
  138. event.Type = UIEVENT_SCROLLWHEEL;
  139. event.wParam = MAKELPARAM(zDelta < 0 ? SB_LINEDOWN : SB_LINEUP, 0);
  140. event.lParam = lParam;
  141. event.dwTimestamp = ::GetTickCount();
  142. m_pOwner->DoEvent(event);
  143. EnsureVisible(m_pOwner->GetCurSel());
  144. return 0;
  145. }
  146. else if( uMsg == WM_KILLFOCUS ) {
  147. if( m_hWnd != (HWND) wParam ) PostMessage(WM_CLOSE);
  148. }
  149. LRESULT lRes = 0;
  150. if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
  151. return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
  152. }
  153. void CComboWnd::EnsureVisible(int iIndex)
  154. {
  155. if( m_pOwner->GetCurSel() < 0 ) return;
  156. m_pLayout->FindSelectable(m_pOwner->GetCurSel(), false);
  157. RECT rcItem = m_pLayout->GetItemAt(iIndex)->GetPos();
  158. RECT rcList = m_pLayout->GetPos();
  159. CScrollBarUI* pHorizontalScrollBar = m_pLayout->GetHorizontalScrollBar();
  160. if( pHorizontalScrollBar && pHorizontalScrollBar->IsVisible() ) rcList.bottom -= pHorizontalScrollBar->GetFixedHeight();
  161. int iPos = m_pLayout->GetScrollPos().cy;
  162. if( rcItem.top >= rcList.top && rcItem.bottom < rcList.bottom ) return;
  163. int dx = 0;
  164. if( rcItem.top < rcList.top ) dx = rcItem.top - rcList.top;
  165. if( rcItem.bottom > rcList.bottom ) dx = rcItem.bottom - rcList.bottom;
  166. Scroll(0, dx);
  167. }
  168. void CComboWnd::Scroll(int dx, int dy)
  169. {
  170. if( dx == 0 && dy == 0 ) return;
  171. SIZE sz = m_pLayout->GetScrollPos();
  172. m_pLayout->SetScrollPos(CDuiSize(sz.cx + dx, sz.cy + dy));
  173. }
  174. #if(_WIN32_WINNT >= 0x0501)
  175. UINT CComboWnd::GetClassStyle() const
  176. {
  177. return __super::GetClassStyle() | CS_DROPSHADOW;
  178. }
  179. #endif
  180. ////////////////////////////////////////////////////////
  181. CComboUI::CComboUI() : m_pWindow(NULL), m_iCurSel(-1), m_uButtonState(0)
  182. {
  183. m_szDropBox = CDuiSize(0, 150);
  184. ::ZeroMemory(&m_rcTextPadding, sizeof(m_rcTextPadding));
  185. m_ListInfo.nColumns = 0;
  186. m_ListInfo.nFont = -1;
  187. m_ListInfo.uTextStyle = DT_VCENTER;
  188. m_ListInfo.dwTextColor = 0xFF000000;
  189. m_ListInfo.dwBkColor = 0;
  190. m_ListInfo.bAlternateBk = false;
  191. m_ListInfo.dwSelectedTextColor = 0xFF000000;
  192. m_ListInfo.dwSelectedBkColor = 0xFFC1E3FF;
  193. m_ListInfo.dwHotTextColor = 0xFF000000;
  194. m_ListInfo.dwHotBkColor = 0xFFE9F5FF;
  195. m_ListInfo.dwDisabledTextColor = 0xFFCCCCCC;
  196. m_ListInfo.dwDisabledBkColor = 0xFFFFFFFF;
  197. m_ListInfo.dwLineColor = 0;
  198. m_ListInfo.bShowHtml = false;
  199. m_ListInfo.bMultiExpandable = false;
  200. m_bShowText = true;
  201. m_bSelectCloseFlag = true;
  202. ::ZeroMemory(&m_ListInfo.rcTextPadding, sizeof(m_ListInfo.rcTextPadding));
  203. ::ZeroMemory(&m_ListInfo.rcColumn, sizeof(m_ListInfo.rcColumn));
  204. }
  205. LPCTSTR CComboUI::GetClass() const
  206. {
  207. return _T("ComboUI");
  208. }
  209. LPVOID CComboUI::GetInterface(LPCTSTR pstrName)
  210. {
  211. if( _tcscmp(pstrName, DUI_CTR_COMBO) == 0 ) return static_cast<CComboUI*>(this);
  212. if( _tcscmp(pstrName, _T("IListOwner")) == 0 ) return static_cast<IListOwnerUI*>(this);
  213. return CContainerUI::GetInterface(pstrName);
  214. }
  215. UINT CComboUI::GetControlFlags() const
  216. {
  217. return UIFLAG_TABSTOP;
  218. }
  219. void CComboUI::DoInit()
  220. {
  221. }
  222. int CComboUI::GetCurSel() const
  223. {
  224. return m_iCurSel;
  225. }
  226. bool CComboUI::GetSelectCloseFlag()
  227. {
  228. return m_bSelectCloseFlag;
  229. }
  230. void CComboUI::SetSelectCloseFlag(bool flag)
  231. {
  232. m_bSelectCloseFlag = flag;
  233. }
  234. bool CComboUI::SelectItem(int iIndex, bool bTakeFocus, bool bTriggerEvent)
  235. {
  236. if( m_bSelectCloseFlag && m_pWindow != NULL ) m_pWindow->Close();
  237. if( iIndex == m_iCurSel ) return true;
  238. int iOldSel = m_iCurSel;
  239. if( m_iCurSel >= 0 ) {
  240. CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
  241. if( !pControl ) return false;
  242. IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
  243. if( pListItem != NULL ) pListItem->Select(false, bTriggerEvent);
  244. m_iCurSel = -1;
  245. }
  246. if( iIndex < 0 ) return false;
  247. if( m_items.GetSize() == 0 ) return false;
  248. if( iIndex >= m_items.GetSize() ) iIndex = m_items.GetSize() - 1;
  249. CControlUI* pControl = static_cast<CControlUI*>(m_items[iIndex]);
  250. if( !pControl || !pControl->IsVisible() || !pControl->IsEnabled() ) return false;
  251. IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
  252. if( pListItem == NULL ) return false;
  253. m_iCurSel = iIndex;
  254. if( m_pWindow != NULL || bTakeFocus ) pControl->SetFocus();
  255. pListItem->Select(true, bTriggerEvent);
  256. if( m_pManager != NULL && bTriggerEvent) m_pManager->SendNotify(this, DUI_MSGTYPE_ITEMSELECT, m_iCurSel, iOldSel);
  257. Invalidate();
  258. return true;
  259. }
  260. bool CComboUI::SetItemIndex(CControlUI* pControl, int iIndex)
  261. {
  262. int iOrginIndex = GetItemIndex(pControl);
  263. if( iOrginIndex == -1 ) return false;
  264. if( iOrginIndex == iIndex ) return true;
  265. IListItemUI* pSelectedListItem = NULL;
  266. if( m_iCurSel >= 0 ) pSelectedListItem =
  267. static_cast<IListItemUI*>(GetItemAt(m_iCurSel)->GetInterface(_T("ListItem")));
  268. if( !CContainerUI::SetItemIndex(pControl, iIndex) ) return false;
  269. int iMinIndex = min(iOrginIndex, iIndex);
  270. int iMaxIndex = max(iOrginIndex, iIndex);
  271. for(int i = iMinIndex; i < iMaxIndex + 1; ++i) {
  272. CControlUI* p = GetItemAt(i);
  273. IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));
  274. if( pListItem != NULL ) {
  275. pListItem->SetIndex(i);
  276. }
  277. }
  278. if( m_iCurSel >= 0 && pSelectedListItem != NULL ) m_iCurSel = pSelectedListItem->GetIndex();
  279. return true;
  280. }
  281. bool CComboUI::Add(CControlUI* pControl)
  282. {
  283. IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
  284. if( pListItem != NULL )
  285. {
  286. pListItem->SetOwner(this);
  287. pListItem->SetIndex(m_items.GetSize());
  288. }
  289. return CContainerUI::Add(pControl);
  290. }
  291. bool CComboUI::AddAt(CControlUI* pControl, int iIndex)
  292. {
  293. if (!CContainerUI::AddAt(pControl, iIndex)) return false;
  294. // The list items should know about us
  295. IListItemUI* pListItem = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
  296. if( pListItem != NULL ) {
  297. pListItem->SetOwner(this);
  298. pListItem->SetIndex(iIndex);
  299. }
  300. for(int i = iIndex + 1; i < GetCount(); ++i) {
  301. CControlUI* p = GetItemAt(i);
  302. pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));
  303. if( pListItem != NULL ) {
  304. pListItem->SetIndex(i);
  305. }
  306. }
  307. if( m_iCurSel >= iIndex ) m_iCurSel += 1;
  308. return true;
  309. }
  310. bool CComboUI::Remove(CControlUI* pControl)
  311. {
  312. int iIndex = GetItemIndex(pControl);
  313. if (iIndex == -1) return false;
  314. if (!CContainerUI::RemoveAt(iIndex)) return false;
  315. for(int i = iIndex; i < GetCount(); ++i) {
  316. CControlUI* p = GetItemAt(i);
  317. IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));
  318. if( pListItem != NULL ) {
  319. pListItem->SetIndex(i);
  320. }
  321. }
  322. if( iIndex == m_iCurSel && m_iCurSel >= 0 ) {
  323. int iSel = m_iCurSel;
  324. m_iCurSel = -1;
  325. SelectItem(FindSelectable(iSel, false));
  326. }
  327. else if( iIndex < m_iCurSel ) m_iCurSel -= 1;
  328. return true;
  329. }
  330. bool CComboUI::RemoveAt(int iIndex)
  331. {
  332. if (!CContainerUI::RemoveAt(iIndex)) return false;
  333. for(int i = iIndex; i < GetCount(); ++i) {
  334. CControlUI* p = GetItemAt(i);
  335. IListItemUI* pListItem = static_cast<IListItemUI*>(p->GetInterface(_T("ListItem")));
  336. if( pListItem != NULL ) pListItem->SetIndex(i);
  337. }
  338. if( iIndex == m_iCurSel && m_iCurSel >= 0 ) {
  339. int iSel = m_iCurSel;
  340. m_iCurSel = -1;
  341. SelectItem(FindSelectable(iSel, false));
  342. }
  343. else if( iIndex < m_iCurSel ) m_iCurSel -= 1;
  344. return true;
  345. }
  346. void CComboUI::RemoveAll()
  347. {
  348. m_iCurSel = -1;
  349. CContainerUI::RemoveAll();
  350. }
  351. void CComboUI::DoEvent(TEventUI& event)
  352. {
  353. if( !IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND ) {
  354. if( m_pParent != NULL ) m_pParent->DoEvent(event);
  355. else CContainerUI::DoEvent(event);
  356. return;
  357. }
  358. if( event.Type == UIEVENT_SETFOCUS )
  359. {
  360. Invalidate();
  361. }
  362. if( event.Type == UIEVENT_KILLFOCUS )
  363. {
  364. Invalidate();
  365. }
  366. if( event.Type == UIEVENT_BUTTONDOWN )
  367. {
  368. if( IsEnabled() ) {
  369. Activate();
  370. m_uButtonState |= UISTATE_PUSHED | UISTATE_CAPTURED;
  371. }
  372. return;
  373. }
  374. if( event.Type == UIEVENT_BUTTONUP )
  375. {
  376. if( (m_uButtonState & UISTATE_CAPTURED) != 0 ) {
  377. m_uButtonState &= ~ UISTATE_CAPTURED;
  378. Invalidate();
  379. }
  380. return;
  381. }
  382. if( event.Type == UIEVENT_MOUSEMOVE )
  383. {
  384. return;
  385. }
  386. if( event.Type == UIEVENT_KEYDOWN )
  387. {
  388. switch( event.chKey ) {
  389. case VK_F4:
  390. Activate();
  391. return;
  392. case VK_UP:
  393. SetSelectCloseFlag(false);
  394. SelectItem(FindSelectable(m_iCurSel - 1, false));
  395. SetSelectCloseFlag(true);
  396. return;
  397. case VK_DOWN:
  398. SetSelectCloseFlag(false);
  399. SelectItem(FindSelectable(m_iCurSel + 1, true));
  400. SetSelectCloseFlag(true);
  401. return;
  402. case VK_PRIOR:
  403. SetSelectCloseFlag(false);
  404. SelectItem(FindSelectable(m_iCurSel - 1, false));
  405. SetSelectCloseFlag(true);
  406. return;
  407. case VK_NEXT:
  408. SetSelectCloseFlag(false);
  409. SelectItem(FindSelectable(m_iCurSel + 1, true));
  410. SetSelectCloseFlag(true);
  411. return;
  412. case VK_HOME:
  413. SetSelectCloseFlag(false);
  414. SelectItem(FindSelectable(0, false));
  415. SetSelectCloseFlag(true);
  416. return;
  417. case VK_END:
  418. SetSelectCloseFlag(false);
  419. SelectItem(FindSelectable(GetCount() - 1, true));
  420. SetSelectCloseFlag(true);
  421. return;
  422. }
  423. }
  424. if( event.Type == UIEVENT_SCROLLWHEEL )
  425. {
  426. bool bDownward = LOWORD(event.wParam) == SB_LINEDOWN;
  427. SetSelectCloseFlag(false);
  428. SelectItem(FindSelectable(m_iCurSel + (bDownward ? 1 : -1), bDownward));
  429. SetSelectCloseFlag(true);
  430. return;
  431. }
  432. if( event.Type == UIEVENT_CONTEXTMENU )
  433. {
  434. return;
  435. }
  436. if( event.Type == UIEVENT_MOUSEENTER )
  437. {
  438. if( ::PtInRect(&m_rcItem, event.ptMouse ) ) {
  439. if( (m_uButtonState & UISTATE_HOT) == 0 )
  440. m_uButtonState |= UISTATE_HOT;
  441. Invalidate();
  442. }
  443. return;
  444. }
  445. if( event.Type == UIEVENT_MOUSELEAVE )
  446. {
  447. if( (m_uButtonState & UISTATE_HOT) != 0 ) {
  448. m_uButtonState &= ~UISTATE_HOT;
  449. Invalidate();
  450. }
  451. return;
  452. }
  453. CControlUI::DoEvent(event);
  454. }
  455. SIZE CComboUI::EstimateSize(SIZE szAvailable)
  456. {
  457. if( m_cxyFixed.cy == 0 ) return CDuiSize(m_cxyFixed.cx, m_pManager->GetDefaultFontInfo()->tm.tmHeight + 12);
  458. return CControlUI::EstimateSize(szAvailable);
  459. }
  460. bool CComboUI::Activate()
  461. {
  462. if( !CControlUI::Activate() ) return false;
  463. if( m_pWindow ) return true;
  464. m_pWindow = new CComboWnd();
  465. ASSERT(m_pWindow);
  466. m_pWindow->Init(this);
  467. if( m_pManager != NULL ) m_pManager->SendNotify(this, DUI_MSGTYPE_DROPDOWN);
  468. Invalidate();
  469. return true;
  470. }
  471. CDuiString CComboUI::GetText() const
  472. {
  473. if( m_iCurSel < 0 ) return _T("");
  474. CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
  475. return pControl->GetText();
  476. }
  477. void CComboUI::SetEnabled(bool bEnable)
  478. {
  479. CContainerUI::SetEnabled(bEnable);
  480. if( !IsEnabled() ) m_uButtonState = 0;
  481. }
  482. CDuiString CComboUI::GetDropBoxAttributeList()
  483. {
  484. return m_sDropBoxAttributes;
  485. }
  486. void CComboUI::SetDropBoxAttributeList(LPCTSTR pstrList)
  487. {
  488. m_sDropBoxAttributes = pstrList;
  489. }
  490. SIZE CComboUI::GetDropBoxSize() const
  491. {
  492. return m_szDropBox;
  493. }
  494. void CComboUI::SetDropBoxSize(SIZE szDropBox)
  495. {
  496. m_szDropBox = szDropBox;
  497. }
  498. bool CComboUI::GetShowText() const
  499. {
  500. return m_bShowText;
  501. }
  502. void CComboUI::SetShowText(bool flag)
  503. {
  504. m_bShowText = flag;
  505. Invalidate();
  506. }
  507. RECT CComboUI::GetTextPadding() const
  508. {
  509. return m_rcTextPadding;
  510. }
  511. void CComboUI::SetTextPadding(RECT rc)
  512. {
  513. m_rcTextPadding = rc;
  514. Invalidate();
  515. }
  516. LPCTSTR CComboUI::GetNormalImage() const
  517. {
  518. return m_diNormal.sDrawString;
  519. }
  520. void CComboUI::SetNormalImage(LPCTSTR pStrImage)
  521. {
  522. if( m_diNormal.sDrawString == pStrImage && m_diNormal.pImageInfo != NULL ) return;
  523. m_diNormal.Clear();
  524. m_diNormal.sDrawString = pStrImage;
  525. Invalidate();
  526. }
  527. LPCTSTR CComboUI::GetHotImage() const
  528. {
  529. return m_diHot.sDrawString;
  530. }
  531. void CComboUI::SetHotImage(LPCTSTR pStrImage)
  532. {
  533. if( m_diHot.sDrawString == pStrImage && m_diHot.pImageInfo != NULL ) return;
  534. m_diHot.Clear();
  535. m_diHot.sDrawString = pStrImage;
  536. Invalidate();
  537. }
  538. LPCTSTR CComboUI::GetPushedImage() const
  539. {
  540. return m_diPushed.sDrawString;
  541. }
  542. void CComboUI::SetPushedImage(LPCTSTR pStrImage)
  543. {
  544. if( m_diPushed.sDrawString == pStrImage && m_diPushed.pImageInfo != NULL ) return;
  545. m_diPushed.Clear();
  546. m_diPushed.sDrawString = pStrImage;
  547. Invalidate();
  548. }
  549. LPCTSTR CComboUI::GetFocusedImage() const
  550. {
  551. return m_diFocused.sDrawString;
  552. }
  553. void CComboUI::SetFocusedImage(LPCTSTR pStrImage)
  554. {
  555. if( m_diFocused.sDrawString == pStrImage && m_diFocused.pImageInfo != NULL ) return;
  556. m_diFocused.Clear();
  557. m_diFocused.sDrawString = pStrImage;
  558. Invalidate();
  559. }
  560. LPCTSTR CComboUI::GetDisabledImage() const
  561. {
  562. return m_diDisabled.sDrawString;
  563. }
  564. void CComboUI::SetDisabledImage(LPCTSTR pStrImage)
  565. {
  566. if( m_diDisabled.sDrawString == pStrImage && m_diDisabled.pImageInfo != NULL ) return;
  567. m_diDisabled.Clear();
  568. m_diDisabled.sDrawString = pStrImage;
  569. Invalidate();
  570. }
  571. TListInfoUI* CComboUI::GetListInfo()
  572. {
  573. return &m_ListInfo;
  574. }
  575. void CComboUI::SetItemFont(int index)
  576. {
  577. m_ListInfo.nFont = index;
  578. Invalidate();
  579. }
  580. void CComboUI::SetItemTextStyle(UINT uStyle)
  581. {
  582. m_ListInfo.uTextStyle = uStyle;
  583. Invalidate();
  584. }
  585. RECT CComboUI::GetItemTextPadding() const
  586. {
  587. return m_ListInfo.rcTextPadding;
  588. }
  589. void CComboUI::SetItemTextPadding(RECT rc)
  590. {
  591. m_ListInfo.rcTextPadding = rc;
  592. Invalidate();
  593. }
  594. void CComboUI::SetItemTextColor(DWORD dwTextColor)
  595. {
  596. m_ListInfo.dwTextColor = dwTextColor;
  597. Invalidate();
  598. }
  599. void CComboUI::SetItemBkColor(DWORD dwBkColor)
  600. {
  601. m_ListInfo.dwBkColor = dwBkColor;
  602. }
  603. void CComboUI::SetItemBkImage(LPCTSTR pStrImage)
  604. {
  605. if( m_ListInfo.diBk.sDrawString == pStrImage && m_ListInfo.diBk.pImageInfo != NULL ) return;
  606. m_ListInfo.diBk.Clear();
  607. m_ListInfo.diBk.sDrawString = pStrImage;
  608. }
  609. DWORD CComboUI::GetItemTextColor() const
  610. {
  611. return m_ListInfo.dwTextColor;
  612. }
  613. DWORD CComboUI::GetItemBkColor() const
  614. {
  615. return m_ListInfo.dwBkColor;
  616. }
  617. LPCTSTR CComboUI::GetItemBkImage() const
  618. {
  619. return m_ListInfo.diBk.sDrawString;
  620. }
  621. bool CComboUI::IsAlternateBk() const
  622. {
  623. return m_ListInfo.bAlternateBk;
  624. }
  625. void CComboUI::SetAlternateBk(bool bAlternateBk)
  626. {
  627. m_ListInfo.bAlternateBk = bAlternateBk;
  628. }
  629. void CComboUI::SetSelectedItemTextColor(DWORD dwTextColor)
  630. {
  631. m_ListInfo.dwSelectedTextColor = dwTextColor;
  632. }
  633. void CComboUI::SetSelectedItemBkColor(DWORD dwBkColor)
  634. {
  635. m_ListInfo.dwSelectedBkColor = dwBkColor;
  636. }
  637. void CComboUI::SetSelectedItemImage(LPCTSTR pStrImage)
  638. {
  639. if( m_ListInfo.diSelected.sDrawString == pStrImage && m_ListInfo.diSelected.pImageInfo != NULL ) return;
  640. m_ListInfo.diSelected.Clear();
  641. m_ListInfo.diSelected.sDrawString = pStrImage;
  642. }
  643. DWORD CComboUI::GetSelectedItemTextColor() const
  644. {
  645. return m_ListInfo.dwSelectedTextColor;
  646. }
  647. DWORD CComboUI::GetSelectedItemBkColor() const
  648. {
  649. return m_ListInfo.dwSelectedBkColor;
  650. }
  651. LPCTSTR CComboUI::GetSelectedItemImage() const
  652. {
  653. return m_ListInfo.diSelected.sDrawString;
  654. }
  655. void CComboUI::SetHotItemTextColor(DWORD dwTextColor)
  656. {
  657. m_ListInfo.dwHotTextColor = dwTextColor;
  658. }
  659. void CComboUI::SetHotItemBkColor(DWORD dwBkColor)
  660. {
  661. m_ListInfo.dwHotBkColor = dwBkColor;
  662. }
  663. void CComboUI::SetHotItemImage(LPCTSTR pStrImage)
  664. {
  665. if( m_ListInfo.diHot.sDrawString == pStrImage && m_ListInfo.diHot.pImageInfo != NULL ) return;
  666. m_ListInfo.diHot.Clear();
  667. m_ListInfo.diHot.sDrawString = pStrImage;
  668. }
  669. DWORD CComboUI::GetHotItemTextColor() const
  670. {
  671. return m_ListInfo.dwHotTextColor;
  672. }
  673. DWORD CComboUI::GetHotItemBkColor() const
  674. {
  675. return m_ListInfo.dwHotBkColor;
  676. }
  677. LPCTSTR CComboUI::GetHotItemImage() const
  678. {
  679. return m_ListInfo.diHot.sDrawString;
  680. }
  681. void CComboUI::SetDisabledItemTextColor(DWORD dwTextColor)
  682. {
  683. m_ListInfo.dwDisabledTextColor = dwTextColor;
  684. }
  685. void CComboUI::SetDisabledItemBkColor(DWORD dwBkColor)
  686. {
  687. m_ListInfo.dwDisabledBkColor = dwBkColor;
  688. }
  689. void CComboUI::SetDisabledItemImage(LPCTSTR pStrImage)
  690. {
  691. if( m_ListInfo.diDisabled.sDrawString == pStrImage && m_ListInfo.diDisabled.pImageInfo != NULL ) return;
  692. m_ListInfo.diDisabled.Clear();
  693. m_ListInfo.diDisabled.sDrawString = pStrImage;
  694. }
  695. DWORD CComboUI::GetDisabledItemTextColor() const
  696. {
  697. return m_ListInfo.dwDisabledTextColor;
  698. }
  699. DWORD CComboUI::GetDisabledItemBkColor() const
  700. {
  701. return m_ListInfo.dwDisabledBkColor;
  702. }
  703. LPCTSTR CComboUI::GetDisabledItemImage() const
  704. {
  705. return m_ListInfo.diDisabled.sDrawString;
  706. }
  707. DWORD CComboUI::GetItemLineColor() const
  708. {
  709. return m_ListInfo.dwLineColor;
  710. }
  711. void CComboUI::SetItemLineColor(DWORD dwLineColor)
  712. {
  713. m_ListInfo.dwLineColor = dwLineColor;
  714. }
  715. bool CComboUI::IsItemShowHtml()
  716. {
  717. return m_ListInfo.bShowHtml;
  718. }
  719. void CComboUI::SetItemShowHtml(bool bShowHtml)
  720. {
  721. if( m_ListInfo.bShowHtml == bShowHtml ) return;
  722. m_ListInfo.bShowHtml = bShowHtml;
  723. Invalidate();
  724. }
  725. void CComboUI::SetPos(RECT rc, bool bNeedInvalidate)
  726. {
  727. // Put all elements out of sight
  728. RECT rcNull = { 0 };
  729. for( int i = 0; i < m_items.GetSize(); i++ ) static_cast<CControlUI*>(m_items[i])->SetPos(rcNull, false);
  730. // Position this control
  731. CControlUI::SetPos(rc, bNeedInvalidate);
  732. }
  733. void CComboUI::Move(SIZE szOffset, bool bNeedInvalidate)
  734. {
  735. CControlUI::Move(szOffset, bNeedInvalidate);
  736. }
  737. void CComboUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
  738. {
  739. if( _tcscmp(pstrName, _T("textpadding")) == 0 ) {
  740. RECT rcTextPadding = { 0 };
  741. LPTSTR pstr = NULL;
  742. rcTextPadding.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  743. rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  744. rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  745. rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  746. SetTextPadding(rcTextPadding);
  747. }
  748. else if( _tcscmp(pstrName, _T("showtext")) == 0 ) SetShowText(_tcscmp(pstrValue, _T("true")) == 0);
  749. else if( _tcscmp(pstrName, _T("normalimage")) == 0 ) SetNormalImage(pstrValue);
  750. else if( _tcscmp(pstrName, _T("hotimage")) == 0 ) SetHotImage(pstrValue);
  751. else if( _tcscmp(pstrName, _T("pushedimage")) == 0 ) SetPushedImage(pstrValue);
  752. else if( _tcscmp(pstrName, _T("focusedimage")) == 0 ) SetFocusedImage(pstrValue);
  753. else if( _tcscmp(pstrName, _T("disabledimage")) == 0 ) SetDisabledImage(pstrValue);
  754. else if( _tcscmp(pstrName, _T("dropbox")) == 0 ) SetDropBoxAttributeList(pstrValue);
  755. else if( _tcscmp(pstrName, _T("dropboxsize")) == 0)
  756. {
  757. SIZE szDropBoxSize = { 0 };
  758. LPTSTR pstr = NULL;
  759. szDropBoxSize.cx = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  760. szDropBoxSize.cy = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  761. SetDropBoxSize(szDropBoxSize);
  762. }
  763. else if( _tcscmp(pstrName, _T("itemfont")) == 0 ) m_ListInfo.nFont = _ttoi(pstrValue);
  764. else if( _tcscmp(pstrName, _T("itemalign")) == 0 ) {
  765. if( _tcsstr(pstrValue, _T("left")) != NULL ) {
  766. m_ListInfo.uTextStyle &= ~(DT_CENTER | DT_RIGHT);
  767. m_ListInfo.uTextStyle |= DT_LEFT;
  768. }
  769. if( _tcsstr(pstrValue, _T("center")) != NULL ) {
  770. m_ListInfo.uTextStyle &= ~(DT_LEFT | DT_RIGHT);
  771. m_ListInfo.uTextStyle |= DT_CENTER;
  772. }
  773. if( _tcsstr(pstrValue, _T("right")) != NULL ) {
  774. m_ListInfo.uTextStyle &= ~(DT_LEFT | DT_CENTER);
  775. m_ListInfo.uTextStyle |= DT_RIGHT;
  776. }
  777. }
  778. if( _tcscmp(pstrName, _T("itemtextpadding")) == 0 ) {
  779. RECT rcTextPadding = { 0 };
  780. LPTSTR pstr = NULL;
  781. rcTextPadding.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  782. rcTextPadding.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  783. rcTextPadding.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  784. rcTextPadding.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  785. SetItemTextPadding(rcTextPadding);
  786. }
  787. else if( _tcscmp(pstrName, _T("itemtextcolor")) == 0 ) {
  788. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  789. LPTSTR pstr = NULL;
  790. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  791. SetItemTextColor(clrColor);
  792. }
  793. else if( _tcscmp(pstrName, _T("itembkcolor")) == 0 ) {
  794. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  795. LPTSTR pstr = NULL;
  796. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  797. SetItemBkColor(clrColor);
  798. }
  799. else if( _tcscmp(pstrName, _T("itembkimage")) == 0 ) SetItemBkImage(pstrValue);
  800. else if( _tcscmp(pstrName, _T("itemaltbk")) == 0 ) SetAlternateBk(_tcscmp(pstrValue, _T("true")) == 0);
  801. else if( _tcscmp(pstrName, _T("itemselectedtextcolor")) == 0 ) {
  802. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  803. LPTSTR pstr = NULL;
  804. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  805. SetSelectedItemTextColor(clrColor);
  806. }
  807. else if( _tcscmp(pstrName, _T("itemselectedbkcolor")) == 0 ) {
  808. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  809. LPTSTR pstr = NULL;
  810. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  811. SetSelectedItemBkColor(clrColor);
  812. }
  813. else if( _tcscmp(pstrName, _T("itemselectedimage")) == 0 ) SetSelectedItemImage(pstrValue);
  814. else if( _tcscmp(pstrName, _T("itemhottextcolor")) == 0 ) {
  815. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  816. LPTSTR pstr = NULL;
  817. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  818. SetHotItemTextColor(clrColor);
  819. }
  820. else if( _tcscmp(pstrName, _T("itemhotbkcolor")) == 0 ) {
  821. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  822. LPTSTR pstr = NULL;
  823. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  824. SetHotItemBkColor(clrColor);
  825. }
  826. else if( _tcscmp(pstrName, _T("itemhotimage")) == 0 ) SetHotItemImage(pstrValue);
  827. else if( _tcscmp(pstrName, _T("itemdisabledtextcolor")) == 0 ) {
  828. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  829. LPTSTR pstr = NULL;
  830. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  831. SetDisabledItemTextColor(clrColor);
  832. }
  833. else if( _tcscmp(pstrName, _T("itemdisabledbkcolor")) == 0 ) {
  834. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  835. LPTSTR pstr = NULL;
  836. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  837. SetDisabledItemBkColor(clrColor);
  838. }
  839. else if( _tcscmp(pstrName, _T("itemdisabledimage")) == 0 ) SetDisabledItemImage(pstrValue);
  840. else if( _tcscmp(pstrName, _T("itemlinecolor")) == 0 ) {
  841. if( *pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
  842. LPTSTR pstr = NULL;
  843. DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
  844. SetItemLineColor(clrColor);
  845. }
  846. else if( _tcscmp(pstrName, _T("itemshowhtml")) == 0 ) SetItemShowHtml(_tcscmp(pstrValue, _T("true")) == 0);
  847. else CContainerUI::SetAttribute(pstrName, pstrValue);
  848. }
  849. void CComboUI::DoPaint(HDC hDC, const RECT& rcPaint)
  850. {
  851. CControlUI::DoPaint(hDC, rcPaint);
  852. }
  853. void CComboUI::PaintStatusImage(HDC hDC)
  854. {
  855. if( IsFocused() ) m_uButtonState |= UISTATE_FOCUSED;
  856. else m_uButtonState &= ~ UISTATE_FOCUSED;
  857. if( !IsEnabled() ) m_uButtonState |= UISTATE_DISABLED;
  858. else m_uButtonState &= ~ UISTATE_DISABLED;
  859. if( (m_uButtonState & UISTATE_DISABLED) != 0 ) {
  860. if (DrawImage(hDC, m_diDisabled)) return;
  861. }
  862. else if( (m_uButtonState & UISTATE_PUSHED) != 0 ) {
  863. if (DrawImage(hDC, m_diPushed)) return;
  864. }
  865. else if( (m_uButtonState & UISTATE_HOT) != 0 ) {
  866. if (DrawImage(hDC, m_diHot)) return;
  867. }
  868. else if( (m_uButtonState & UISTATE_FOCUSED) != 0 ) {
  869. if (DrawImage(hDC, m_diFocused)) return;
  870. }
  871. DrawImage(hDC, m_diNormal);
  872. }
  873. void CComboUI::PaintText(HDC hDC)
  874. {
  875. if (!m_bShowText) return;
  876. RECT rcText = m_rcItem;
  877. rcText.left += m_rcTextPadding.left;
  878. rcText.right -= m_rcTextPadding.right;
  879. rcText.top += m_rcTextPadding.top;
  880. rcText.bottom -= m_rcTextPadding.bottom;
  881. if( m_iCurSel >= 0 ) {
  882. CControlUI* pControl = static_cast<CControlUI*>(m_items[m_iCurSel]);
  883. IListItemUI* pElement = static_cast<IListItemUI*>(pControl->GetInterface(_T("ListItem")));
  884. if( pElement != NULL ) {
  885. pElement->DrawItemText(hDC, rcText);
  886. }
  887. else {
  888. RECT rcOldPos = pControl->GetPos();
  889. pControl->SetPos(rcText, false);
  890. pControl->Paint(hDC, rcText);
  891. pControl->SetPos(rcOldPos, false);
  892. }
  893. }
  894. }
  895. } // namespace DuiLib