www.pudn.com > PropertyListCtrl.rar > InPlaceComboBoxImp.cpp


// InPlaceComboBoxImp.cpp : implementation file
//
/////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1999, Stefan Belopotocan, http://welcome.to/StefanBelopotocan
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "InPlaceComboBoxImp.h"

#include "UserMessageID.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define DEFAULT_IPLISTBOX_HEIGHT 16 * 8

/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBEditImp

BOOL CInPlaceCBEditImp::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
CWnd* pOwner = GetOwner();
WPARAM nChar = pMsg->wParam;

switch(nChar)
{
case VK_ESCAPE:
case VK_RETURN:
case VK_TAB:
::PeekMessage(pMsg, NULL, NULL, NULL, PM_REMOVE);
pOwner->GetParent()->SetFocus();
return TRUE;
case VK_UP:
case VK_DOWN:
pOwner->SendMessage(WM_USER_ON_NEW_SELECTION, nChar);
return TRUE;
default:
;
}
}

return CEdit::PreTranslateMessage(pMsg);
}

BEGIN_MESSAGE_MAP(CInPlaceCBEditImp, CEdit)
//{{AFX_MSG_MAP(CInPlaceCBEditImp)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBEditImp message handlers

BOOL CInPlaceCBEditImp::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBListBoxImp

CInPlaceCBListBoxImp::CInPlaceCBListBoxImp()
{
}

CInPlaceCBListBoxImp::~CInPlaceCBListBoxImp()
{
}

BEGIN_MESSAGE_MAP(CInPlaceCBListBoxImp, CListBox)
//{{AFX_MSG_MAP(CInPlaceCBListBoxImp)
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBListBoxImp message handlers

void CInPlaceCBListBoxImp::ProcessSelected(bool bProcess)
{
ReleaseCapture();

CWnd* pOwner = GetOwner();

if(bProcess)
{
int nSelectedItem = GetCurSel();
pOwner->SendMessage(WM_USER_ON_SELECTION_OK, nSelectedItem, GetItemData(nSelectedItem));
}
else
pOwner->SendMessage(WM_USER_ON_SELECTION_CANCEL);
}

void CInPlaceCBListBoxImp::OnLButtonUp(UINT nFlags, CPoint point)
{
CListBox::OnLButtonUp(nFlags, point);

CRect rect;
GetClientRect(rect);

if(rect.PtInRect(point))
ProcessSelected();
//else
// ReleaseCapture();
}

BOOL CInPlaceCBListBoxImp::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
case VK_RETURN:
ProcessSelected();
return TRUE;
case VK_ESCAPE:
case VK_TAB:
ProcessSelected(false);
return TRUE;
default:
;
}
}

return CListBox::PreTranslateMessage(pMsg);
}

#if 0
/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBListCtrlImp

CInPlaceCBListCtrlImp::CInPlaceCBListCtrlImp()
{
}

CInPlaceCBListCtrlImp::~CInPlaceCBListCtrlImp()
{
}

int CInPlaceCBListCtrlImp::GetCount() const
{
return GetItemCount();
}

void CInPlaceCBListCtrlImp::GetText(int nIndex, CString&amt; strText) const
{
strText = GetItemText(nIndex, 0);
}

int CInPlaceCBListCtrlImp::SetCurSel(int nSelect)
{
return SetItemState(nSelect, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED) ? 0 : LB_ERR;
}

int CInPlaceCBListCtrlImp::AddString(LPCTSTR pStrText)
{
return InsertItem(GetItemCount(), pStrText);
}

void CInPlaceCBListCtrlImp::ResetContent()
{
DeleteAllItems();
}

BEGIN_MESSAGE_MAP(CInPlaceCBListCtrlImp, CListCtrl)
//{{AFX_MSG_MAP(CInPlaceCBListCtrlImp)
ON_WM_KILLFOCUS()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CInPlaceCBListCtrlImp message handlers

void CInPlaceCBListCtrlImp::OnKillFocus(CWnd* pNewWnd)
{
CListCtrl::OnKillFocus(pNewWnd);

GetOwner()->SendMessage(WM_USER_ON_SELECTION_CANCEL);
}

void CInPlaceCBListCtrlImp::ProcessSelected()
{
int nSelectedItem = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);

