|
// 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::SetActive\n");
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_KEYDOWN\n");
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::OnKillFocus\n");
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=%d\n", nIndex, bOutside);
if (!bOutside)
{
int nCurSel = m_ListBox.GetCurSel();
if (nIndex != nCurSel)
if (nIndex >= 0 && nIndex < m_ListBox.GetCount())
m_ListBox.SetCurSel(nIndex);
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.