SkinListBox.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. // SkinListBox.cpp : 实现文件
  2. //
  3. #include "stdafx.h"
  4. #include "Control.h"
  5. #include "SkinListBox.h"
  6. // CSkinListBox
  7. IMPLEMENT_DYNAMIC(CSkinListBox, CListBox)
  8. BEGIN_MESSAGE_MAP(CSkinListBox, CListBox)
  9. ON_WM_DESTROY()
  10. ON_WM_RBUTTONUP()
  11. ON_WM_LBUTTONDOWN()
  12. ON_WM_LBUTTONUP()
  13. ON_WM_MOUSEMOVE()
  14. //ON_WM_NCPAINT()
  15. ON_WM_ERASEBKGND()
  16. END_MESSAGE_MAP()
  17. CSkinListBox::CSkinListBox( void )
  18. {
  19. m_pBackImgN = NULL;
  20. m_pSelectImg = NULL;
  21. m_pBackImgH = NULL;
  22. m_nHovenItem = 0;
  23. nItemHeight = 20;
  24. m_ItemStruct.clear();
  25. }
  26. CSkinListBox::~CSkinListBox( void )
  27. {
  28. }
  29. BOOL CSkinListBox::SetBackNormalImage( LPCTSTR lpszFileName, CONST LPRECT lpNinePart /*= NULL*/ )
  30. {
  31. RenderEngine->RemoveImage(m_pBackImgN);
  32. m_pBackImgN = RenderEngine->GetImage(lpszFileName);
  33. if (m_pBackImgN != NULL)
  34. m_pBackImgN->SetNinePart(lpNinePart);
  35. return (m_pBackImgN != NULL) ? TRUE : FALSE;
  36. }
  37. BOOL CSkinListBox::SetSelectImage( LPCTSTR lpszFileName, CONST LPRECT lpNinePart /*= NULL*/ )
  38. {
  39. RenderEngine->RemoveImage(m_pSelectImg);
  40. m_pSelectImg = RenderEngine->GetImage(lpszFileName);
  41. if (m_pSelectImg != NULL)
  42. m_pSelectImg->SetNinePart(lpNinePart);
  43. return (m_pSelectImg != NULL) ? TRUE : FALSE;
  44. }
  45. BOOL CSkinListBox::SetHovenImage( LPCTSTR lpszFileName, CONST LPRECT lpNinePart /*= NULL*/ )
  46. {
  47. RenderEngine->RemoveImage(m_pBackImgH);
  48. m_pBackImgH = RenderEngine->GetImage(lpszFileName);
  49. if (m_pBackImgH != NULL)
  50. m_pBackImgH->SetNinePart(lpNinePart);
  51. return (m_pBackImgH != NULL) ? TRUE : FALSE;
  52. }
  53. void CSkinListBox::OnDestroy()
  54. {
  55. __super::OnDestroy();
  56. RenderEngine->RemoveImage(m_pBackImgN);
  57. RenderEngine->RemoveImage(m_pBackImgH);
  58. RenderEngine->RemoveImage(m_pSelectImg);
  59. RemoveScorll();
  60. }
  61. void CSkinListBox::OnNcPaint()
  62. {
  63. //如果资源没有就是不想绘制边框了
  64. if ( m_pBackImgN == NULL )
  65. {
  66. __super::OnNcPaint();
  67. return;
  68. }
  69. CRect rcWindow;
  70. GetWindowRect(&rcWindow);
  71. CRect rcClient;
  72. GetClientRect(&rcClient);
  73. ClientToScreen(&rcClient);
  74. rcClient.OffsetRect(-rcWindow.left, -rcWindow.top);
  75. rcWindow.OffsetRect(-rcWindow.left, -rcWindow.top);
  76. CDC *pWindowDC = GetWindowDC();
  77. CMemoryDC MemDC(pWindowDC,rcWindow);
  78. DrawParentWndBg(GetSafeHwnd(),MemDC.GetSafeHdc());
  79. if (m_pBackImgN != NULL && !m_pBackImgN->IsNull())
  80. m_pBackImgN->Draw(&MemDC, rcWindow);
  81. pWindowDC->BitBlt(rcWindow.left,rcWindow.top,rcWindow.Width(),rcWindow.Height(),&MemDC,0,0,SRCCOPY);
  82. ReleaseDC(pWindowDC);
  83. }
  84. void CSkinListBox::OnRButtonUp(UINT nFlags, CPoint point)
  85. {
  86. CRect rcItem(0,0,0,0);
  87. SetSel(-1,FALSE);
  88. for (int i =0; i<GetCount(); i++)
  89. {
  90. GetItemRect(i, &rcItem);
  91. if(rcItem.PtInRect(point))
  92. {
  93. if( IsSingleSel() )
  94. SetCurSel(i);
  95. else
  96. SetSel(i);
  97. break;
  98. }
  99. }
  100. CWnd *pWnd = GetParent();
  101. if ( (pWnd == NULL) && (pWnd->GetSafeHwnd() != NULL) ) return;
  102. pWnd->PostMessage(WM_COMMAND,GetDlgCtrlID(),0);
  103. __super::OnRButtonUp(nFlags, point);
  104. }
  105. void CSkinListBox::OnMouseMove(UINT nFlags, CPoint point)
  106. {
  107. CRect rcItem(0,0,0,0);
  108. //保存旧状态,为了防止在同一个节点下因过多的刷新消耗cpu资源
  109. static int nOldIndex = -1;
  110. for (int i =0; i<GetCount(); i++)
  111. {
  112. GetItemRect(i, &rcItem);
  113. if(rcItem.PtInRect(point))
  114. {
  115. if( m_nHovenItem != i ) Invalidate(FALSE);
  116. m_nHovenItem = i;
  117. break;
  118. }
  119. }
  120. __super::OnMouseMove(nFlags, point);
  121. }
  122. void CSkinListBox::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  123. {
  124. //没有节点就不用继续执行了
  125. if( GetCount()==0 ) return;
  126. //变量定义
  127. CRect rcItem=lpDrawItemStruct->rcItem;
  128. CDC * pDCControl=CDC::FromHandle(lpDrawItemStruct->hDC);
  129. //创建缓冲
  130. CDC BufferDC;
  131. CBitmap ImageBuffer;
  132. BufferDC.CreateCompatibleDC(pDCControl);
  133. ImageBuffer.CreateCompatibleBitmap(pDCControl,rcItem.Width(),rcItem.Height());
  134. //设置环境
  135. BufferDC.SelectObject(&ImageBuffer);
  136. BufferDC.SelectObject(GetCtrlFont());
  137. //获取字符
  138. CString strString;
  139. GetText(lpDrawItemStruct->itemID,strString);
  140. //计算位置
  141. CRect rcString;
  142. rcString.SetRect(4,0,rcItem.Width()-8,rcItem.Height());
  143. //颜色定义
  144. COLORREF crTextColor=((lpDrawItemStruct->itemState&ODS_SELECTED)!=0)?m_colSelectText:m_colNormalText;
  145. //绘画背景
  146. BufferDC.FillSolidRect(0,0,rcItem.Width(),rcItem.Height(),m_colBack);
  147. //节点选中
  148. if ( (lpDrawItemStruct->itemState&ODS_SELECTED) != 0 )
  149. {
  150. if ( m_pSelectImg!= NULL && !m_pSelectImg->IsNull() )
  151. {
  152. m_pSelectImg->Draw(&BufferDC,CRect(0,0,rcItem.Width(),rcItem.Height()));
  153. }
  154. }
  155. //节点高亮
  156. else if ( m_nHovenItem == lpDrawItemStruct->itemID )
  157. {
  158. if ( m_pBackImgH!= NULL && !m_pBackImgH->IsNull() )
  159. {
  160. m_pBackImgH->Draw(&BufferDC,CRect(0,0,rcItem.Width(),rcItem.Height()));
  161. }
  162. }
  163. //绘画字符
  164. BufferDC.SetBkMode(TRANSPARENT);
  165. BufferDC.SetTextColor(crTextColor);
  166. BufferDC.DrawText(strString,&rcString,DT_VCENTER|DT_SINGLELINE);
  167. //绘画界面
  168. pDCControl->BitBlt(rcItem.left,rcItem.top,rcItem.Width(),rcItem.Height(),&BufferDC,0,0,SRCCOPY);
  169. //清理资源
  170. BufferDC.DeleteDC();
  171. ImageBuffer.DeleteObject();
  172. }
  173. void CSkinListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  174. {
  175. vector<tagItemStruct>::iterator iter = m_ItemStruct.begin();
  176. for (;iter != m_ItemStruct.end(); ++iter )
  177. {
  178. lpMeasureItemStruct->itemHeight = iter->itemHeight;
  179. lpMeasureItemStruct->itemWidth = iter->itemWidth;
  180. }
  181. }
  182. bool CSkinListBox::IsSingleSel()
  183. {
  184. DWORD dwStyle = GetStyle();
  185. if ( ((dwStyle&LBS_EXTENDEDSEL)!=0) || ((dwStyle&LBS_MULTIPLESEL)!=0) )
  186. {
  187. return false;
  188. }
  189. return true;
  190. }
  191. void CSkinListBox::AddString(LPCTSTR lpszItem)
  192. {
  193. InsertItem();
  194. __super::AddString(lpszItem);
  195. }
  196. int CSkinListBox::SetItemHeight( int nIndex, UINT cyItemHeight )
  197. {
  198. if ( nIndex == -1 ) nItemHeight = cyItemHeight;
  199. vector<tagItemStruct>::iterator iter = m_ItemStruct.begin();
  200. for (;iter != m_ItemStruct.end(); ++iter )
  201. {
  202. if ( iter->itemID == nIndex )
  203. {
  204. iter->itemHeight = cyItemHeight;
  205. break;
  206. }
  207. }
  208. return __super::SetItemHeight(nIndex,cyItemHeight);
  209. }
  210. int CSkinListBox::DeleteString( UINT nIndex )
  211. {
  212. vector<tagItemStruct>::iterator iter = m_ItemStruct.begin();
  213. for (;iter != m_ItemStruct.end(); ++iter )
  214. {
  215. if ( iter->itemID == nIndex )
  216. {
  217. m_ItemStruct.erase(iter);
  218. break;
  219. }
  220. }
  221. return __super::DeleteString(nIndex);
  222. }
  223. void CSkinListBox::InsertItem()
  224. {
  225. tagItemStruct ItemStruct;
  226. ZeroMemory(&ItemStruct,sizeof ItemStruct);
  227. CRect rcClient;
  228. GetClientRect(&rcClient);
  229. ItemStruct.itemID = m_ItemStruct.size();
  230. ItemStruct.itemHeight = nItemHeight;
  231. ItemStruct.itemWidth = rcClient.Width();
  232. m_ItemStruct.push_back(ItemStruct);
  233. }
  234. void CSkinListBox::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue )
  235. {
  236. ISkinControl::SetAttribute(pstrName,pstrValue);
  237. // if( _tcscmp(pstrName, _T("itemheight")) == 0 )
  238. // {
  239. // LPTSTR pstr = NULL;
  240. // SetItemHeight(-1,_tcstol(pstrValue, &pstr, 10));
  241. // }
  242. // else
  243. if( _tcscmp(pstrName, _T("scrollimage")) == 0 )
  244. {
  245. SetScrollImage(this,pstrValue);
  246. }
  247. }
  248. void CSkinListBox::ParseItem( CXmlNode *root )
  249. {
  250. if( root == NULL ) return;
  251. int nAttributes = root->GetAttributeCount();
  252. LPCTSTR pstrClass = NULL;
  253. LPCTSTR pstrName = NULL;
  254. LPCTSTR pstrValue = NULL;
  255. for( int i = 0; i < nAttributes; i++ )
  256. {
  257. pstrClass = root->GetName();
  258. pstrName = root->GetAttributeName(i);
  259. pstrValue = root->GetAttributeValue(i);
  260. if( _tcscmp(pstrClass, _T("bknormalimage")) == 0 )
  261. {
  262. if( _tcscmp(pstrName, _T("value")) == 0 ) SetBackNormalImage(pstrValue);
  263. else if( _tcscmp(pstrName, _T("ninepart")) == 0 )
  264. {
  265. LPTSTR pstr = NULL;
  266. CRect rc;
  267. rc.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  268. rc.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  269. rc.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  270. rc.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  271. if (m_pBackImgN != NULL)
  272. m_pBackImgN->SetNinePart(&rc);
  273. }
  274. }
  275. else if( _tcscmp(pstrClass, _T("selectimage")) == 0 )
  276. {
  277. if( _tcscmp(pstrName, _T("value")) == 0 ) SetSelectImage(pstrValue);
  278. else if( _tcscmp(pstrName, _T("ninepart")) == 0 )
  279. {
  280. LPTSTR pstr = NULL;
  281. CRect rc;
  282. rc.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  283. rc.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  284. rc.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  285. rc.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  286. if (m_pSelectImg != NULL)
  287. m_pSelectImg->SetNinePart(&rc);
  288. }
  289. }
  290. else if( _tcscmp(pstrClass, _T("hovenimage")) == 0 )
  291. {
  292. if( _tcscmp(pstrName, _T("value")) == 0 ) SetHovenImage(pstrValue);
  293. else if( _tcscmp(pstrName, _T("ninepart")) == 0 )
  294. {
  295. LPTSTR pstr = NULL;
  296. CRect rc;
  297. rc.left = _tcstol(pstrValue, &pstr, 10); ASSERT(pstr);
  298. rc.top = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  299. rc.right = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  300. rc.bottom = _tcstol(pstr + 1, &pstr, 10); ASSERT(pstr);
  301. if (m_pBackImgH != NULL)
  302. m_pBackImgH->SetNinePart(&rc);
  303. }
  304. }
  305. else if( _tcscmp(pstrClass, _T("item")) == 0 )
  306. {
  307. if( _tcscmp(pstrName, _T("text")) == 0 ) AddString(pstrValue);
  308. }
  309. }
  310. }
  311. BOOL CSkinListBox::CreateControl( CWnd* pParentWnd )
  312. {
  313. if( !Create(WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS |WS_VSCROLL ,CRect(0,0,0,0),pParentWnd,0) )
  314. return FALSE;
  315. SetFont(CFont::FromHandle(RenderEngine->GetDeaultFont()));
  316. m_pOwnWnd = this;
  317. return TRUE;
  318. }
  319. BOOL CSkinListBox::OnEraseBkgnd(CDC* pDC)
  320. {
  321. return TRUE;
  322. return __super::OnEraseBkgnd(pDC);
  323. }