GetOwner()->SendMessage(WM_USER_ON_SELECTION_OK, nSelectedItem, GetItemData(nSelectedItem));
}

void CInPlaceCBListCtrlImp::OnLButtonUp(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonUp(nFlags, point);

ProcessSelected();
}

BOOL CInPlaceCBListCtrlImp::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
if(pMsg->wParam == VK_RETURN)
{
ProcessSelected();
return TRUE;
}
}

return CListCtrl::PreTranslateMessage(pMsg);
}
#endif


/////////////////////////////////////////////////////////////////////////////
// CInPlaceComboBoxImp

int CInPlaceComboBoxImp::m_nButtonDx = ::GetSystemMetrics(SM_CXHSCROLL);

IMPLEMENT_DYNAMIC(CInPlaceComboBoxImp, CWnd)

CInPlaceComboBoxImp::CInPlaceComboBoxImp()
{
m_nCurrentSelection = -1;
}

CInPlaceComboBoxImp* CInPlaceComboBoxImp::CreateInPlaceComboBox(CWnd* pWndParent, CRect&amt; rect)
{
CInPlaceComboBoxImp* pInPlaceComboBox = (CInPlaceComboBoxImp*)new CInPlaceComboBoxImp;

pInPlaceComboBox->Create(NULL, "", WS_VISIBLE|WS_CHILD, rect, pWndParent, 1);

return pInPlaceComboBox;
}

BEGIN_MESSAGE_MAP(CInPlaceComboBoxImp, CWnd)
//{{AFX_MSG_MAP(CInPlaceComboBoxImp)
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SETFOCUS()
ON_WM_LBUTTONDOWN()
ON_MESSAGE(WM_USER_ON_SELECTION_OK, OnSelectionOk)
ON_MESSAGE(WM_USER_ON_SELECTION_CANCEL, OnSelectionCancel)
ON_MESSAGE(WM_USER_ON_NEW_SELECTION, OnNewSelection)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CInPlaceComboBoxImp message handlers

int CInPlaceComboBoxImp::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CWnd::OnCreate(lpCreateStruct) == -1)
return -1;

CRect rect;
GetClientRect(rect);
rect.DeflateRect(0, 1);
rect.right -= m_nButtonDx;

CWnd* pParent = GetParent();
ASSERT(pParent != NULL);

CFont* pFont = pParent->GetFont();

// Vstupný riadok
m_wndEdit.Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL, rect, this, 2);
m_wndEdit.SetOwner(this);
m_wndEdit.SetFont(pFont);

// Zoznam položiek
rect.right += m_nButtonDx - 1;
rect.top = rect.bottom + 2;
rect.bottom += 100;

ClientToScreen(rect);
pParent = pParent->GetParent();
pParent->ScreenToClient(rect);

m_wndList.Create(WS_BORDER|WS_CHILD|WS_VSCROLL, rect, pParent, 3);
m_wndList.SetOwner(this);
m_wndList.SetFont(pFont);

return 0;
}

void CInPlaceComboBoxImp::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);

m_wndEdit.SetWindowPos(NULL, 0, 0, cx - m_nButtonDx, cy, SWP_NOZORDER|SWP_NOMOVE);
}

void CInPlaceComboBoxImp::MoveControl(CRect&amt; rect)
{
CRect prevRect;
GetClientRect(prevRect);

CWnd* pParent = GetParent();

// Prekresli predošlú pozíciu
ClientToScreen(prevRect);
pParent->ScreenToClient(prevRect);
pParent->InvalidateRect(prevRect);

// Nová pozícia
MoveWindow(rect, FALSE);

pParent->ClientToScreen(rect);
pParent = pParent->GetParent();
pParent->ScreenToClient(rect);

m_wndList.SetWindowPos(NULL, rect.left, rect.bottom + 1, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
}

void CInPlaceComboBoxImp::ResetListBoxHeight()
{
CRect rect;

GetClientRect(rect);
rect.right -= 1;

int nItems = m_wndList.GetCount();
int nListBoxHeight = nItems > 0 ? nItems * m_nButtonDx : DEFAULT_IPLISTBOX_HEIGHT;

if(nListBoxHeight > DEFAULT_IPLISTBOX_HEIGHT)
nListBoxHeight = DEFAULT_IPLISTBOX_HEIGHT;

m_wndList.SetWindowPos(NULL, 0, 0, rect.Width(), nListBoxHeight, SWP_NOZORDER|SWP_NOMOVE);
}

void CInPlaceComboBoxImp::OnPaint()
{
CPaintDC dc(this);

// Nakresli tlačítko
CRect rect;

GetClientRect(rect);
rect.left = rect.right - m_nButtonDx;

#if 1
dc.DrawFrameControl(rect, DFC_SCROLL, m_wndList.IsWindowVisible() ?
DFCS_SCROLLDOWN|DFCS_PUSHED : DFCS_SCROLLDOWN);
#else
dc.DrawFrameControl(rect, DFC_SCROLL, m_wndList.IsWindowVisible() ?
DFCS_SCROLLDOWN|DFCS_PUSHED|DFCS_FLAT : DFCS_SCROLLDOWN|DFCS_FLAT);
#endif
}

BOOL CInPlaceComboBoxImp::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}

