ControlEx.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #ifndef __CONTROLEX_H__
  2. #define __CONTROLEX_H__
  3. #include <vector>
  4. #include <math.h>
  5. inline double CalculateDelay(double state) {
  6. return pow(state, 2);
  7. }
  8. // category(0)->game(1)->server(2)->room(3)
  9. class GameListUI : public CListUI
  10. {
  11. public:
  12. enum { SCROLL_TIMERID = 10 };
  13. struct NodeData
  14. {
  15. int _level;
  16. bool _expand;
  17. CDuiString _text;
  18. CListLabelElementUI* _pListElement;
  19. };
  20. class Node
  21. {
  22. typedef std::vector <Node*> Children;
  23. Children _children;
  24. Node* _parent;
  25. NodeData _data;
  26. private:
  27. void set_parent(Node* parent) { _parent = parent; }
  28. public:
  29. Node() : _parent(NULL) {}
  30. explicit Node(NodeData t) : _data(t), _parent(NULL) {}
  31. Node(NodeData t, Node* parent) : _data(t), _parent(parent) {}
  32. ~Node()
  33. {
  34. for (int i = 0; i < num_children(); i++)
  35. delete _children[i];
  36. }
  37. NodeData& data() { return _data; }
  38. int num_children() const { return _children.size(); }
  39. Node* child(int i) { return _children[i]; }
  40. Node* parent() { return (_parent); }
  41. bool has_children() const { return num_children() > 0; }
  42. void add_child(Node* child)
  43. {
  44. child->set_parent(this);
  45. _children.push_back(child);
  46. }
  47. void remove_child(Node* child)
  48. {
  49. Children::iterator iter = _children.begin();
  50. for (; iter < _children.end(); ++iter)
  51. {
  52. if (*iter == child)
  53. {
  54. _children.erase(iter);
  55. return;
  56. }
  57. }
  58. }
  59. Node* get_last_child()
  60. {
  61. if (has_children())
  62. {
  63. return child(num_children() - 1)->get_last_child();
  64. }
  65. else return this;
  66. }
  67. };
  68. GameListUI() : _root(NULL), m_dwDelayDeltaY(0), m_dwDelayNum(0), m_dwDelayLeft(0)
  69. {
  70. SetItemShowHtml(true);
  71. _root = new Node;
  72. _root->data()._level = -1;
  73. _root->data()._expand = true;
  74. _root->data()._pListElement = NULL;
  75. }
  76. ~GameListUI() { if (_root) delete _root; }
  77. bool Add(CControlUI* pControl)
  78. {
  79. if (!pControl) return false;
  80. if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
  81. return CListUI::Add(pControl);
  82. }
  83. bool AddAt(CControlUI* pControl, int iIndex)
  84. {
  85. if (!pControl) return false;
  86. if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
  87. return CListUI::AddAt(pControl, iIndex);
  88. }
  89. bool Remove(CControlUI* pControl, bool bDoNotDestroy = false)
  90. {
  91. if (!pControl) return false;
  92. if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
  93. if (reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()) == NULL)
  94. return CListUI::Remove(pControl, bDoNotDestroy);
  95. else
  96. return RemoveNode(reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()));
  97. }
  98. bool RemoveAt(int iIndex, bool bDoNotDestroy = false)
  99. {
  100. CControlUI* pControl = GetItemAt(iIndex);
  101. if (!pControl) return false;
  102. if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
  103. if (reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()) == NULL)
  104. return CListUI::RemoveAt(iIndex, bDoNotDestroy);
  105. else
  106. return RemoveNode(reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()));
  107. }
  108. void RemoveAll()
  109. {
  110. CListUI::RemoveAll();
  111. for (int i = 0; i < _root->num_children(); ++i)
  112. {
  113. Node* child = _root->child(i);
  114. RemoveNode(child);
  115. }
  116. delete _root;
  117. _root = new Node;
  118. _root->data()._level = -1;
  119. _root->data()._expand = true;
  120. _root->data()._pListElement = NULL;
  121. }
  122. void SetVisible(bool bVisible = true)
  123. {
  124. if (m_bVisible == bVisible) return;
  125. CControlUI::SetVisible(bVisible);
  126. }
  127. void SetInternVisible(bool bVisible = true)
  128. {
  129. CControlUI::SetInternVisible(bVisible);
  130. }
  131. void DoEvent(TEventUI& event)
  132. {
  133. if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND) {
  134. if (m_pParent != NULL) m_pParent->DoEvent(event);
  135. else CVerticalLayoutUI::DoEvent(event);
  136. return;
  137. }
  138. if (event.Type == UIEVENT_TIMER && event.wParam == SCROLL_TIMERID) {
  139. if (m_dwDelayLeft > 0) {
  140. --m_dwDelayLeft;
  141. SIZE sz = GetScrollPos();
  142. LONG lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
  143. if ((lDeltaY > 0 && sz.cy != 0) || (lDeltaY < 0 && sz.cy != GetScrollRange().cy)) {
  144. sz.cy -= lDeltaY;
  145. SetScrollPos(sz);
  146. return;
  147. }
  148. }
  149. m_dwDelayDeltaY = 0;
  150. m_dwDelayNum = 0;
  151. m_dwDelayLeft = 0;
  152. m_pManager->KillTimer(this, SCROLL_TIMERID);
  153. return;
  154. }
  155. if (event.Type == UIEVENT_SCROLLWHEEL) {
  156. LONG lDeltaY = 0;
  157. if (m_dwDelayNum > 0) lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
  158. switch (LOWORD(event.wParam)) {
  159. case SB_LINEUP:
  160. if (m_dwDelayDeltaY >= 0) m_dwDelayDeltaY = lDeltaY + 8;
  161. else m_dwDelayDeltaY = lDeltaY + 12;
  162. break;
  163. case SB_LINEDOWN:
  164. if (m_dwDelayDeltaY <= 0) m_dwDelayDeltaY = lDeltaY - 8;
  165. else m_dwDelayDeltaY = lDeltaY - 12;
  166. break;
  167. }
  168. if (m_dwDelayDeltaY > 100) m_dwDelayDeltaY = 100;
  169. else if (m_dwDelayDeltaY < -100) m_dwDelayDeltaY = -100;
  170. m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
  171. m_dwDelayLeft = m_dwDelayNum;
  172. m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
  173. return;
  174. }
  175. CListUI::DoEvent(event);
  176. }
  177. Node* GetRoot() { return _root; }
  178. Node* AddNode(LPCTSTR text, Node* parent = NULL)
  179. {
  180. if (!parent) parent = _root;
  181. CListLabelElementUI* pListElement = new CListLabelElementUI;
  182. Node* node = new Node;
  183. node->data()._level = parent->data()._level + 1;
  184. if (node->data()._level == 0) node->data()._expand = true;
  185. else node->data()._expand = false;
  186. node->data()._text = text;
  187. node->data()._pListElement = pListElement;
  188. if (parent != _root) {
  189. if (!(parent->data()._expand && parent->data()._pListElement->IsVisible()))
  190. pListElement->SetInternVisible(false);
  191. }
  192. CDuiString html_text;
  193. html_text += _T("<x 6>");
  194. for (int i = 0; i < node->data()._level; ++i) {
  195. html_text += _T("<x 24>");
  196. }
  197. if (node->data()._level < 3) {
  198. if (node->data()._expand) html_text += _T("<v center><a><i tree_expand.png 2 1></a></v>");
  199. else html_text += _T("<v center><a><i tree_expand.png 2 0></a></v>");
  200. }
  201. html_text += node->data()._text;
  202. pListElement->SetText(html_text);
  203. //if( node->data()._level == 0 ) pListElement->SetFixedHeight(28);
  204. //else pListElement->SetFixedHeight(24);
  205. pListElement->SetTag((UINT_PTR)node);
  206. if (node->data()._level == 0) {
  207. pListElement->SetBkImage(_T("file='tree_top.png' corner='2,1,2,1' fade='100'"));
  208. }
  209. int index = 0;
  210. if (parent->has_children()) {
  211. Node* prev = parent->get_last_child();
  212. index = prev->data()._pListElement->GetIndex() + 1;
  213. }
  214. else {
  215. if (parent == _root) index = 0;
  216. else index = parent->data()._pListElement->GetIndex() + 1;
  217. }
  218. if (!CListUI::AddAt(pListElement, index)) {
  219. delete pListElement;
  220. delete node;
  221. node = NULL;
  222. }
  223. parent->add_child(node);
  224. return node;
  225. }
  226. bool RemoveNode(Node* node)
  227. {
  228. if (!node || node == _root) return false;
  229. for (int i = 0; i < node->num_children(); ++i) {
  230. Node* child = node->child(i);
  231. RemoveNode(child);
  232. }
  233. CListUI::Remove(node->data()._pListElement);
  234. node->parent()->remove_child(node);
  235. delete node;
  236. return true;
  237. }
  238. void ExpandNode(Node* node, bool expand)
  239. {
  240. if (!node || node == _root) return;
  241. if (node->data()._expand == expand) return;
  242. node->data()._expand = expand;
  243. CDuiString html_text;
  244. html_text += _T("<x 6>");
  245. for (int i = 0; i < node->data()._level; ++i) {
  246. html_text += _T("<x 24>");
  247. }
  248. if (node->data()._level < 3) {
  249. if (node->data()._expand) html_text += _T("<v center><a><i tree_expand.png 2 1></a></v>");
  250. else html_text += _T("<v center><a><i tree_expand.png 2 0></a></v>");
  251. }
  252. html_text += node->data()._text;
  253. node->data()._pListElement->SetText(html_text);
  254. if (!node->data()._pListElement->IsVisible()) return;
  255. if (!node->has_children()) return;
  256. Node* begin = node->child(0);
  257. Node* end = node->get_last_child();
  258. for (int i = begin->data()._pListElement->GetIndex(); i <= end->data()._pListElement->GetIndex(); ++i) {
  259. CControlUI* control = GetItemAt(i);
  260. if (_tcscmp(control->GetClass(), DUI_CTR_LISTLABELELEMENT) == 0) {
  261. Node* local_parent = ((GameListUI::Node*)control->GetTag())->parent();
  262. control->SetInternVisible(local_parent->data()._expand && local_parent->data()._pListElement->IsVisible());
  263. }
  264. }
  265. NeedUpdate();
  266. }
  267. SIZE GetExpanderSizeX(Node* node) const
  268. {
  269. if (!node || node == _root) return CDuiSize();
  270. if (node->data()._level >= 3) return CDuiSize();
  271. SIZE szExpander = { 0 };
  272. szExpander.cx = 6 + 24 * node->data()._level - 4/*适当放大一点*/;
  273. szExpander.cy = szExpander.cx + 16 + 8/*适当放大一点*/;
  274. return szExpander;
  275. }
  276. private:
  277. Node* _root;
  278. LONG m_dwDelayDeltaY;
  279. DWORD m_dwDelayNum;
  280. DWORD m_dwDelayLeft;
  281. };
  282. class DeskListUI : public CTileLayoutUI
  283. {
  284. public:
  285. enum { SCROLL_TIMERID = 10 };
  286. DeskListUI() : m_uButtonState(0), m_dwDelayDeltaY(0), m_dwDelayNum(0), m_dwDelayLeft(0)
  287. {
  288. SetItemSize(CDuiSize(182, 152));
  289. CDialogBuilder builder;
  290. CContainerUI* pDesk = static_cast<CContainerUI*>(builder.Create(_T("desk.xml"), (UINT)0));
  291. if (pDesk != NULL) {
  292. for (int i = 0; i < 500; ++i)
  293. {
  294. if (pDesk == NULL) pDesk = static_cast<CContainerUI*>(builder.Create());
  295. if (pDesk != NULL) {
  296. this->Add(pDesk);
  297. TCHAR indexBuffer[16];
  298. CDuiString strIndexString = _T("- ");
  299. strIndexString += _itot(i + 1, indexBuffer, 10);
  300. strIndexString += _T(" -");
  301. pDesk->GetItemAt(3)->SetText(strIndexString);
  302. pDesk = NULL;
  303. }
  304. else {
  305. this->RemoveAll();
  306. return;
  307. }
  308. }
  309. }
  310. }
  311. void DoEvent(TEventUI& event)
  312. {
  313. if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND) {
  314. if (m_pParent != NULL) m_pParent->DoEvent(event);
  315. else CTileLayoutUI::DoEvent(event);
  316. return;
  317. }
  318. if (event.Type == UIEVENT_TIMER && event.wParam == SCROLL_TIMERID)
  319. {
  320. if ((m_uButtonState & UISTATE_CAPTURED) != 0) {
  321. POINT pt = m_pManager->GetMousePos();
  322. LONG cy = (pt.y - m_ptLastMouse.y);
  323. m_ptLastMouse = pt;
  324. SIZE sz = GetScrollPos();
  325. sz.cy -= cy;
  326. SetScrollPos(sz);
  327. return;
  328. }
  329. else if (m_dwDelayLeft > 0) {
  330. --m_dwDelayLeft;
  331. SIZE sz = GetScrollPos();
  332. LONG lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
  333. if ((lDeltaY > 0 && sz.cy != 0) || (lDeltaY < 0 && sz.cy != GetScrollRange().cy)) {
  334. sz.cy -= lDeltaY;
  335. SetScrollPos(sz);
  336. return;
  337. }
  338. }
  339. m_dwDelayDeltaY = 0;
  340. m_dwDelayNum = 0;
  341. m_dwDelayLeft = 0;
  342. m_pManager->KillTimer(this, SCROLL_TIMERID);
  343. return;
  344. }
  345. if (event.Type == UIEVENT_BUTTONDOWN && IsEnabled())
  346. {
  347. m_uButtonState |= UISTATE_CAPTURED;
  348. m_ptLastMouse = event.ptMouse;
  349. m_dwDelayDeltaY = 0;
  350. m_dwDelayNum = 0;
  351. m_dwDelayLeft = 0;
  352. ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));
  353. m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
  354. return;
  355. }
  356. if (event.Type == UIEVENT_BUTTONUP)
  357. {
  358. if ((m_uButtonState & UISTATE_CAPTURED) != 0) {
  359. m_uButtonState &= ~UISTATE_CAPTURED;
  360. ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
  361. if (m_ptLastMouse.y != event.ptMouse.y) {
  362. m_dwDelayDeltaY = (event.ptMouse.y - m_ptLastMouse.y);
  363. if (m_dwDelayDeltaY > 120) m_dwDelayDeltaY = 120;
  364. else if (m_dwDelayDeltaY < -120) m_dwDelayDeltaY = -120;
  365. m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
  366. m_dwDelayLeft = m_dwDelayNum;
  367. }
  368. else
  369. m_pManager->KillTimer(this, SCROLL_TIMERID);
  370. }
  371. return;
  372. }
  373. if (event.Type == UIEVENT_SCROLLWHEEL)
  374. {
  375. LONG lDeltaY = 0;
  376. if (m_dwDelayNum > 0) lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
  377. switch (LOWORD(event.wParam)) {
  378. case SB_LINEUP:
  379. if (m_dwDelayDeltaY >= 0) m_dwDelayDeltaY = lDeltaY + 8;
  380. else m_dwDelayDeltaY = lDeltaY + 12;
  381. break;
  382. case SB_LINEDOWN:
  383. if (m_dwDelayDeltaY <= 0) m_dwDelayDeltaY = lDeltaY - 8;
  384. else m_dwDelayDeltaY = lDeltaY - 12;
  385. break;
  386. }
  387. if (m_dwDelayDeltaY > 100) m_dwDelayDeltaY = 100;
  388. else if (m_dwDelayDeltaY < -100) m_dwDelayDeltaY = -100;
  389. m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
  390. m_dwDelayLeft = m_dwDelayNum;
  391. m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
  392. return;
  393. }
  394. CTileLayoutUI::DoEvent(event);
  395. }
  396. private:
  397. UINT m_uButtonState;
  398. POINT m_ptLastMouse;
  399. LONG m_dwDelayDeltaY;
  400. DWORD m_dwDelayNum;
  401. DWORD m_dwDelayLeft;
  402. };
  403. class CDialogBuilderCallbackEx : public IDialogBuilderCallback
  404. {
  405. public:
  406. CControlUI* CreateControl(LPCTSTR pstrClass)
  407. {
  408. if (_tcscmp(pstrClass, _T("GameList")) == 0) return new GameListUI;
  409. else if (_tcscmp(pstrClass, _T("DeskList")) == 0) return new DeskListUI;
  410. return NULL;
  411. }
  412. };
  413. #endif __CONTROLEX_H__