RollupCtrl.cpp
上传用户:sunh8215
上传日期:2010-02-13
资源大小:1616k
文件大小:25k
源码类别:

酒店行业

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // RollupCtrl.cpp
  4. // 
  5. // Code Johann Nadalutti
  6. // Mail: jnadalutti@worldonline.fr
  7. //
  8. //////////////////////////////////////////////////////////////////////////////
  9. //
  10. // This code is free for personal and commercial use, providing this 
  11. // notice remains intact in the source files and all eventual changes are
  12. // clearly marked with comments.
  13. //
  14. // No warrantee of any kind, express or implied, is included with this
  15. // software; use at your own risk, responsibility for damages (if any) to
  16. // anyone resulting from the use of this software rests entirely with the
  17. // user.
  18. //
  19. //////////////////////////////////////////////////////////////////////////////
  20. //
  21. // History
  22. // --------
  23. // #v1.0
  24. // 31/03/01: Created
  25. //
  26. // #v1.01
  27. // 13/04/01: Added ScrollToPage() method
  28. // Added automatic page visibility to ExpandPage() method
  29. // Added Mousewheel support
  30. // 15/04/01: Added mouse capture checking on WM_MOUSEMOVE dialog msg
  31. // Added SetCursor() on Dialog WM_SETCURSOR
  32. // Added MovePageAt() method
  33. // 17/04/01: Fixed Group Boxes displayed over Buttons
  34. // 20/04/01: Added IsPageExpanded() and IsPageExpanded() methods
  35. // Added PopupMenu
  36. // Added Button subclassing (now button's focus not drawn)
  37. //
  38. // Note
  39. // -----
  40. // Dialog box width is
  41. // RollupCtrlClientRect.Width() - RC_SCROLLBARWIDTH - (RC_GRPBOXINDENT*2)
  42. //
  43. //
  44. // Thanks to
  45. // ----------
  46. // PJ Arends, Ramon Smits, Uwe Keim, Daniel Madden, Do Quyet Tien,
  47. // Ravi Bhavnani, Masaaki Onishi, ...
  48. // and all others users for their comments.
  49. //
  50. /////////////////////////////////////////////////////////////////////////////
  51. /////////////////////////////////////////////////////////////////////////////
  52. // CRollupCtrl Includes
  53. #include "stdafx.h"
  54. #include "RollupCtrl.h"
  55. /////////////////////////////////////////////////////////////////////////////
  56. #ifdef _DEBUG
  57. #define new DEBUG_NEW
  58. #undef THIS_FILE
  59. static char THIS_FILE[] = __FILE__;
  60. #endif
  61. /////////////////////////////////////////////////////////////////////////////
  62. // CRollupCtrl Message Map
  63. BEGIN_MESSAGE_MAP(CRollupCtrl, CWnd)
  64. //{{AFX_MSG_MAP(CRollupCtrl)
  65. ON_WM_PAINT()
  66. ON_WM_SIZE()
  67. ON_WM_LBUTTONDOWN()
  68. ON_WM_LBUTTONUP()
  69. ON_WM_MOUSEMOVE()
  70. ON_WM_MOUSEWHEEL()
  71. ON_WM_MOUSEACTIVATE()
  72. ON_WM_CONTEXTMENU()
  73. //}}AFX_MSG_MAP
  74. END_MESSAGE_MAP()
  75. /////////////////////////////////////////////////////////////////////////////
  76. // CRollupCtrl Implementation
  77. IMPLEMENT_DYNCREATE(CRollupCtrl, CWnd)
  78. //---------------------------------------------------------------------------
  79. // Constructor
  80. //---------------------------------------------------------------------------
  81. CRollupCtrl::CRollupCtrl()
  82. {
  83. m_strMyClass = AfxRegisterWndClass(
  84. CS_VREDRAW | CS_HREDRAW,
  85. (HCURSOR)::LoadCursor(NULL, IDC_ARROW),
  86. (HBRUSH)COLOR_WINDOW,
  87. NULL);
  88. m_nStartYPos = m_nPageHeight = 0;
  89. }
  90. //---------------------------------------------------------------------------
  91. // Destructor
  92. //---------------------------------------------------------------------------
  93. CRollupCtrl::~CRollupCtrl()
  94. {
  95. //Remove all pages allocations
  96. for (int i=0; i<m_PageList.GetSize(); i++) {
  97. if (m_PageList[i]->pwndButton) delete m_PageList[i]->pwndButton;
  98. if (m_PageList[i]->pwndGroupBox) delete m_PageList[i]->pwndGroupBox;
  99. if (m_PageList[i]->pwndTemplate && m_PageList[i]->bAutoDestroyTpl) {
  100. m_PageList[i]->pwndTemplate->DestroyWindow();
  101. delete m_PageList[i]->pwndTemplate;
  102. }
  103. delete m_PageList[i];
  104. }
  105. }
  106. //---------------------------------------------------------------------------
  107. // Create
  108. //---------------------------------------------------------------------------
  109. BOOL CRollupCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
  110. {
  111. return  CWnd::Create(m_strMyClass, "RollupCtrl", dwStyle, rect, pParentWnd, nID);
  112. }
  113. //---------------------------------------------------------------------------
  114. // Function name : InsertPage
  115. // Description : Return -1 if an error occurs
  116. //   Make sure template had WS_CHILD style
  117. //---------------------------------------------------------------------------
  118. int CRollupCtrl::InsertPage(LPCTSTR caption, UINT nIDTemplate, CRuntimeClass* rtc, int idx)
  119. {
  120. if (idx>0 && idx>=m_PageList.GetSize()) idx=-1;
  121. //Create Template
  122. ASSERT(rtc!=NULL);
  123. CDialog* pwndTemplate = (CDialog*)rtc->CreateObject();
  124. BOOL b = pwndTemplate->Create(nIDTemplate, this);
  125. if (!b) { delete pwndTemplate; return -1; }
  126. //Insert Page
  127. return _InsertPage(caption, pwndTemplate, idx, TRUE);
  128. }
  129. //---------------------------------------------------------------------------
  130. // Function name : InsertPage
  131. // Description : return -1 if an error occurs
  132. //   Make sure template had WS_CHILD style
  133. //---------------------------------------------------------------------------
  134. int CRollupCtrl::InsertPage(LPCTSTR caption, CDialog* pwndTemplate, BOOL bAutoDestroyTpl, int idx)
  135. {
  136. if (!pwndTemplate) return -1;
  137. if (idx>0 && idx>=m_PageList.GetSize()) idx=-1;
  138. //Insert Page
  139. return _InsertPage(caption, pwndTemplate, idx, bAutoDestroyTpl);
  140. }
  141. //---------------------------------------------------------------------------
  142. // Function name : InsertPage
  143. // Description : Called by InsertPage(...) methods
  144. //   Return -1 if an error occurs
  145. //   Make sure template had WS_CHILD style
  146. //---------------------------------------------------------------------------
  147. int CRollupCtrl::_InsertPage(LPCTSTR caption, CDialog* pwndTemplate, int idx, BOOL bAutoDestroyTpl)
  148. {
  149. ASSERT(pwndTemplate!=NULL);
  150. ASSERT(pwndTemplate->m_hWnd!=NULL);
  151.   //Get client rect
  152. CRect r; GetClientRect(r);
  153. //Create GroupBox
  154. CButton* groupbox = new CButton;
  155. groupbox->Create("", WS_CHILD|BS_GROUPBOX, r, this, 0 );
  156. //Create Button
  157. CButton* but = new CButton;
  158. but->Create(caption, WS_CHILD|BS_AUTOCHECKBOX|BS_PUSHLIKE|BS_FLAT, r, this, 0 ); 
  159. //Change Button's font
  160. HFONT hfont= (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
  161. CFont* font = CFont::FromHandle(hfont);
  162. but->SetFont(font);
  163. //Add page at pagelist
  164. RC_PAGEINFO* pi = new RC_PAGEINFO;
  165. pi->bExpanded = FALSE;
  166. pi->bEnable = TRUE;
  167. pi->pwndTemplate = pwndTemplate;
  168. pi->pwndButton = but;
  169. pi->pwndGroupBox = groupbox;
  170. pi->pOldDlgProc = (WNDPROC)::GetWindowLong(pwndTemplate->m_hWnd, DWL_DLGPROC);
  171. pi->pOldButProc = (WNDPROC)::GetWindowLong(but->m_hWnd, GWL_WNDPROC);
  172. pi->bAutoDestroyTpl = bAutoDestroyTpl;
  173. int newidx;
  174. if (idx<0) newidx = m_PageList.Add(pi);
  175. else { m_PageList.InsertAt(idx, pi); newidx=idx; }
  176. //Set Dlg Window datas
  177. ::SetWindowLong(pwndTemplate->m_hWnd, GWL_USERDATA, (LONG)m_PageList[newidx]);
  178. ::SetWindowLong(pwndTemplate->m_hWnd, DWL_USER, (LONG)this);
  179. //Set But Window data
  180. ::SetWindowLong(but->m_hWnd, GWL_USERDATA, (LONG)m_PageList[newidx]);
  181. //SubClass Template window proc
  182. ::SetWindowLong(pwndTemplate->m_hWnd, DWL_DLGPROC, (LONG)CRollupCtrl::DlgWindowProc);
  183. //SubClass Button window proc
  184. ::SetWindowLong(but->m_hWnd, GWL_WNDPROC, (LONG)CRollupCtrl::ButWindowProc);
  185. //Update
  186. m_nPageHeight+=RC_PGBUTTONHEIGHT+(RC_GRPBOXINDENT/2);
  187. RecalLayout();
  188. return newidx;
  189. }
  190. //---------------------------------------------------------------------------
  191. // Function name : RemovePage
  192. // Description : 
  193. //---------------------------------------------------------------------------
  194. void CRollupCtrl::RemovePage(int idx)
  195. {
  196. if (idx>=m_PageList.GetSize() || idx<0) return;
  197. //Remove
  198. _RemovePage(idx);
  199. //Update
  200. RecalLayout();
  201. }
  202. //---------------------------------------------------------------------------
  203. // Function name : RemoveAllPages
  204. // Description :
  205. //---------------------------------------------------------------------------
  206. void CRollupCtrl::RemoveAllPages()
  207. {
  208. //Remove all
  209. for (; m_PageList.GetSize();)
  210. _RemovePage(0);
  211. //Update
  212. RecalLayout();
  213. }
  214. //---------------------------------------------------------------------------
  215. // Function name : _RemovePage
  216. // Description : Called by RemovePage or RemoveAllPages methods
  217. //---------------------------------------------------------------------------
  218. void CRollupCtrl::_RemovePage(int idx)
  219. {
  220. RC_PAGEINFO* pi = m_PageList[idx];
  221. //Get Page Rect
  222. CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
  223. //Update PageHeight
  224. m_nPageHeight-=RC_PGBUTTONHEIGHT+(RC_GRPBOXINDENT/2);
  225. if (pi->bExpanded) m_nPageHeight-=tr.Height();
  226. //Remove wnds
  227. if (pi->pwndButton) delete pi->pwndButton;
  228. if (pi->pwndGroupBox) delete pi->pwndGroupBox;
  229. if (pi->pwndTemplate && pi->bAutoDestroyTpl) {
  230. pi->pwndTemplate->DestroyWindow();
  231. delete pi->pwndTemplate;
  232. }
  233. //Remove page from array
  234. m_PageList.RemoveAt(idx);
  235. //Delete pageinfo
  236. delete pi;
  237. }
  238. //---------------------------------------------------------------------------
  239. // Function name : ExpandPage
  240. // Description :
  241. //---------------------------------------------------------------------------
  242. void CRollupCtrl::ExpandPage(int idx, BOOL bExpand)
  243. {
  244. if (idx>=m_PageList.GetSize() || idx<0) return;
  245. //Expand-collapse
  246. _ExpandPage(m_PageList[idx], bExpand);
  247. //Update
  248. RecalLayout();
  249. //Scroll to this page (Automatic page visibility)
  250. if (bExpand) ScrollToPage(idx, FALSE);
  251. }
  252. //---------------------------------------------------------------------------
  253. // Function name : ExpandAllPages
  254. // Description : 
  255. //---------------------------------------------------------------------------
  256. void CRollupCtrl::ExpandAllPages(BOOL bExpand)
  257. {
  258. //Expand-collapse All
  259. for (int i=0; i<m_PageList.GetSize(); i++)
  260. _ExpandPage(m_PageList[i], bExpand);
  261. //Update
  262. RecalLayout();
  263. }
  264. //---------------------------------------------------------------------------
  265. // Function name : _ExpandPage
  266. // Description : Called by ExpandPage or ExpandAllPages methods
  267. //---------------------------------------------------------------------------
  268. void CRollupCtrl::_ExpandPage(RC_PAGEINFO* pi, BOOL bExpand)
  269. {
  270. //Check if we need to change state
  271. if (pi->bExpanded==bExpand) return;
  272. if (!pi->bEnable) return;
  273. //Get Page Rect
  274. CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
  275. //Expand-collapse
  276. pi->bExpanded = bExpand;
  277. if (bExpand) m_nPageHeight+=tr.Height();
  278. else m_nPageHeight-=tr.Height();
  279. }
  280. //---------------------------------------------------------------------------
  281. // Function name : EnablePage
  282. // Description : 
  283. //---------------------------------------------------------------------------
  284. void CRollupCtrl::EnablePage(int idx, BOOL bEnable)
  285. {
  286. if (idx>=m_PageList.GetSize() || idx<0) return;
  287. //Enable-Disable
  288. _EnablePage(m_PageList[idx], bEnable);
  289. //Update
  290. RecalLayout();
  291. }
  292. //---------------------------------------------------------------------------
  293. // Function name : EnableAllPages
  294. // Description : 
  295. //---------------------------------------------------------------------------
  296. void CRollupCtrl::EnableAllPages(BOOL bEnable)
  297. {
  298. //Enable-disable All
  299. for (int i=0; i<m_PageList.GetSize(); i++)
  300. _EnablePage(m_PageList[i], bEnable);
  301. //Update
  302. RecalLayout();
  303. }
  304. //---------------------------------------------------------------------------
  305. // Function name : _EnablePage
  306. // Description : Called by EnablePage or EnableAllPages methods
  307. //---------------------------------------------------------------------------
  308. void CRollupCtrl::_EnablePage(RC_PAGEINFO* pi, BOOL bEnable)
  309. {
  310. //Check if we need to change state
  311. if (pi->bEnable==bEnable) return;
  312. //Get Page Rect
  313. CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
  314. //Change state
  315. pi->bEnable = bEnable;
  316. if (pi->bExpanded) { m_nPageHeight-=tr.Height(); pi->bExpanded=FALSE; }
  317. }
  318. //---------------------------------------------------------------------------
  319. // Function name : ScrollToPage
  320. // Description : Scroll a page at the top of the RollupCtrl if bAtTheTop=TRUE
  321. //   or just ensure page visibility into view if bAtTheTop=FALSE
  322. //---------------------------------------------------------------------------
  323. void CRollupCtrl::ScrollToPage(int idx, BOOL bAtTheTop)
  324. {
  325. if (idx>=m_PageList.GetSize() || idx<0) return;
  326. //Get page infos
  327. RC_PAGEINFO* pi = m_PageList[idx];
  328. //Get windows rect
  329. CRect r; GetWindowRect(&r);
  330. CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
  331. //Check page visibility
  332. if (bAtTheTop || ((tr.bottom>r.bottom) || (tr.top<r.top)))
  333. {
  334. //Compute new m_nStartYPos
  335. pi->pwndButton->GetWindowRect(&tr);
  336. m_nStartYPos-= (tr.top-r.top);
  337. //Update
  338. RecalLayout();
  339. }
  340. }
  341. //---------------------------------------------------------------------------
  342. // Function name : MovePageAt
  343. // Description : newidx can be equal to -1 (move at end)
  344. //   Return -1 if an error occurs
  345. //---------------------------------------------------------------------------
  346. int CRollupCtrl::MovePageAt(int idx, int newidx)
  347. {
  348. if (idx==newidx) return -1;
  349. if (idx>=m_PageList.GetSize() || idx<0) return -1;
  350. if (newidx>0 && newidx>=m_PageList.GetSize()) newidx=-1;
  351. //Remove page from its old position
  352. RC_PAGEINFO* pi = m_PageList[idx];
  353. m_PageList.RemoveAt(idx);
  354. //Insert at its new position
  355. int retidx;
  356. if (newidx<0) retidx = m_PageList.Add(pi);
  357. else { m_PageList.InsertAt(newidx, pi); retidx=newidx; }
  358. //Update
  359. RecalLayout();
  360. return retidx;
  361. }
  362. //---------------------------------------------------------------------------
  363. // Function name : IsPageExpanded
  364. // Description : 
  365. //---------------------------------------------------------------------------
  366. BOOL CRollupCtrl::IsPageExpanded(int idx)
  367. {
  368. if (idx>=m_PageList.GetSize() || idx<0) return FALSE;
  369. return m_PageList[idx]->bExpanded;
  370. }
  371. //---------------------------------------------------------------------------
  372. // Function name : IsPageEnabled
  373. // Description : 
  374. //---------------------------------------------------------------------------
  375. BOOL CRollupCtrl::IsPageEnabled(int idx)
  376. {
  377. if (idx>=m_PageList.GetSize() || idx<0) return FALSE;
  378. return m_PageList[idx]->bEnable;
  379. }
  380. //---------------------------------------------------------------------------
  381. // Function name : RecalLayout
  382. // Description : 
  383. //---------------------------------------------------------------------------
  384. void CRollupCtrl::RecalLayout()
  385. {
  386. //Check StartPosY
  387. CRect r; GetClientRect(&r);
  388. int BottomPagePos = m_nStartYPos+m_nPageHeight;
  389. if (BottomPagePos<r.Height()) m_nStartYPos = r.Height()-m_nPageHeight;
  390. if (m_nStartYPos>0) m_nStartYPos = 0;
  391. //Update layout
  392. HDWP hdwp = BeginDeferWindowPos(m_PageList.GetSize()*3); //*3 for pwndButton+pwndTemplate+pwndGroupBox
  393. int posy=m_nStartYPos;
  394. for (int i=0; i<m_PageList.GetSize(); i++){
  395. RC_PAGEINFO* pi = m_PageList[i];
  396. //Enable-Disable Button
  397. pi->pwndButton->SetCheck(pi->bEnable&pi->bExpanded);
  398. pi->pwndButton->EnableWindow(pi->bEnable);
  399. //Expanded
  400. if (pi->bExpanded && pi->bEnable) {
  401. CRect tr; pi->pwndTemplate->GetWindowRect(&tr);
  402. //Update GroupBox position and size
  403. DeferWindowPos(hdwp, pi->pwndGroupBox->m_hWnd, 0, 2, posy, r.Width()-3-RC_SCROLLBARWIDTH, tr.Height()+RC_PGBUTTONHEIGHT+RC_GRPBOXINDENT-4, SWP_NOZORDER|SWP_SHOWWINDOW);
  404. //Update Template position and size
  405. DeferWindowPos(hdwp, pi->pwndTemplate->m_hWnd, 0, RC_GRPBOXINDENT, posy+RC_PGBUTTONHEIGHT, r.Width()-RC_SCROLLBARWIDTH-(RC_GRPBOXINDENT*2), tr.Height(), SWP_NOZORDER|SWP_SHOWWINDOW);
  406. //Update Button's position and size
  407. DeferWindowPos(hdwp, pi->pwndButton->m_hWnd, 0, RC_GRPBOXINDENT, posy, r.Width()-RC_SCROLLBARWIDTH-(RC_GRPBOXINDENT*2), RC_PGBUTTONHEIGHT, SWP_NOZORDER|SWP_SHOWWINDOW);
  408. posy+=tr.Height()+RC_PGBUTTONHEIGHT;
  409. //Collapsed
  410. } else {
  411. //Update GroupBox position and size
  412. DeferWindowPos(hdwp, pi->pwndGroupBox->m_hWnd, 0, 2, posy, r.Width()-3-RC_SCROLLBARWIDTH, 16,SWP_NOZORDER|SWP_SHOWWINDOW);
  413. //Update Template position and size
  414. DeferWindowPos(hdwp, pi->pwndTemplate->m_hWnd, 0, RC_GRPBOXINDENT, 0, 0, 0,SWP_NOZORDER|SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
  415. //Update Button's position and size
  416. DeferWindowPos(hdwp, pi->pwndButton->m_hWnd, 0, RC_GRPBOXINDENT, posy, r.Width()-RC_SCROLLBARWIDTH-(RC_GRPBOXINDENT*2), RC_PGBUTTONHEIGHT, SWP_NOZORDER|SWP_SHOWWINDOW);
  417. posy+=RC_PGBUTTONHEIGHT;
  418. }
  419. posy+=(RC_GRPBOXINDENT/2);
  420. }
  421. EndDeferWindowPos(hdwp);
  422. //Update Scroll Bar
  423. CRect br = CRect(r.right-RC_SCROLLBARWIDTH,r.top, r.right, r.bottom);
  424. InvalidateRect(&br, FALSE);
  425. UpdateWindow();
  426. }
  427. //---------------------------------------------------------------------------
  428. // Function name : GetPageIdxFromButtonHWND
  429. // Description : Return -1 if matching hwnd not found
  430. //---------------------------------------------------------------------------
  431. int CRollupCtrl::GetPageIdxFromButtonHWND(HWND hwnd)
  432. {
  433. //Search matching button's hwnd
  434. for (int i=0; i<m_PageList.GetSize(); i++)
  435. if (hwnd==m_PageList[i]->pwndButton->m_hWnd) return i;
  436. return -1;
  437. }
  438. //---------------------------------------------------------------------------
  439. // Function name : GetPageInfo
  440. // Description : Return -1 if an error occurs
  441. //---------------------------------------------------------------------------
  442. RC_PAGEINFO* CRollupCtrl::GetPageInfo(int idx)
  443. {
  444. if (idx>=m_PageList.GetSize() || idx<0) return (RC_PAGEINFO*)-1;
  445. return m_PageList[idx];
  446. }
  447. //---------------------------------------------------------------------------
  448. // Dialog SubClasser
  449. //---------------------------------------------------------------------------
  450. LRESULT CALLBACK CRollupCtrl::DlgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  451. {
  452. RC_PAGEINFO* pi = (RC_PAGEINFO*)GetWindowLong(hWnd, GWL_USERDATA);
  453. CRollupCtrl* _this = (CRollupCtrl*)GetWindowLong(hWnd, DWL_USER);
  454. CRect r; _this->GetClientRect(&r);
  455. if (_this->m_nPageHeight>r.Height()) //Can Scroll ?
  456. {
  457. switch (uMsg) {
  458. case WM_LBUTTONDOWN:
  459. case WM_MBUTTONDOWN:
  460. {
  461. CPoint pos; GetCursorPos(&pos);
  462. _this->m_nOldMouseYPos = pos.y;
  463. ::SetCapture(hWnd);
  464. return 0;
  465. }
  466. case WM_LBUTTONUP:
  467. case WM_MBUTTONUP:
  468. {
  469. if (::GetCapture() == hWnd) { ::ReleaseCapture(); return 0; }
  470. break;
  471. }
  472. case WM_MOUSEMOVE:
  473. {
  474. if ((::GetCapture() == hWnd) && (wParam==MK_LBUTTON || wParam==MK_MBUTTON)) {
  475. CPoint pos; GetCursorPos(&pos);
  476. _this->m_nStartYPos+=(pos.y-_this->m_nOldMouseYPos);
  477. _this->RecalLayout();
  478. _this->m_nOldMouseYPos = pos.y;
  479. return 0;
  480. }
  481. break;
  482. }
  483. case WM_SETCURSOR:
  484. if ((HWND)wParam==hWnd) { ::SetCursor(::LoadCursor(NULL, RC_ROLLCURSOR)); return TRUE; }
  485. break;
  486. }//switch(uMsg)
  487. }
  488. return ::CallWindowProc(pi->pOldDlgProc, hWnd, uMsg, wParam, lParam);
  489. }
  490. //---------------------------------------------------------------------------
  491. // Button SubClasser
  492. //---------------------------------------------------------------------------
  493. LRESULT CALLBACK CRollupCtrl::ButWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  494. {
  495. if (uMsg==WM_SETFOCUS) return FALSE;
  496. RC_PAGEINFO* pi = (RC_PAGEINFO*)GetWindowLong(hWnd, GWL_USERDATA);
  497. return ::CallWindowProc(pi->pOldButProc, hWnd, uMsg, wParam, lParam);
  498. }
  499. /////////////////////////////////////////////////////////////////////////////
  500. // CRollupCtrl message handlers
  501. //---------------------------------------------------------------------------
  502. // OnCommand
  503. //---------------------------------------------------------------------------
  504. BOOL CRollupCtrl::OnCommand(WPARAM wParam, LPARAM lParam) 
  505. {
  506. //PopupMenu command ExpandAllPages
  507. if (LOWORD(wParam)==RC_IDM_EXPANDALL) ExpandAllPages(TRUE);
  508. else if (LOWORD(wParam)==RC_IDM_COLLAPSEALL) ExpandAllPages(FALSE);
  509. //PopupMenu command ExpandPage
  510. else if (LOWORD(wParam)>=RC_IDM_STARTPAGES
  511. &&  LOWORD(wParam)<RC_IDM_STARTPAGES+GetPagesCount())
  512. {
  513. int idx = LOWORD(wParam)-RC_IDM_STARTPAGES;
  514. ExpandPage(idx, !IsPageExpanded(idx) );
  515. }
  516. //Button command
  517. else if (HIWORD(wParam)==BN_CLICKED)
  518. {
  519. int idx = GetPageIdxFromButtonHWND((HWND)lParam);
  520. if (idx!=-1) {
  521. RC_PAGEINFO* pi = m_PageList[idx];
  522. ExpandPage(idx, !pi->bExpanded);
  523. return 0;
  524. }
  525. }
  526. return CWnd::OnCommand(wParam, lParam);
  527. }
  528. //---------------------------------------------------------------------------
  529. // OnPaint
  530. //---------------------------------------------------------------------------
  531. void CRollupCtrl::OnPaint() 
  532. {
  533. CPaintDC dc(this);
  534. //Draw ScrollBar
  535. CRect r; GetClientRect(&r);
  536. CRect br = CRect(r.right-RC_SCROLLBARWIDTH,r.top, r.right, r.bottom);
  537. dc.DrawEdge(&br, EDGE_RAISED, BF_RECT  );
  538. int SB_Pos = 0;
  539. int SB_Size = 0;
  540. int ClientHeight = r.Height()-4;
  541. if (m_nPageHeight>r.Height()) {
  542. SB_Size = ClientHeight-(((m_nPageHeight-r.Height())*ClientHeight)/m_nPageHeight);
  543. SB_Pos = -(m_nStartYPos*ClientHeight)/m_nPageHeight;
  544. } else {
  545. SB_Size = ClientHeight;
  546. }
  547. br.left +=2;
  548. br.right -=1;
  549. br.top = SB_Pos+2;
  550. br.bottom = br.top+SB_Size;
  551. dc.FillSolidRect(&br, RC_SCROLLBARCOLOR);
  552. dc.FillSolidRect(CRect(br.left,2,br.right,br.top), RGB(0,0,0));
  553. dc.FillSolidRect(CRect(br.left,br.bottom,br.right,2+ClientHeight), RGB(0,0,0));
  554. // Do not call CWnd::OnPaint() for painting messages
  555. }
  556. //---------------------------------------------------------------------------
  557. // OnSize
  558. //---------------------------------------------------------------------------
  559. void CRollupCtrl::OnSize(UINT nType, int cx, int cy) 
  560. {
  561. CWnd::OnSize(nType, cx, cy);
  562. RecalLayout();
  563. }
  564. //---------------------------------------------------------------------------
  565. // OnLButtonDown
  566. //---------------------------------------------------------------------------
  567. void CRollupCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  568. {
  569. CRect r; GetClientRect(&r);
  570. if (m_nPageHeight<=r.Height()) return; //Can't Scroll
  571. CRect br = CRect(r.right-RC_SCROLLBARWIDTH,r.top, r.right, r.bottom);
  572. if ((nFlags&MK_LBUTTON) && br.PtInRect(point)) {
  573. SetCapture();
  574. int ClientHeight = r.Height()-4;
  575. int SB_Size = ClientHeight-(((m_nPageHeight-r.Height())*ClientHeight)/m_nPageHeight);
  576. int SB_Pos = -(m_nStartYPos*ClientHeight)/m_nPageHeight;
  577. //Click inside scrollbar cursor
  578. if ((point.y<(SB_Pos+SB_Size)) && (point.y>SB_Pos)) {
  579. m_nSBOffset = SB_Pos-point.y+1;
  580. //Click outside scrollbar cursor (2 cases => above or below cursor)
  581. } else {
  582. int distup = point.y-SB_Pos;
  583. int distdown= (SB_Pos+SB_Size)-point.y;
  584. if (distup<distdown) m_nSBOffset = 0; //above
  585. else m_nSBOffset = -SB_Size; //below
  586. }
  587. //Calc new m_nStartYPos from mouse pos
  588. int TargetPos = point.y + m_nSBOffset;
  589. m_nStartYPos=-(TargetPos*m_nPageHeight)/ClientHeight;
  590. //Update
  591. RecalLayout();
  592. }
  593. CWnd::OnLButtonDown(nFlags, point);
  594. }
  595. //---------------------------------------------------------------------------
  596. // OnLButtonUp
  597. //---------------------------------------------------------------------------
  598. void CRollupCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
  599. {
  600. if (GetCapture()==this) ReleaseCapture();
  601. CWnd::OnLButtonUp(nFlags, point);
  602. }
  603. //---------------------------------------------------------------------------
  604. // OnMouseMove
  605. //---------------------------------------------------------------------------
  606. void CRollupCtrl::OnMouseMove(UINT nFlags, CPoint point) 
  607. {
  608. CRect r; GetClientRect(&r);
  609. if (m_nPageHeight<=r.Height()) return; //Can't Scroll
  610. CRect br = CRect(r.right-RC_SCROLLBARWIDTH,r.top, r.right, r.bottom);
  611. if ((nFlags&MK_LBUTTON) && (GetCapture()==this)) {
  612. //Calc new m_nStartYPos from mouse pos
  613. int ClientHeight = r.Height()-4;
  614. int TargetPos = point.y + m_nSBOffset;
  615. m_nStartYPos=-(TargetPos*m_nPageHeight)/ClientHeight;
  616. //Update
  617. RecalLayout();
  618. }
  619. CWnd::OnMouseMove(nFlags, point);
  620. }
  621. //---------------------------------------------------------------------------
  622. // OnMouseWheel
  623. //---------------------------------------------------------------------------
  624. BOOL CRollupCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
  625. {
  626. //Calc new m_nStartYPos
  627. m_nStartYPos+=(zDelta/4);
  628. //Update
  629. RecalLayout();
  630. return CWnd::OnMouseWheel(nFlags, zDelta, pt);
  631. }
  632. //---------------------------------------------------------------------------
  633. // OnMouseActivate
  634. //---------------------------------------------------------------------------
  635. int CRollupCtrl::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
  636. {
  637. SetFocus();
  638. return CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
  639. }
  640. //---------------------------------------------------------------------------
  641. // OnContextMenu
  642. //---------------------------------------------------------------------------
  643. void CRollupCtrl::OnContextMenu(CWnd* pWnd, CPoint point) 
  644. {
  645. CMenu menu;
  646. if (menu.CreatePopupMenu())
  647. {
  648. menu.AppendMenu(MF_STRING, RC_IDM_EXPANDALL, "Expand all" );
  649. menu.AppendMenu(MF_STRING, RC_IDM_COLLAPSEALL, "Collapse all" );
  650. menu.AppendMenu(MF_SEPARATOR, 0, "" );
  651. //Add all pages with checked style for expanded ones
  652. for (int i=0; i<m_PageList.GetSize(); i++) {
  653. CString cstrPageName;
  654. m_PageList[i]->pwndButton->GetWindowText(cstrPageName);
  655. menu.AppendMenu(MF_STRING, RC_IDM_STARTPAGES+i, cstrPageName);
  656. if (m_PageList[i]->bExpanded)
  657. menu.CheckMenuItem(RC_IDM_STARTPAGES+i, MF_CHECKED);
  658. }
  659. menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON, point.x, point.y, this);
  660. }
  661. }