void CInPlaceComboBoxImp::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);

CRect rect;
GetClientRect(rect);

CRect rectButton(rect);
rectButton.left = rectButton.right - m_nButtonDx;

if(rectButton.PtInRect(point))
{
int nDoAction = m_wndList.IsWindowVisible() ? SW_HIDE : SW_SHOW;

m_wndList.ShowWindow(nDoAction);
InvalidateRect(rectButton, FALSE);

if(nDoAction == SW_SHOW)
{
m_wndList.SetFocus();
m_wndList.SetCapture();
}
}
}

void CInPlaceComboBoxImp::OnSetFocus(CWnd* pOldWnd)
{
CWnd::OnSetFocus(pOldWnd);

m_wndEdit.SetFocus();
}

void CInPlaceComboBoxImp::HideListBox()
{
m_wndList.ShowWindow(SW_HIDE);

CRect rectButton;

GetClientRect(rectButton);
rectButton.left = rectButton.right - m_nButtonDx;

InvalidateRect(rectButton, FALSE);

m_wndEdit.SetFocus();
}

LRESULT CInPlaceComboBoxImp::OnSelectionOk(WPARAM wParam, LPARAM /*lParam*/)
{
HideListBox();

SetCurSelToEdit(m_nCurrentSelection = int(wParam));

GetOwner()->SendMessage(WM_USER_SET_DATA);

return TRUE;
}

LRESULT CInPlaceComboBoxImp::OnSelectionCancel(WPARAM /*wParam*/, LPARAM /*lParam*/)
{
HideListBox();

return TRUE;
}

LRESULT CInPlaceComboBoxImp::OnNewSelection(WPARAM wParam, LPARAM /*lParam*/)
{
int nItems = m_wndList.GetCount();

if(nItems > 0)
{
if(wParam == VK_UP)
{
if(m_nCurrentSelection > 0)
SetCurSel(m_nCurrentSelection - 1);
}
else
{
if(m_nCurrentSelection < nItems - 1)
SetCurSel(m_nCurrentSelection + 1);
}
}

return TRUE;
}

void CInPlaceComboBoxImp::SetCurSelToEdit(int nSelect)
{
CString strText;

if(nSelect != -1)
m_wndList.GetText(nSelect, strText);

m_wndEdit.SetWindowText(strText);
m_wndEdit.SetSel(0, -1);
}

int CInPlaceComboBoxImp::SetCurSel(int nSelect, bool bSendSetData)
{
if(nSelect >= m_wndList.GetCount())
return CB_ERR;


int nRet = m_wndList.SetCurSel(nSelect);

if(nRet != -1)
{
SetCurSelToEdit(nSelect);
m_nCurrentSelection = nSelect;

if(bSendSetData)
GetOwner()->SendMessage(WM_USER_SET_DATA);
}

return nRet;
}

CString CInPlaceComboBoxImp::GetTextData() const
{
CString strText;

if(m_nCurrentSelection != -1)
m_wndList.GetText(m_nCurrentSelection, strText);

return strText;
}

int CInPlaceComboBoxImp::AddString(LPCTSTR pStrText, DWORD nData)
{
int nIndex = m_wndList.AddString(pStrText);

return m_wndList.SetItemData(nIndex, nData);
}

void CInPlaceComboBoxImp::ResetContent()
{
m_wndList.ResetContent();

m_nCurrentSelection = -1;
}