XComboList.cpp
上传用户:dfzycw
上传日期:2010-01-10
资源大小:66k
文件大小:10k
源码类别:

进程与线程

开发平台:

Visual C++

  1. // XComboList.cpp
  2. //
  3. // Author:  Hans Dietrich
  4. //          hdietrich2@hotmail.com
  5. //
  6. // This software is released into the public domain.
  7. // You are free to use it in any way you like.
  8. //
  9. // This software is provided "as is" with no expressed
  10. // or implied warranty.  I accept no liability for any
  11. // damage or loss of business that this software may cause.
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. #include "stdafx.h"
  15. #include "XComboList.h"
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. UINT NEAR WM_XCOMBOLIST_VK_RETURN = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_VK_RETURN"));
  22. UINT NEAR WM_XCOMBOLIST_VK_ESCAPE = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_VK_ESCAPE"));
  23. UINT NEAR WM_XCOMBOLIST_KEYDOWN   = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_KEYDOWN"));
  24. UINT NEAR WM_XCOMBOLIST_LBUTTONUP = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_LBUTTONUP"));
  25. BEGIN_MESSAGE_MAP(CXComboList, CWnd)
  26. //{{AFX_MSG_MAP(CXComboList)
  27. ON_WM_LBUTTONDOWN()
  28. ON_WM_KILLFOCUS()
  29. ON_WM_CREATE()
  30. ON_WM_VSCROLL()
  31. ON_WM_DESTROY()
  32. ON_WM_TIMER()
  33. //}}AFX_MSG_MAP
  34. END_MESSAGE_MAP()
  35. ///////////////////////////////////////////////////////////////////////////////
  36. // ctor
  37. CXComboList::CXComboList(CWnd *pParent)
  38. {
  39. m_pParent = pParent;
  40. ASSERT(m_pParent);
  41. m_nCount = 0;
  42. m_bFirstTime = TRUE;
  43. }
  44. CXComboList::~CXComboList()
  45. {
  46. }
  47. ///////////////////////////////////////////////////////////////////////////////
  48. // SetActive
  49. void CXComboList::SetActive(int nScrollBarWidth)
  50. {
  51. //TRACE0("in CXComboList::SetActiven");
  52. if (!::IsWindow(m_ListBox.m_hWnd))
  53. return;
  54. m_ListBox.SetFocus();
  55. if (m_bFirstTime)
  56. {
  57. m_bFirstTime = FALSE;
  58. CRect rect;
  59. GetWindowRect(&rect);
  60. // set listbox size according to item height
  61. int nItemHeight = m_ListBox.GetItemHeight(0);
  62. CRect lbrect;
  63. GetClientRect(&lbrect);
  64. lbrect.top   += 1;
  65. lbrect.bottom = lbrect.top + (rect.Height() / nItemHeight) * nItemHeight;
  66. lbrect.left  += 1;
  67. lbrect.right -= nScrollBarWidth;
  68. int nItemsInView = (lbrect.Height()) / nItemHeight;
  69. // set size of listbox wrapper (from size of listbox)
  70. rect.bottom = rect.top + lbrect.Height() + 4;
  71. MoveWindow(&rect);
  72. m_ListBox.MoveWindow(&lbrect);
  73. m_ListBox.BringWindowToTop();
  74. // set size and position for vertical scroll bar
  75. CRect sbrect;
  76. sbrect = lbrect;
  77. sbrect.left   = lbrect.right;
  78. sbrect.right += nScrollBarWidth;
  79. m_wndSBVert.MoveWindow(&sbrect);
  80. SCROLLINFO si;
  81. si.cbSize = sizeof(si);
  82. si.fMask = SIF_ALL;
  83. m_wndSBVert.GetScrollInfo(&si);
  84. // set info for scrollbar
  85. si.nMin = 0;
  86. si.nMax = m_ListBox.GetCount();
  87. if (si.nMax < 0)
  88. si.nMax = 1;
  89. si.nPage = nItemsInView;
  90. int nCurSel = m_ListBox.GetCurSel();
  91. if (nCurSel == LB_ERR || nCurSel < 0)
  92. nCurSel = 0;
  93. si.nPos = nCurSel;
  94. // set top index, to force selected item to be in view
  95. m_ListBox.SetTopIndex(nCurSel > 0 ? nCurSel - 1 : 0);
  96. if (si.nPos < 0)
  97. si.nPos = 0;
  98. m_wndSBVert.SetScrollInfo(&si);
  99. m_wndSBVert.SetScrollPos(si.nPos, TRUE);
  100. //RedrawWindow();
  101. SetTimer(1, 80, NULL);
  102. }
  103. }
  104. ///////////////////////////////////////////////////////////////////////////////
  105. // GetScrollBarCtrl
  106. CScrollBar* CXComboList::GetScrollBarCtrl(int nBar)
  107. {
  108. UNUSED_ALWAYS(nBar);
  109. return &m_wndSBVert;
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////
  112. // SendRegisteredMessage
  113. void CXComboList::SendRegisteredMessage(UINT nMsg, WPARAM wParam, LPARAM lParam)
  114. {
  115. CWnd *pWnd = m_pParent;
  116. if (pWnd)
  117. pWnd->SendMessage(nMsg, wParam, lParam);
  118. }
  119. ///////////////////////////////////////////////////////////////////////////////
  120. // OnLButtonDown
  121. void CXComboList::OnLButtonDown(UINT nFlags, CPoint point) 
  122. {
  123. SendRegisteredMessage(WM_XCOMBOLIST_LBUTTONUP, 0, 0);
  124. CWnd::OnLButtonUp(nFlags, point);
  125. }
  126. ///////////////////////////////////////////////////////////////////////////////
  127. // PreTranslateMessage
  128. BOOL CXComboList::PreTranslateMessage(MSG* pMsg) 
  129. {
  130. switch (pMsg->message)
  131. {
  132. case WM_KEYDOWN:
  133. {
  134. ///////////////////////////////////////////////////////////////////
  135. // we need to trap all cursor keys & alpha keys to reposition the 
  136. // scroll bar
  137. ///////////////////////////////////////////////////////////////////
  138. //TRACE("   WM_KEYDOWNn");
  139. SCROLLINFO si = 
  140. {
  141. sizeof(SCROLLINFO),
  142. SIF_ALL | SIF_DISABLENOSCROLL,
  143. };
  144. m_wndSBVert.GetScrollInfo(&si);
  145. BOOL bSetScrollInfo = FALSE;
  146. int nIndex = 0;
  147. if (::IsWindow(m_ListBox.m_hWnd))
  148. nIndex = m_ListBox.GetCurSel();
  149. if (nIndex == LB_ERR || nIndex < 0)
  150. nIndex = 0;
  151. // use index from listbox, because scroll position cannot be relied
  152. // upon here
  153. switch (pMsg->wParam)
  154. {
  155. case VK_RETURN:
  156. SendRegisteredMessage(WM_XCOMBOLIST_VK_RETURN, 0, 0);
  157. break;
  158. case VK_ESCAPE:
  159. SendRegisteredMessage(WM_XCOMBOLIST_VK_ESCAPE, 0, 0);
  160. break;
  161. // handle scrolling messages
  162. case VK_DOWN:
  163. si.nPos = nIndex + 1;
  164. bSetScrollInfo = TRUE;
  165. break;
  166. case VK_END:
  167. si.nPos = si.nMax;
  168. bSetScrollInfo = TRUE;
  169. break;
  170. case VK_HOME:
  171. si.nPos = 0;
  172. bSetScrollInfo = TRUE;
  173. break;
  174. case VK_NEXT: // PAGE DOWN
  175. si.nPos = nIndex + (si.nPage-1);
  176. bSetScrollInfo = TRUE;
  177. break;
  178. case VK_PRIOR: // PAGE UP
  179. si.nPos = nIndex - (si.nPage - 1);
  180. bSetScrollInfo = TRUE;
  181. break;
  182. case VK_UP:
  183. si.nPos = nIndex - 1;
  184. bSetScrollInfo = TRUE;
  185. break;
  186. default:
  187. if (pMsg->wParam >= 0x41/*VK_A*/ && pMsg->wParam <= 0x5A/*VK_Z*/)
  188. {
  189. // this was an alpha key - try to find listbox index
  190. CString strAlpha;
  191. strAlpha = (_TCHAR) pMsg->wParam;
  192. int nIndex2 = 0;
  193. if (::IsWindow(m_ListBox.m_hWnd))
  194. nIndex2 = m_ListBox.FindString(nIndex, strAlpha);
  195. if (nIndex2 != LB_ERR)
  196. {
  197. si.nPos = nIndex2;
  198. bSetScrollInfo = TRUE;
  199. }
  200. }
  201. break;
  202. }
  203. if (bSetScrollInfo)
  204. {
  205. // let parent know the selection has changed
  206. SendRegisteredMessage(WM_XCOMBOLIST_KEYDOWN, 0, 0);
  207. // update scrollbar
  208. if (si.nPos < 0)
  209. si.nPos = 0;
  210. if (si.nPos > si.nMax)
  211. si.nPos = si.nMax;
  212. m_wndSBVert.SetScrollInfo(&si);
  213. }
  214. break;
  215. }
  216. case WM_LBUTTONUP:
  217. SendRegisteredMessage(WM_XCOMBOLIST_LBUTTONUP, 0, 0);
  218. break;
  219. }
  220. return CWnd::PreTranslateMessage(pMsg);
  221. }
  222. ///////////////////////////////////////////////////////////////////////////////
  223. // OnKillFocus
  224. void CXComboList::OnKillFocus(CWnd* pNewWnd) 
  225. {
  226. //TRACE0("in CXComboList::OnKillFocusn");
  227. CWnd::OnKillFocus(pNewWnd);
  228. m_nCount++;
  229. if (m_nCount > 2)
  230. {
  231. SendRegisteredMessage(WM_XCOMBOLIST_VK_ESCAPE, 0, 0);
  232. }
  233. }
  234. ///////////////////////////////////////////////////////////////////////////////
  235. // OnCreate
  236. int CXComboList::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  237. {
  238. if (CWnd::OnCreate(lpCreateStruct) == -1)
  239. return -1;
  240. CRect rect2(0,0,0,0);
  241. // create the listbox that we're wrapping
  242. VERIFY(m_ListBox.Create(WS_VISIBLE|WS_CHILD|LBS_NOINTEGRALHEIGHT/*|WS_BORDER*/,
  243. rect2, this, 0));
  244. // create the vertical scrollbar
  245. VERIFY(m_wndSBVert.Create(WS_VISIBLE|WS_CHILD|SBS_VERT,
  246. rect2, this, 0));
  247. // set font from parent
  248. CFont *font = GetParent()->GetFont();
  249. if (font)
  250. {
  251. SetFont(font, FALSE);
  252. m_wndSBVert.SetFont(font, FALSE);
  253. }
  254. return 0;
  255. }
  256. ///////////////////////////////////////////////////////////////////////////////
  257. // OnVScroll
  258. void CXComboList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*) 
  259. {
  260. if (!::IsWindow(m_ListBox.m_hWnd))
  261. return;
  262. // forward scroll message to listbox
  263. const MSG* pMsg = GetCurrentMessage();
  264. m_ListBox.SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
  265.     SCROLLINFO si = 
  266. {
  267.         sizeof(SCROLLINFO),
  268.         SIF_ALL | SIF_DISABLENOSCROLL,
  269.     };
  270. m_wndSBVert.GetScrollInfo(&si);
  271.     switch (nSBCode) 
  272. {
  273. case SB_BOTTOM: // scroll to bottom
  274. si.nPos = si.nMax;
  275. break;
  276. case SB_TOP: // scroll to top
  277. si.nPos = 0;
  278. break;
  279. case SB_PAGEDOWN: // scroll one page down
  280. si.nPos += si.nPage;
  281. break;
  282. case SB_PAGEUP: // scroll one page up
  283. si.nPos -= si.nPage;
  284. break;
  285. case SB_LINEDOWN: // scroll one line up
  286. si.nPos += 1;
  287. break;
  288. case SB_LINEUP: // scroll one line up
  289. si.nPos -= 1;
  290. break;
  291. case SB_THUMBTRACK: // drag scroll box to specified position. The 
  292. // current position is provided in nPos
  293. case SB_THUMBPOSITION: // scroll to the absolute position. The current 
  294. // position is provided in nPos
  295. si.nPos = nPos;        
  296. break;
  297. case SB_ENDSCROLL: // end scroll
  298. return;
  299. default:
  300. break;
  301. }
  302. if (si.nPos < 0)
  303. si.nPos = 0;
  304. if (si.nPos > si.nMax)
  305. si.nPos = si.nMax;
  306. m_wndSBVert.SetScrollInfo(&si);
  307. }
  308. ///////////////////////////////////////////////////////////////////////////////
  309. // OnDestroy
  310. void CXComboList::OnDestroy() 
  311. {
  312. KillTimer(1);
  313. if (::IsWindow(m_ListBox.m_hWnd))
  314. m_ListBox.DestroyWindow();
  315. CWnd::OnDestroy();
  316. }
  317. ///////////////////////////////////////////////////////////////////////////////
  318. // OnTimer
  319. void CXComboList::OnTimer(UINT nIDEvent) 
  320. {
  321. UNUSED_ALWAYS(nIDEvent);
  322. if (!::IsWindow(m_ListBox.m_hWnd))
  323. return;
  324. // get current mouse position
  325. POINT point;
  326. ::GetCursorPos(&point);
  327. ScreenToClient(&point);
  328. BOOL bOutside;
  329. int nIndex = m_ListBox.ItemFromPoint(point, bOutside);
  330. //TRACE("   nIndex=%d  bOutside=%dn", nIndex, bOutside);
  331. if (!bOutside)
  332. {
  333. int nCurSel = m_ListBox.GetCurSel();
  334. if (nIndex != nCurSel)
  335. if (nIndex >= 0 && nIndex < m_ListBox.GetCount())
  336. m_ListBox.SetCurSel(nIndex);
  337. }
  338. }