XComboList.cpp
资源名称:多线程实例.rar [点击查看]
上传用户:dfzycw
上传日期:2010-01-10
资源大小:66k
文件大小:10k
源码类别:
进程与线程
开发平台:
Visual C++
- // XComboList.cpp
- //
- // Author: Hans Dietrich
- // hdietrich2@hotmail.com
- //
- // This software is released into the public domain.
- // You are free to use it in any way you like.
- //
- // This software is provided "as is" with no expressed
- // or implied warranty. I accept no liability for any
- // damage or loss of business that this software may cause.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "XComboList.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- UINT NEAR WM_XCOMBOLIST_VK_RETURN = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_VK_RETURN"));
- UINT NEAR WM_XCOMBOLIST_VK_ESCAPE = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_VK_ESCAPE"));
- UINT NEAR WM_XCOMBOLIST_KEYDOWN = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_KEYDOWN"));
- UINT NEAR WM_XCOMBOLIST_LBUTTONUP = ::RegisterWindowMessage(_T("WM_XCOMBOLIST_LBUTTONUP"));
- BEGIN_MESSAGE_MAP(CXComboList, CWnd)
- //{{AFX_MSG_MAP(CXComboList)
- ON_WM_LBUTTONDOWN()
- ON_WM_KILLFOCUS()
- ON_WM_CREATE()
- ON_WM_VSCROLL()
- ON_WM_DESTROY()
- ON_WM_TIMER()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- ///////////////////////////////////////////////////////////////////////////////
- // ctor
- CXComboList::CXComboList(CWnd *pParent)
- {
- m_pParent = pParent;
- ASSERT(m_pParent);
- m_nCount = 0;
- m_bFirstTime = TRUE;
- }
- CXComboList::~CXComboList()
- {
- }
- ///////////////////////////////////////////////////////////////////////////////
- // SetActive
- void CXComboList::SetActive(int nScrollBarWidth)
- {
- //TRACE0("in CXComboList::SetActiven");
- if (!::IsWindow(m_ListBox.m_hWnd))
- return;
- m_ListBox.SetFocus();
- if (m_bFirstTime)
- {
- m_bFirstTime = FALSE;
- CRect rect;
- GetWindowRect(&rect);
- // set listbox size according to item height
- int nItemHeight = m_ListBox.GetItemHeight(0);
- CRect lbrect;
- GetClientRect(&lbrect);
- lbrect.top += 1;
- lbrect.bottom = lbrect.top + (rect.Height() / nItemHeight) * nItemHeight;
- lbrect.left += 1;
- lbrect.right -= nScrollBarWidth;
- int nItemsInView = (lbrect.Height()) / nItemHeight;
- // set size of listbox wrapper (from size of listbox)
- rect.bottom = rect.top + lbrect.Height() + 4;
- MoveWindow(&rect);
- m_ListBox.MoveWindow(&lbrect);
- m_ListBox.BringWindowToTop();
- // set size and position for vertical scroll bar
- CRect sbrect;
- sbrect = lbrect;
- sbrect.left = lbrect.right;
- sbrect.right += nScrollBarWidth;
- m_wndSBVert.MoveWindow(&sbrect);
- SCROLLINFO si;
- si.cbSize = sizeof(si);
- si.fMask = SIF_ALL;
- m_wndSBVert.GetScrollInfo(&si);
- // set info for scrollbar
- si.nMin = 0;
- si.nMax = m_ListBox.GetCount();
- if (si.nMax < 0)
- si.nMax = 1;
- si.nPage = nItemsInView;
- int nCurSel = m_ListBox.GetCurSel();
- if (nCurSel == LB_ERR || nCurSel < 0)
- nCurSel = 0;
- si.nPos = nCurSel;
- // set top index, to force selected item to be in view
- m_ListBox.SetTopIndex(nCurSel > 0 ? nCurSel - 1 : 0);
- if (si.nPos < 0)
- si.nPos = 0;
- m_wndSBVert.SetScrollInfo(&si);
- m_wndSBVert.SetScrollPos(si.nPos, TRUE);
- //RedrawWindow();
- SetTimer(1, 80, NULL);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // GetScrollBarCtrl
- CScrollBar* CXComboList::GetScrollBarCtrl(int nBar)
- {
- UNUSED_ALWAYS(nBar);
- return &m_wndSBVert;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // SendRegisteredMessage
- void CXComboList::SendRegisteredMessage(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- CWnd *pWnd = m_pParent;
- if (pWnd)
- pWnd->SendMessage(nMsg, wParam, lParam);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnLButtonDown
- void CXComboList::OnLButtonDown(UINT nFlags, CPoint point)
- {
- SendRegisteredMessage(WM_XCOMBOLIST_LBUTTONUP, 0, 0);
- CWnd::OnLButtonUp(nFlags, point);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // PreTranslateMessage
- BOOL CXComboList::PreTranslateMessage(MSG* pMsg)
- {
- switch (pMsg->message)
- {
- case WM_KEYDOWN:
- {
- ///////////////////////////////////////////////////////////////////
- // we need to trap all cursor keys & alpha keys to reposition the
- // scroll bar
- ///////////////////////////////////////////////////////////////////
- //TRACE(" WM_KEYDOWNn");
- SCROLLINFO si =
- {
- sizeof(SCROLLINFO),
- SIF_ALL | SIF_DISABLENOSCROLL,
- };
- m_wndSBVert.GetScrollInfo(&si);
- BOOL bSetScrollInfo = FALSE;
- int nIndex = 0;
- if (::IsWindow(m_ListBox.m_hWnd))
- nIndex = m_ListBox.GetCurSel();
- if (nIndex == LB_ERR || nIndex < 0)
- nIndex = 0;
- // use index from listbox, because scroll position cannot be relied
- // upon here
- switch (pMsg->wParam)
- {
- case VK_RETURN:
- SendRegisteredMessage(WM_XCOMBOLIST_VK_RETURN, 0, 0);
- break;
- case VK_ESCAPE:
- SendRegisteredMessage(WM_XCOMBOLIST_VK_ESCAPE, 0, 0);
- break;
- // handle scrolling messages
- case VK_DOWN:
- si.nPos = nIndex + 1;
- bSetScrollInfo = TRUE;
- break;
- case VK_END:
- si.nPos = si.nMax;
- bSetScrollInfo = TRUE;
- break;
- case VK_HOME:
- si.nPos = 0;
- bSetScrollInfo = TRUE;
- break;
- case VK_NEXT: // PAGE DOWN
- si.nPos = nIndex + (si.nPage-1);
- bSetScrollInfo = TRUE;
- break;
- case VK_PRIOR: // PAGE UP
- si.nPos = nIndex - (si.nPage - 1);
- bSetScrollInfo = TRUE;
- break;
- case VK_UP:
- si.nPos = nIndex - 1;
- bSetScrollInfo = TRUE;
- break;
- default:
- if (pMsg->wParam >= 0x41/*VK_A*/ && pMsg->wParam <= 0x5A/*VK_Z*/)
- {
- // this was an alpha key - try to find listbox index
- CString strAlpha;
- strAlpha = (_TCHAR) pMsg->wParam;
- int nIndex2 = 0;
- if (::IsWindow(m_ListBox.m_hWnd))
- nIndex2 = m_ListBox.FindString(nIndex, strAlpha);
- if (nIndex2 != LB_ERR)
- {
- si.nPos = nIndex2;
- bSetScrollInfo = TRUE;
- }
- }
- break;
- }
- if (bSetScrollInfo)
- {
- // let parent know the selection has changed
- SendRegisteredMessage(WM_XCOMBOLIST_KEYDOWN, 0, 0);
- // update scrollbar
- if (si.nPos < 0)
- si.nPos = 0;
- if (si.nPos > si.nMax)
- si.nPos = si.nMax;
- m_wndSBVert.SetScrollInfo(&si);
- }
- break;
- }
- case WM_LBUTTONUP:
- SendRegisteredMessage(WM_XCOMBOLIST_LBUTTONUP, 0, 0);
- break;
- }
- return CWnd::PreTranslateMessage(pMsg);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnKillFocus
- void CXComboList::OnKillFocus(CWnd* pNewWnd)
- {
- //TRACE0("in CXComboList::OnKillFocusn");
- CWnd::OnKillFocus(pNewWnd);
- m_nCount++;
- if (m_nCount > 2)
- {
- SendRegisteredMessage(WM_XCOMBOLIST_VK_ESCAPE, 0, 0);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnCreate
- int CXComboList::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CWnd::OnCreate(lpCreateStruct) == -1)
- return -1;
- CRect rect2(0,0,0,0);
- // create the listbox that we're wrapping
- VERIFY(m_ListBox.Create(WS_VISIBLE|WS_CHILD|LBS_NOINTEGRALHEIGHT/*|WS_BORDER*/,
- rect2, this, 0));
- // create the vertical scrollbar
- VERIFY(m_wndSBVert.Create(WS_VISIBLE|WS_CHILD|SBS_VERT,
- rect2, this, 0));
- // set font from parent
- CFont *font = GetParent()->GetFont();
- if (font)
- {
- SetFont(font, FALSE);
- m_wndSBVert.SetFont(font, FALSE);
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnVScroll
- void CXComboList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*)
- {
- if (!::IsWindow(m_ListBox.m_hWnd))
- return;
- // forward scroll message to listbox
- const MSG* pMsg = GetCurrentMessage();
- m_ListBox.SendMessage(WM_VSCROLL, pMsg->wParam, pMsg->lParam);
- SCROLLINFO si =
- {
- sizeof(SCROLLINFO),
- SIF_ALL | SIF_DISABLENOSCROLL,
- };
- m_wndSBVert.GetScrollInfo(&si);
- switch (nSBCode)
- {
- case SB_BOTTOM: // scroll to bottom
- si.nPos = si.nMax;
- break;
- case SB_TOP: // scroll to top
- si.nPos = 0;
- break;
- case SB_PAGEDOWN: // scroll one page down
- si.nPos += si.nPage;
- break;
- case SB_PAGEUP: // scroll one page up
- si.nPos -= si.nPage;
- break;
- case SB_LINEDOWN: // scroll one line up
- si.nPos += 1;
- break;
- case SB_LINEUP: // scroll one line up
- si.nPos -= 1;
- break;
- case SB_THUMBTRACK: // drag scroll box to specified position. The
- // current position is provided in nPos
- case SB_THUMBPOSITION: // scroll to the absolute position. The current
- // position is provided in nPos
- si.nPos = nPos;
- break;
- case SB_ENDSCROLL: // end scroll
- return;
- default:
- break;
- }
- if (si.nPos < 0)
- si.nPos = 0;
- if (si.nPos > si.nMax)
- si.nPos = si.nMax;
- m_wndSBVert.SetScrollInfo(&si);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnDestroy
- void CXComboList::OnDestroy()
- {
- KillTimer(1);
- if (::IsWindow(m_ListBox.m_hWnd))
- m_ListBox.DestroyWindow();
- CWnd::OnDestroy();
- }
- ///////////////////////////////////////////////////////////////////////////////
- // OnTimer
- void CXComboList::OnTimer(UINT nIDEvent)
- {
- UNUSED_ALWAYS(nIDEvent);
- if (!::IsWindow(m_ListBox.m_hWnd))
- return;
- // get current mouse position
- POINT point;
- ::GetCursorPos(&point);
- ScreenToClient(&point);
- BOOL bOutside;
- int nIndex = m_ListBox.ItemFromPoint(point, bOutside);
- //TRACE(" nIndex=%d bOutside=%dn", nIndex, bOutside);
- if (!bOutside)
- {
- int nCurSel = m_ListBox.GetCurSel();
- if (nIndex != nCurSel)
- if (nIndex >= 0 && nIndex < m_ListBox.GetCount())
- m_ListBox.SetCurSel(nIndex);
- }
- }