GfxOutBarCtrl.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /************************************************************************
  2. * 程序名: 精仿QQ主界面
  3. * 制作人: 李克平, 2011年04月11日
  4. * 版本号: 1.0
  5. ************************************************************************/
  6. // GfxOutBarCtrl.cpp : implementation file
  7. //
  8. #include "stdafx.h"
  9. #include "resource.h"
  10. #include "GfxOutBarCtrl.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CGfxOutBarCtrl
  18. IMPLEMENT_DYNCREATE(CGfxOutBarCtrl, CWnd)
  19. CGfxOutBarCtrl::CGfxOutBarCtrl()
  20. {
  21. //背景色
  22. m_crBackground = RGB(255,255,255);
  23. //字体颜色
  24. m_crText = RGB(27,79,116);
  25. //字体
  26. m_pFont = NULL;
  27. //目录高度
  28. nFolderHeight = 20;
  29. //当前选中目录索引
  30. iSelFolder = 1;
  31. //最后高亮的目录索引
  32. iLastFolderHighlighted = -1;
  33. //当前鼠标滑过的目录
  34. iHoverFolder = -1;
  35. hHandCursor = AfxGetApp()->LoadCursor(IDC_CURSOR_HAND);
  36. iSelcon = NULL;
  37. }
  38. CGfxOutBarCtrl::~CGfxOutBarCtrl()
  39. {
  40. for (int t = 0; t < m_arFolder.GetSize(); t++)
  41. {
  42. if (m_arFolder.GetAt(t)) delete (CBm_arFolder*) m_arFolder.GetAt(t);
  43. }
  44. m_arFolder.RemoveAll();
  45. }
  46. BEGIN_MESSAGE_MAP(CGfxOutBarCtrl, CWnd)
  47. //{{AFX_MSG_MAP(CGfxOutBarCtrl)
  48. ON_WM_CREATE()
  49. ON_WM_PAINT()
  50. ON_WM_ERASEBKGND()
  51. ON_WM_LBUTTONDOWN()
  52. ON_WM_SETCURSOR()
  53. ON_WM_SIZE()
  54. //}}AFX_MSG_MAP
  55. ON_WM_MOUSEMOVE()
  56. ON_WM_TIMER()
  57. END_MESSAGE_MAP()
  58. /////////////////////////////////////////////////////////////////////////////
  59. // CGfxOutBarCtrl message handlers
  60. void CGfxOutBarCtrl::SetFolderImage(LPCTSTR lpszPath)
  61. {
  62. CEnBitmap bmpTemp;
  63. bmpTemp.LoadImage(lpszPath);
  64. bmpTemp.DrawImage(m_bmpNormalFolder,1,1,1,2);
  65. bmpTemp.DrawImage(m_bmpHoverFolder,1,2,1,2);
  66. bmpTemp.DeleteObject();
  67. };
  68. void CGfxOutBarCtrl::SetSelIcon(LPCTSTR lpszIconPath)
  69. {
  70. iSelcon=(HICON)::LoadImage(AfxGetApp()->m_hInstance,lpszIconPath,IMAGE_ICON,16,16,LR_LOADFROMFILE);
  71. }
  72. void CGfxOutBarCtrl::SetFolderText(const int index, const char * text)
  73. {
  74. ASSERT(index >= 0 && index < GetFolderCount());
  75. CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(index);
  76. if (pbf->cName)
  77. {
  78. delete [] pbf->cName;
  79. pbf->cName = NULL;
  80. }
  81. pbf->cName = new char [lstrlen(text)+1];
  82. lstrcpy(pbf->cName, text);
  83. }
  84. BOOL CGfxOutBarCtrl::Create(DWORD dwStyle, const RECT & rect, CWnd * pParentWnd, UINT nID)
  85. {
  86. return CWnd::CreateEx(0, NULL, NULL, dwStyle|WS_CHILD, rect, pParentWnd, nID);
  87. }
  88. int CGfxOutBarCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  89. {
  90. if (CWnd::OnCreate(lpCreateStruct) == -1)
  91. return -1;
  92. // TODO: Add your specialized creation code here
  93. return 0;
  94. }
  95. void CGfxOutBarCtrl::OnPaint()
  96. {
  97. CRect rc;
  98. GetClientRect(&rc);
  99. CPaintDC dc(this);
  100. CDC memDC;
  101. memDC.CreateCompatibleDC(&dc);
  102. CBitmap bmp;
  103. bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
  104. CBitmap * oldbmp = memDC.SelectObject(&bmp);;
  105. memDC.FillSolidRect(rc,m_crBackground);
  106. int nFolders=m_arFolder.GetSize();
  107. for(int i=0;i<nFolders;i++)
  108. {
  109. CRect rcFolder;
  110. GetFolderRect(i,rcFolder);
  111. DrawFolder(&memDC,i,&rcFolder);
  112. }
  113. dc.BitBlt(rc.left,rc.top,rc.Width(),rc.Height(),&memDC,0,0,SRCCOPY);//Copy
  114. memDC.DeleteDC();
  115. }
  116. BOOL CGfxOutBarCtrl::OnEraseBkgnd(CDC* pDC)
  117. {
  118. return true;
  119. }
  120. bool CGfxOutBarCtrl::GetFolderRect(const int iIndex, CRect & rect) const
  121. {
  122. int max = m_arFolder.GetSize();
  123. ASSERT(iIndex >= 0 && iIndex < max);
  124. if (iIndex >= 0 && iIndex < max)
  125. {
  126. CRect rc;
  127. GetClientRect(rc);
  128. if (iIndex > iSelFolder)
  129. rect.SetRect(rc.left, rc.bottom - ((max - iIndex)) * nFolderHeight, rc.right,
  130. rc.bottom - (max - iIndex - 1) * nFolderHeight);
  131. else
  132. rect.SetRect(rc.left, rc.top + iIndex * nFolderHeight, rc.right,
  133. rc.top + (1 + iIndex) * nFolderHeight);
  134. return true;
  135. }
  136. return false;
  137. }
  138. int CGfxOutBarCtrl::AddFolder(const char * cFolderName, const DWORD exData)
  139. {
  140. CBm_arFolder * pbf = new CBm_arFolder(cFolderName, exData);
  141. ASSERT(pbf);
  142. m_arFolder.Add((void *)pbf);
  143. return m_arFolder.GetSize() - 1;
  144. }
  145. int CGfxOutBarCtrl::AddFolderBar(const char * pFolder, CWnd * pSon, const DWORD exData)
  146. {
  147. CBm_arFolder * pbf = new CBm_arFolder(pFolder, exData);
  148. ASSERT(pbf);
  149. pbf->pChild = pSon;
  150. m_arFolder.Add((void *)pbf);
  151. return m_arFolder.GetSize() - 1;
  152. }
  153. CGfxOutBarCtrl::CBm_arFolder::CBm_arFolder(const char * name, DWORD exData)
  154. {
  155. cName = NULL;
  156. dwData = exData;
  157. if (name)
  158. {
  159. cName = new char[lstrlen(name)+1];
  160. ASSERT(cName);
  161. lstrcpy(cName, name);
  162. }
  163. pChild = NULL;
  164. }
  165. CGfxOutBarCtrl::CBm_arFolder::~CBm_arFolder()
  166. {
  167. if (cName) delete [] cName;
  168. }
  169. void CGfxOutBarCtrl::GetInsideRect(CRect & rect) const
  170. {
  171. GetClientRect(rect);
  172. if (m_arFolder.GetSize() > 0)
  173. {
  174. int max = m_arFolder.GetSize();
  175. rect.top += nFolderHeight * (iSelFolder + 1);//+ 2;
  176. rect.bottom -= (max - iSelFolder - 1)*nFolderHeight +1;
  177. return;
  178. }
  179. }
  180. int CGfxOutBarCtrl::HitTestEx(const CPoint & point, int &index)
  181. {
  182. int max = m_arFolder.GetSize(), t;
  183. CRect rc;
  184. for (t = 0; t < max; t++)
  185. {
  186. GetFolderRect(t, rc);
  187. if (rc.PtInRect(point))
  188. {
  189. index = t;
  190. return htFolder;
  191. }
  192. }
  193. index = -1;
  194. return htNothing;
  195. }
  196. void CGfxOutBarCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  197. {
  198. if (GetFocus() != this) SetFocus();
  199. int index, ht = HitTestEx(point, index);
  200. if (ht == htFolder)
  201. {
  202. bool bHigh = true;
  203. if (::GetCapture() == NULL)
  204. {
  205. SetCapture();
  206. ASSERT(this == GetCapture());
  207. AfxLockTempMaps();
  208. while (TRUE)
  209. {
  210. MSG msg;
  211. VERIFY(::GetMessage(&msg, NULL, 0, 0));
  212. if (CWnd::GetCapture() != this) break;
  213. switch (msg.message)
  214. {
  215. case WM_LBUTTONUP:
  216. {
  217. CPoint pt(msg.lParam);
  218. int idx, ht1 = HitTestEx(pt, idx);
  219. if (ht1 == htFolder && idx != iSelFolder)
  220. {
  221. //idx = (idx == iSelFolder)?(idx+1):idx;
  222. if(idx <GetFolderCount())
  223. SetSelFolder(idx);
  224. }
  225. }
  226. goto ExitLoop;
  227. default:
  228. DispatchMessage(&msg);
  229. break;
  230. }
  231. }
  232. ExitLoop:
  233. ReleaseCapture();
  234. AfxUnlockTempMaps(FALSE);
  235. }
  236. }
  237. CWnd::OnLButtonDown(nFlags, point);
  238. }
  239. void CGfxOutBarCtrl::SetSelFolder(const int index)
  240. {
  241. ASSERT(index >= 0 && index < GetFolderCount());
  242. if (index == iSelFolder) return;
  243. CWnd * pc = GetFolderChild();
  244. if (pc) pc->ShowWindow(SW_HIDE);
  245. iSelFolder = index;
  246. pc = GetFolderChild();
  247. if (pc)
  248. {
  249. CRect rc;
  250. GetInsideRect(rc);
  251. pc->MoveWindow(rc);
  252. pc->ShowWindow(SW_SHOW);
  253. }
  254. Invalidate();
  255. }
  256. int CGfxOutBarCtrl::GetFolderCount() const
  257. {
  258. return m_arFolder.GetSize();
  259. }
  260. int CGfxOutBarCtrl::GetSelFolder() const
  261. {
  262. return iSelFolder;
  263. }
  264. void CGfxOutBarCtrl::RemoveFolder(const int index)
  265. {
  266. ASSERT(index >= 0 && index < GetFolderCount());
  267. CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(index);
  268. delete pbf;
  269. m_arFolder.RemoveAt(index);
  270. if (iSelFolder >= index) iSelFolder = index - 1;
  271. if (iSelFolder < 0 && GetFolderCount() > 0) iSelFolder = 0;
  272. Invalidate();
  273. }
  274. BOOL CGfxOutBarCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  275. {
  276. CPoint pt(GetMessagePos());
  277. ScreenToClient(&pt);
  278. int index, ht = HitTestEx(pt, index);
  279. if (ht == htFolder)
  280. {
  281. SetCursor(hHandCursor);
  282. return true;
  283. }
  284. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  285. }
  286. void CGfxOutBarCtrl::OnSize(UINT nType, int cx, int cy)
  287. {
  288. CWnd::OnSize(nType, cx, cy);
  289. int t, max = GetFolderCount();
  290. CRect rc;
  291. GetInsideRect(rc);
  292. for (t = 0; t < max; t++)
  293. {
  294. CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(t);
  295. CWnd * pc = GetFolderChild(t);
  296. if (pc) pc->SetWindowPos(0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER);
  297. }
  298. }
  299. CWnd * CGfxOutBarCtrl::GetFolderChild(int iFolder)
  300. {
  301. if (GetFolderCount())
  302. {
  303. if (iFolder < 0) iFolder = iSelFolder;
  304. CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(iFolder);
  305. return pbf->pChild;
  306. }
  307. return NULL;
  308. }
  309. DWORD CGfxOutBarCtrl::GetFolderData(int iFolder)
  310. {
  311. if (iFolder < 0) iFolder = iSelFolder;
  312. CBm_arFolder * pbf = (CBm_arFolder *) m_arFolder.GetAt(iFolder);
  313. return pbf->dwData;
  314. }
  315. void CGfxOutBarCtrl::OnMouseMove(UINT nFlags, CPoint point)
  316. {
  317. // TODO: 在此添加消息处理程序代码和/或调用默认值
  318. int ht = HitTestEx(point, iHoverFolder);
  319. if (ht == htFolder)
  320. {
  321. HighlightFolder(iHoverFolder);
  322. SetTimer(1,100,NULL);
  323. }
  324. CWnd::OnMouseMove(nFlags, point);
  325. }
  326. void CGfxOutBarCtrl::DrawFolder(CDC * pDC, const int iIdx, CRect rect)
  327. {
  328. if(iIdx < 0) return;
  329. CBm_arFolder *pBf=(CBm_arFolder*)m_arFolder.GetAt(iIdx);
  330. if (iHoverFolder == iIdx)
  331. {
  332. if(m_bmpHoverFolder.m_hObject != NULL)
  333. m_bmpHoverFolder.ExtendDraw(pDC,rect,20,5);
  334. }
  335. else
  336. {
  337. if(m_bmpNormalFolder.m_hObject != NULL)
  338. m_bmpNormalFolder.ExtendDraw(pDC,rect,20,5);
  339. }
  340. if(iSelFolder == iIdx && iSelcon != NULL)
  341. {
  342. ::DrawIconEx(*pDC,rect.left+2,rect.top +(nFolderHeight-16)/2,iSelcon,16,16,0,NULL,DI_NORMAL);
  343. }
  344. //Draw Folder Name In Folder
  345. if(m_pFont == NULL)
  346. m_pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT));
  347. pDC->SelectObject(m_pFont);
  348. pDC->SetTextColor(m_crText);
  349. pDC->SetBkMode(TRANSPARENT);
  350. pDC->DrawText(pBf->cName,rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  351. }
  352. void CGfxOutBarCtrl::HighlightFolder(const int index)
  353. {
  354. if (iLastFolderHighlighted == index) return;
  355. CClientDC dc(this);
  356. if (iLastFolderHighlighted >= 0)
  357. {
  358. CRect rc;
  359. if (GetFolderRect(iLastFolderHighlighted, rc))
  360. {
  361. DrawFolder(&dc,iLastFolderHighlighted,rc);
  362. }
  363. }
  364. if (index >= 0)
  365. {
  366. CRect rc;
  367. if (GetFolderRect(index, rc))
  368. {
  369. DrawFolder(&dc,index,rc);
  370. }
  371. }
  372. iLastFolderHighlighted = index;
  373. }
  374. void CGfxOutBarCtrl::OnTimer(UINT_PTR nIDEvent)
  375. {
  376. // TODO: 在此添加消息处理程序代码和/或调用默认值
  377. if (nIDEvent == 1)
  378. {
  379. CPoint pt(GetMessagePos()); ScreenToClient(&pt);
  380. CRect rc; GetClientRect(&rc);
  381. int ht = HitTestEx(pt, iHoverFolder);
  382. if (ht != htFolder ||
  383. !(rc.PtInRect(pt)))
  384. {
  385. HighlightFolder(-1);
  386. KillTimer(1);
  387. }
  388. }
  389. CWnd::OnTimer(nIDEvent);
  390. }