CListCtrl带编辑功能与下拉功能的本质即在列表中嵌入CEdit和CComboBox控件,其具体代码如下所示:
//InPlaceEdit.h
#if
!defined(AFX_INPLACEEDIT_H__175AEDFF_731E_4721_8399_DE406A465861__INCLUDED_)
#define
AFX_INPLACEEDIT_H__175AEDFF_731E_4721_8399_DE406A465861__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CInPlaceEdit : public CEdit
{
public:
// Implementation
// Returns the
instance of the class
static CInPlaceEdit* GetInstance();
// Deletes the instance of the class
static void
DeleteInstance();
// Creates the Windows edit control and attaches it to the
object
// Shows the edit ctrl
BOOL ShowEditCtrl(DWORD dwStyle,
const RECT& rCellRect, CWnd* pParentWnd,
UINT uiResourceID, int iRowIndex, int
iColumnIndex,
CString&
strValidChars, CString& rstrCurSelection);
// Overrides
// ClassWizard generated virtual function
overrides
//{{AFX_VIRTUAL(CInPlaceEdit)
public:
virtual
BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
// Attributes
// afx_msg void OnPaste(WPARAM wParam, LPARAM
lParam);
protected:
// Generated message map
functions
//{{AFX_MSG(CInPlaceEdit)
afx_msg void
OnKillFocus(CWnd* pNewWnd);
afx_msg void OnChar(UINT nChar, UINT
nRepCnt, UINT nFlags);
afx_msg int OnCreate(LPCREATESTRUCT
lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
// Implementation
// Constructor
CInPlaceEdit();
// Hide the copy constructor and operator =
CInPlaceEdit
(CInPlaceEdit&) {}
operator = (CInPlaceEdit) {}
//
Destructor
virtual ~CInPlaceEdit();
// Attributes
// Index of the item in the list control
int m_iRowIndex;
// Index of the subitem in the list control
int
m_iColumnIndex;
// To indicate whether ESC key was pressed
BOOL
m_bESC;
// Valid characters
CString
m_strValidChars;
// Singleton instance
static CInPlaceEdit* m_pInPlaceEdit;
// Previous string value in the edit control
CString
m_strWindowText;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional
declarations immediately before the previous line.
#endif //
!defined(AFX_INPLACEEDIT_H__175AEDFF_731E_4721_8399_DE406A465861__INCLUDED_)
//InPlaceEdit.cpp
#include
"stdafx.h"
#include "InPlaceEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char
THIS_FILE[] = __FILE__;
#endif
#define CTRL_C 0x3
#define CTRL_V 0x16
#define
CTRL_X 0x18
/////////////////////////////////////////////////////////////////////////////
//
CInPlaceEdit
CInPlaceEdit* CInPlaceEdit::m_pInPlaceEdit = NULL;
CInPlaceEdit::CInPlaceEdit()
{
m_iRowIndex=
-1;
m_iColumnIndex = -1;
m_bESC =
FALSE;
m_strValidChars.Empty();
}
CInPlaceEdit::~CInPlaceEdit()
{
}
BEGIN_MESSAGE_MAP(CInPlaceEdit,
CEdit)
//{{AFX_MSG_MAP(CInPlaceEdit)
ON_WM_KILLFOCUS()
ON_WM_CHAR()
ON_WM_CREATE()
//}}AFX_MSG_MAP
// ON_MESSAGE(WM_PASTE,
OnPaste)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
CInPlaceEdit message handlers
/*
void CInPlaceEdit::OnPaste(WPARAM ,
LPARAM )
{
if
(m_strValidChars.IsEmpty())
{
return;
}
CString strFromClipboard;
// get the text from clipboard
if(OpenClipboard())
{
HANDLE l_hData =
GetClipboardData(CF_TEXT);
if(NULL == l_hData)
{
return;
}
char
*l_pBuffer = (char*)GlobalLock(l_hData);
if(NULL != l_pBuffer)
{
strFromClipboard = l_pBuffer;
}
GlobalUnlock(l_hData);
CloseClipboard();
}
// Validate the characters before pasting
for(int iCounter_ =
0; iCounter_ < strFromClipboard.GetLength();
iCounter_++)
{
if (-1 ==
m_strValidChars.Find(strFromClipboard.GetAt(iCounter_)))
{
return;
}
}
//let
the individual control handle other
processing
CEdit::Default();
}
*/
void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
// TODO: Add your
message handler code here
// Get the text in the edit ctrl
CString
strEdit;
GetWindowText(strEdit);
// if(strEdit.GetLength() == 1)
// strEdit = _T("0") +
strEdit;
// Send Notification to parent of edit ctrl
LV_DISPINFO
dispinfo;
dispinfo.hdr.hwndFrom =
GetParent()->m_hWnd;
dispinfo.hdr.idFrom =
GetDlgCtrlID();
dispinfo.hdr.code = LVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT;
dispinfo.item.iItem =
m_iRowIndex;
dispinfo.item.iSubItem =
m_iColumnIndex;
dispinfo.item.pszText = m_bESC ?
LPTSTR((LPCTSTR)m_strWindowText) :
LPTSTR((LPCTSTR)strEdit);
dispinfo.item.cchTextMax = m_bESC ?
m_strWindowText.GetLength() :
strEdit.GetLength();
GetParent()->SendMessage(WM_NOTIFY,
GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
PostMessage(WM_CLOSE);
}
void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call
default
if ((m_strValidChars.IsEmpty()) || ((-1 !=
m_strValidChars.Find(static_cast<TCHAR> (nChar))) ||
(nChar == VK_BACK) || (nChar == CTRL_C) || (nChar == CTRL_V) ||
(nChar == CTRL_X)))
{
CEdit::OnChar(nChar, nRepCnt,
nFlags);
}
else
{
MessageBeep(MB_ICONEXCLAMATION);
return;
}
}
BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add
your specialized code here and/or call the base class
if (WM_KEYDOWN ==
pMsg->message && (VK_ESCAPE == pMsg->wParam || VK_RETURN ==
pMsg->wParam))
{
if (VK_ESCAPE ==
pMsg->wParam)
{
m_bESC =
TRUE;
}
GetParent()->SetFocus();
return
TRUE;
}
return CEdit::PreTranslateMessage(pMsg);
}
int CInPlaceEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if
(CEdit::OnCreate(lpCreateStruct) == -1)
return
-1;
// TODO: Add your specialized creation code
here
// Set the proper font
CFont* pFont =
GetParent()->GetFont();
SetFont(pFont);
ShowWindow(SW_SHOW);
SetWindowText(m_strWindowText);
SetSel(0,
-1);
SetFocus();
return 0;
}
CInPlaceEdit* CInPlaceEdit::GetInstance()
{
if(m_pInPlaceEdit ==
NULL)
{
m_pInPlaceEdit = new
CInPlaceEdit;
}
return m_pInPlaceEdit;
}
void CInPlaceEdit::DeleteInstance()
{
delete
m_pInPlaceEdit;
m_pInPlaceEdit = NULL;
}
BOOL CInPlaceEdit::ShowEditCtrl(DWORD dwStyle, const RECT &rCellRect,
CWnd* pParentWnd,
UINT
uiResourceID, int iRowIndex, int
iColumnIndex,
CString&
strValidChars, CString& rstrCurSelection)
{
m_iRowIndex =
iRowIndex;
m_iColumnIndex = iColumnIndex;
m_strValidChars =
strValidChars;
m_strWindowText = rstrCurSelection;
m_bESC =
FALSE;
if (NULL == m_pInPlaceEdit->m_hWnd)
{
return m_pInPlaceEdit->Create(dwStyle, rCellRect,
pParentWnd, uiResourceID);
}
return TRUE;
}
//InPlaceCombo.h
#if
!defined(AFX_INPLACECOMBO_H__2E04D8D9_827F_4FBD_9E87_30AF8C31639D__INCLUDED_)
#define
AFX_INPLACECOMBO_H__2E04D8D9_827F_4FBD_9E87_30AF8C31639D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CInPlaceCombo : public CComboBox
{
public:
//
Implementation
// Returns the instance of the
class
static CInPlaceCombo* GetInstance();
// Deletes the instance of the class
static void
DeleteInstance();
// Creates the Windows combo control and attaches it to the object, if
needed and shows the combo ctrl
BOOL ShowComboCtrl(DWORD dwStyle, const
CRect& rCellRect, CWnd* pParentWnd, UINT
uiResourceID,
int iRowIndex, int
iColumnIndex, CStringList* pDropDownList, CString strCurSelecetion = "", int
iCurSel = -1);
// Overrides
// ClassWizard generated virtual function
overrides
//{{AFX_VIRTUAL(CInPlaceCombo)
public:
virtual
BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
protected:
// Generated message map
functions
//{{AFX_MSG(CInPlaceCombo)
afx_msg int
OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnKillFocus(CWnd*
pNewWnd);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT
nFlags);
afx_msg void
OnCloseup();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
// Implementation
// Constructor
CInPlaceCombo();
// Hide the copy constructor and operator =
CInPlaceCombo
(CInPlaceCombo&) {}
operator = (CInPlaceCombo) {}
// Destructor
virtual ~CInPlaceCombo();
// Attributes
// Index of the item in the list control
int m_iRowIndex;
// Index of the subitem in the list control
int
m_iColumnIndex;
// To indicate whether ESC key was pressed
BOOL
m_bESC;
// Singleton instance
static CInPlaceCombo*
m_pInPlaceCombo;
// Previous selected string value in the combo control
CString
m_strWindowText;
// List of items to be shown in the drop down
CStringList
m_DropDownList;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional
declarations immediately before the previous line.
#endif //
!defined(AFX_INPLACECOMBO_H__2E04D8D9_827F_4FBD_9E87_30AF8C31639D__INCLUDED_)
//InPlaceCombo.cpp
#include
"stdafx.h"
#include "InPlaceCombo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char
THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
CInPlaceCombo
CInPlaceCombo* CInPlaceCombo::m_pInPlaceCombo = NULL;
CInPlaceCombo::CInPlaceCombo()
{
m_iRowIndex =
-1;
m_iColumnIndex = -1;
m_bESC = FALSE;
}
CInPlaceCombo::~CInPlaceCombo()
{
}
BEGIN_MESSAGE_MAP(CInPlaceCombo,
CComboBox)
//{{AFX_MSG_MAP(CInPlaceCombo)
ON_WM_CREATE()
ON_WM_KILLFOCUS()
ON_WM_CHAR()
ON_CONTROL_REFLECT(CBN_CLOSEUP,
OnCloseup)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
CInPlaceCombo message handlers
int CInPlaceCombo::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if
(CComboBox::OnCreate(lpCreateStruct) == -1)
{
return
-1;
}
// Set the proper font
CFont* pFont =
GetParent()->GetFont();
SetFont(pFont);
SetFocus();
ResetContent();
for (POSITION Pos_ =
m_DropDownList.GetHeadPosition(); Pos_ !=
NULL;)
{
AddString((LPCTSTR)
(m_DropDownList.GetNext(Pos_)));
}
return 0;
}
BOOL CInPlaceCombo::PreTranslateMessage(MSG* pMsg)
{
// If the
message if for "Enter" or "Esc"
// Do not process
if
(pMsg->message == WM_KEYDOWN)
{
if(pMsg->wParam ==
VK_RETURN || pMsg->wParam ==
VK_ESCAPE)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
//
DO NOT process further
return
TRUE;
}
}
return
CComboBox::PreTranslateMessage(pMsg);
}
void CInPlaceCombo::OnKillFocus(CWnd* pNewWnd)
{
CComboBox::OnKillFocus(pNewWnd);
// Get the
current selection text
CString str;
GetWindowText(str);
// Send Notification to parent of ListView ctrl
LV_DISPINFO
dispinfo;
dispinfo.hdr.hwndFrom =
GetParent()->m_hWnd;
dispinfo.hdr.idFrom =
GetDlgCtrlID();
dispinfo.hdr.code = LVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT;
dispinfo.item.iItem =
m_iRowIndex;
dispinfo.item.iSubItem =
m_iColumnIndex;
dispinfo.item.pszText = m_bESC ?
LPTSTR((LPCTSTR)m_strWindowText) :
LPTSTR((LPCTSTR)str);
dispinfo.item.cchTextMax = m_bESC ?
m_strWindowText.GetLength() :
str.GetLength();
GetParent()->SendMessage(WM_NOTIFY,
GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
// Close the control
PostMessage(WM_CLOSE);
}
void CInPlaceCombo::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// If the key is "Esc" set focus back to the list
control
if (nChar == VK_ESCAPE || nChar ==
VK_RETURN)
{
if (nChar ==
VK_ESCAPE)
{
m_bESC =
TRUE;
}
GetParent()->SetFocus();
return;
}
CComboBox::OnChar(nChar,
nRepCnt, nFlags);
}
void CInPlaceCombo::OnCloseup()
{
// Set the focus to the parent
list control
GetParent()->SetFocus();
}
CInPlaceCombo* CInPlaceCombo::GetInstance()
{
if(m_pInPlaceCombo
== NULL)
{
m_pInPlaceCombo = new
CInPlaceCombo;
}
return m_pInPlaceCombo;
}
void CInPlaceCombo::DeleteInstance()
{
delete
m_pInPlaceCombo;
m_pInPlaceCombo = NULL;
}
BOOL CInPlaceCombo::ShowComboCtrl(DWORD dwStyle, const CRect &rCellRect,
CWnd* pParentWnd, UINT
uiResourceID,
int
iRowIndex, int iColumnIndex, CStringList* pDropDownList,
CString
strCurSelecetion /*= ""*/, int iCurSel /*= -1*/)
{
m_iRowIndex = iRowIndex;
m_iColumnIndex =
iColumnIndex;
m_bESC =
FALSE;
m_DropDownList.RemoveAll();
m_DropDownList.AddTail(pDropDownList);
BOOL bRetVal = TRUE;
if (-1 != iCurSel)
{
GetLBText(iCurSel,
m_strWindowText);
}
else if (!strCurSelecetion.IsEmpty())
{
m_strWindowText =
strCurSelecetion;
}
if (NULL ==
m_pInPlaceCombo->m_hWnd)
{
bRetVal =
m_pInPlaceCombo->Create(dwStyle, rCellRect, pParentWnd, uiResourceID);
}
SetCurSel(iCurSel);
return bRetVal;
}
//MyComboListCtrl.h
#if
!defined(AFX_MYCOMBOLISTCTRL_H__9089600F_374F_4BFC_9482_DEAC0E7133E8__INCLUDED_)
#define
AFX_MYCOMBOLISTCTRL_H__9089600F_374F_4BFC_9482_DEAC0E7133E8__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//the max listCtrl columns
#define MAX_LISTCTRL_COLUMNS 100
#include <afxtempl.h>
#include <afxcmn.h>
class CInPlaceCombo;
class CInPlaceEdit;
// User define message
// This message is posted to the parent
// The
message can be handled to make the necessary validations, if any
#define
WM_VALIDATE WM_USER + 0x7FFD
// User define message
// This message is posted to the parent
// The
message should be handled to spcify the items to the added to the
combo
#define WM_SET_ITEMS WM_USER + 0x7FFC
class CMyComboListCtrl : public CListCtrl
{
public:
//
Implementation
typedef enum
{MODE_READONLY,MODE_DIGITAL_EDIT,MODE_TEXT_EDIT,MODE_COMBO}
COMBOLISTCTRL_COLUMN_MODE;
// Constructor
CMyComboListCtrl();
// Destructor
virtual ~CMyComboListCtrl();
// Sets/Resets the column which support the in place combo
box
void SetComboColumns(int iColumnIndex, bool bSet =
true);
// Sets/Resets the column which support the in place
edit control
void SetReadOnlyColumns(int iColumnIndex, bool bSet =
true);
// Sets the valid characters for the edit ctrl
void
SetValidEditCtrlCharacters(CString& rstrValidCharacters);
// Sets the vertical scroll
void EnableVScroll(bool bEnable =
true);
// Sets the horizontal scroll
void EnableHScroll(bool bEnable
= true);
//insert column
int CMyComboListCtrl::InsertColumn(int
nCol,LPCTSTR lpszColumnHeading,int nFormat = LVCFMT_LEFT,int nWidth = -1,int
nSubItem = -1);
//Get column counts
int GetColumnCounts();
//delete all column
void DeleteAllColumn();
//set column Valid char string
void
SetColumnValidEditCtrlCharacters(CString &rstrValidCharacters,int column =
-1);
// Overrides
// ClassWizard generated virtual function
overrides
//{{AFX_VIRTUAL(CMyComboListCtrl)
//}}AFX_VIRTUAL
protected:
// Methods
// Generated message map
functions
//{{AFX_MSG(CMyComboListCtrl)
afx_msg void
OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg
void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*
pScrollBar);
afx_msg void OnLButtonDown(UINT nFlags, CPoint
point);
afx_msg void OnEndLabelEdit(NMHDR* pNMHDR, LRESULT*
pResult);
afx_msg void OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT*
pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
// Implementation
// Returns the row & column index of the column on which mouse
click event has occured
bool HitTestEx(CPoint& rHitPoint, int*
pRowIndex, int* pColumnIndex) const;
// Creates and displays the in place combo box
CInPlaceCombo*
ShowInPlaceList(int iRowIndex, int iColumnIndex, CStringList&
rComboItemsList,
CString
strCurSelecetion = "", int iSel = -1);
// Creates and displays the in place edit
control
CInPlaceEdit* ShowInPlaceEdit(int iRowIndex, int iColumnIndex,
CString& rstrCurSelection);
// Calculates the cell rect
void CalculateCellRect(int
iColumnIndex, int iRowIndex, CRect& robCellRect);
// Checks whether column supports in place combo box
bool
IsCombo(int iColumnIndex);
// Checks whether column is read only
bool IsReadOnly(int
iColumnIndex);
// Scrolls the list ctrl to bring the in place ctrl to the
view
void ScrollToView(int iColumnIndex, /*int iOffSet, */CRect&
obCellRect);
// Attributes
// List of columns that support the in place
combo box
CList<int, int> m_ComboSupportColumnsList;
// List of columns that are read only
CList<int, int>
m_ReadOnlyColumnsList;
// Valid characters
CString m_strValidEditCtrlChars;
// The window style of the in place edit ctrl
DWORD
m_dwEditCtrlStyle;
// The window style of the in place combo ctrl
DWORD
m_dwDropDownCtrlStyle;
//columnCounts
int m_iColumnCounts;
//column types
COMBOLISTCTRL_COLUMN_MODE
m_modeColumn[MAX_LISTCTRL_COLUMNS];
//column
CString
m_strValidChars[MAX_LISTCTRL_COLUMNS];
//int m_
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional
declarations immediately before the previous line.
#endif //
!defined(AFX_MYCOMBOLISTCTRL_H__9089600F_374F_4BFC_9482_DEAC0E7133E8__INCLUDED_)
//MyComboListCtrl.cpp
#include
"stdafx.h"
#include "MyComboListCtrl.h"
#include
"InPlaceCombo.h"
#include "InPlaceEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char
THIS_FILE[] = __FILE__;
#endif
//#defines
#define FIRST_COLUMN 0
#define
MIN_COLUMN_WIDTH 10
#define
MAX_DROP_DOWN_ITEM_COUNT 10
/////////////////////////////////////////////////////////////////////////////
//
CMyComboListCtrl
CMyComboListCtrl::CMyComboListCtrl()
{
m_iColumnCounts =
0;
m_ComboSupportColumnsList.RemoveAll();
m_ReadOnlyColumnsList.RemoveAll();
m_strValidEditCtrlChars.Empty();
m_dwEditCtrlStyle
= ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT |
ES_NOHIDESEL;
m_dwDropDownCtrlStyle = WS_BORDER | WS_CHILD | WS_VISIBLE
| ES_AUTOHSCROLL | ES_AUTOVSCROLL |
CBS_DROPDOWNLIST |
CBS_DISABLENOSCROLL;
}
CMyComboListCtrl::~CMyComboListCtrl()
{
CInPlaceCombo::DeleteInstance();
CInPlaceEdit::DeleteInstance();
}
BEGIN_MESSAGE_MAP(CMyComboListCtrl,
CListCtrl)
//{{AFX_MSG_MAP(CMyComboListCtrl)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_LBUTTONDOWN()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT,
OnEndLabelEdit)
ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT,
OnBeginLabelEdit)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
CMyComboListCtrl message handlers
CInPlaceCombo* CMyComboListCtrl::ShowInPlaceList(int iRowIndex, int
iColumnIndex, CStringList& rComboItemsList,
CString strCurSelecetion /*= ""*/, int iSel /*= -1*/)
{
// The
returned obPointer should not be saved
// Make sure that the
item is visible
if (!EnsureVisible(iRowIndex,
TRUE))
{
return NULL;
}
// Make sure that iColumnIndex is valid
CHeaderCtrl* pHeader
= static_cast<CHeaderCtrl*> (GetDlgItem(FIRST_COLUMN));
int iColumnCount = pHeader->GetItemCount();
if (iColumnIndex >= iColumnCount || GetColumnWidth(iColumnIndex)
< MIN_COLUMN_WIDTH)
{
return NULL;
}
// Calculate the rectangle specifications for the combo
box
CRect obCellRect(0, 0, 0,
0);
CalculateCellRect(iColumnIndex, iRowIndex, obCellRect);
int iHeight = obCellRect.Height();
int iCount = (int
)rComboItemsList.GetCount();
iCount = (iCount < MAX_DROP_DOWN_ITEM_COUNT) ?
iCount + MAX_DROP_DOWN_ITEM_COUNT : (MAX_DROP_DOWN_ITEM_COUNT +
1);
obCellRect.bottom += iHeight * iCount;
// Create the in place combobox
CInPlaceCombo* pInPlaceCombo =
CInPlaceCombo::GetInstance();
pInPlaceCombo->ShowComboCtrl(m_dwDropDownCtrlStyle,
obCellRect, this, 0, iRowIndex, iColumnIndex, &rComboItemsList,
strCurSelecetion,
iSel);
return pInPlaceCombo;
}
CInPlaceEdit* CMyComboListCtrl::ShowInPlaceEdit(int iRowIndex, int
iColumnIndex, CString& rstrCurSelection)
{
// Create an in-place
edit control
CInPlaceEdit* pInPlaceEdit =
CInPlaceEdit::GetInstance();
CRect obCellRect(0, 0, 0,
0);
CalculateCellRect(iColumnIndex, iRowIndex,
obCellRect);
pInPlaceEdit->ShowEditCtrl(m_dwEditCtrlStyle,
obCellRect, this, 0,
iRowIndex,
iColumnIndex,
m_strValidChars[iColumnIndex], rstrCurSelection);
return pInPlaceEdit;
}
void CMyComboListCtrl::OnHScroll(UINT iSBCode, UINT iPos, CScrollBar*
pScrollBar)
{
// TODO: Add your message handler code here and/or
call default
if (GetFocus() !=
this)
{
SetFocus();
}
CListCtrl::OnHScroll(iSBCode, iPos, pScrollBar);
}
void CMyComboListCtrl::OnVScroll(UINT iSBCode, UINT iPos, CScrollBar*
pScrollBar)
{
// TODO: Add your message handler code here and/or
call default
if (GetFocus() !=
this)
{
SetFocus();
}
CListCtrl::OnVScroll(iSBCode, iPos, pScrollBar);
}
void CMyComboListCtrl::OnLButtonDown(UINT iFlags, CPoint obPoint)
{
// TODO: Add your message handler code here and/or call
default
int iColumnIndex = -1;
int iRowIndex = -1;
// Get the current column and row
if (!HitTestEx(obPoint,
&iRowIndex,
&iColumnIndex))
{
return;
}
CListCtrl::OnLButtonDown(iFlags, obPoint);
// If
column is not read only then
// If the SHIFT or CTRL key is down call
the base class
// Check the high bit of GetKeyState to determine
whether SHIFT or CTRL key is down
if ((GetKeyState(VK_SHIFT) &
0x80) || (GetKeyState(VK_CONTROL) &
0x80))
{
return;
}
// Get the current selection before creating the in place combo
box
CString strCurSelection = GetItemText(iRowIndex,
iColumnIndex);
if (-1 !=
iRowIndex)
{
UINT flag =
LVIS_FOCUSED;
if ((GetItemState(iRowIndex, flag )
& flag) == flag)
{
// Add check for
LVS_EDITLABELS
if (GetWindowLong(m_hWnd, GWL_STYLE) &
LVS_EDITLABELS)
{
// If combo
box is supported
// Create and show the in place
combo box
if
(IsCombo(iColumnIndex))
{
CStringList
obComboItemsList;
GetParent()->SendMessage(WM_SET_ITEMS,
(WPARAM)iColumnIndex, (LPARAM)&obComboItemsList);
CInPlaceCombo*
pInPlaceComboBox = ShowInPlaceList(iRowIndex, iColumnIndex, obComboItemsList,
strCurSelection);
ASSERT(pInPlaceComboBox);
// Set the
selection to previous
selection
pInPlaceComboBox->SelectString(-1,
strCurSelection);
}
// If
combo box is not read only
// Create and show the in
place edit control
else if
(!IsReadOnly(iColumnIndex))
{
CInPlaceEdit*
pInPlaceEdit = ShowInPlaceEdit(iRowIndex, iColumnIndex,
strCurSelection);
}
}
}
}
}
bool CMyComboListCtrl::HitTestEx(CPoint &obPoint, int* pRowIndex, int*
pColumnIndex) const
{
if (!pRowIndex ||
!pColumnIndex)
{
return false;
}
// Get the row index
*pRowIndex = HitTest(obPoint, NULL);
if (pColumnIndex)
{
*pColumnIndex =
0;
}
// Make sure that the ListView is in LVS_REPORT
if
((GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) !=
LVS_REPORT)
{
return false;
}
// Get the number of columns
CHeaderCtrl* pHeader =
(CHeaderCtrl*)GetDlgItem(0);
int iColumnCount = pHeader->GetItemCount();
// Get bounding rect of item and check whether obPoint falls in
it.
CRect obCellRect;
GetItemRect(*pRowIndex, &obCellRect,
LVIR_BOUNDS);
if
(obCellRect.PtInRect(obPoint))
{
// Now find the
column
for (*pColumnIndex = 0; *pColumnIndex < iColumnCount;
(*pColumnIndex)++)
{
int iColWidth =
GetColumnWidth(*pColumnIndex);
if
(obPoint.x >= obCellRect.left && obPoint.x <= (obCellRect.left +
iColWidth))
{
return
true;
}
obCellRect.left +=
iColWidth;
}
}
return false;
}
void CMyComboListCtrl::SetComboColumns(int iColumnIndex, bool bSet /*=
true*/)
{
// If the Column Index is not present && Set flag
is false
// Then do nothing
// If the Column Index is present
&& Set flag is true
// Then do nothing
POSITION Pos =
m_ComboSupportColumnsList.Find(iColumnIndex);
// If the Column Index is not present && Set flag is
true
// Then Add to list
if ((NULL == Pos) && bSet)
{
m_ComboSupportColumnsList.AddTail(iColumnIndex);
}
// If the Column Index is present && Set flag is
false
// Then Remove from list
if ((NULL != Pos) &&
!bSet)
{
m_ComboSupportColumnsList.RemoveAt(Pos);
}
}
void CMyComboListCtrl::SetReadOnlyColumns(int iColumnIndex, bool bSet /*=
true*/)
{
// If the Column Index is not present && Set flag
is false
// Then do nothing
// If the Column Index is present
&& Set flag is true
// Then do nothing
POSITION Pos =
m_ReadOnlyColumnsList.Find(iColumnIndex);
// If the Column Index is not present && Set flag is
true
// Then Add to list
if ((NULL == Pos) && bSet)
{
m_ReadOnlyColumnsList.AddTail(iColumnIndex);
}
// If the Column Index is present && Set flag is
false
// Then Remove from list
if ((NULL != Pos) &&
!bSet)
{
m_ReadOnlyColumnsList.RemoveAt(Pos);
}
}
bool CMyComboListCtrl::IsReadOnly(int iColumnIndex)
{
if
(m_ReadOnlyColumnsList.Find(iColumnIndex))
{
return
true;
}
return false;
}
bool CMyComboListCtrl::IsCombo(int iColumnIndex)
{
if
(m_ComboSupportColumnsList.Find(iColumnIndex))
{
return
true;
}
return false;
}
void CMyComboListCtrl::CalculateCellRect(int iColumnIndex, int iRowIndex,
CRect& robCellRect)
{
GetItemRect(iRowIndex, &robCellRect,
LVIR_BOUNDS);
CRect
rcClient;
GetClientRect(&rcClient);
if (robCellRect.right > rcClient.right)
{
robCellRect.right = rcClient.right;
}
ScrollToView(iColumnIndex, robCellRect);
}
void CMyComboListCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO:
Add your control notification handler code here
// Update the
item text with the new text
SetItemText(pDispInfo->item.iItem,
pDispInfo->item.iSubItem, pDispInfo->item.pszText);
GetParent()->SendMessage(WM_VALIDATE, GetDlgCtrlID(),
(LPARAM)pDispInfo);
*pResult = 0;
}
void CMyComboListCtrl::SetValidEditCtrlCharacters(CString
&rstrValidCharacters)
{
m_strValidEditCtrlChars =
rstrValidCharacters;
}
void CMyComboListCtrl::SetColumnValidEditCtrlCharacters(CString
&rstrValidCharacters,int
column)
{
if(column>MAX_LISTCTRL_COLUMNS-1)
return;
if(column
== -1)
{
for(int
i=0;i<MAX_LISTCTRL_COLUMNS;i++)
{
m_strValidChars[i]
=
rstrValidCharacters;
}
}
else
m_strValidChars[column]
= rstrValidCharacters;
}
void CMyComboListCtrl::EnableHScroll(bool bEnable /*=
true*/)
{
if
(bEnable)
{
m_dwDropDownCtrlStyle |=
WS_HSCROLL;
}
else
{
m_dwDropDownCtrlStyle
&= ~WS_HSCROLL;
}
}
void CMyComboListCtrl::EnableVScroll(bool bEnable /*=
true*/)
{
if
(bEnable)
{
m_dwDropDownCtrlStyle |=
WS_VSCROLL;
}
else
{
m_dwDropDownCtrlStyle
&= ~WS_VSCROLL;
}
}
void CMyComboListCtrl::ScrollToView(int iColumnIndex, /*int iOffSet,
*/CRect& robCellRect)
{
// Now scroll if we need to expose the
column
CRect rcClient;
GetClientRect(&rcClient);
int iColumnWidth = GetColumnWidth(iColumnIndex);
// Get the column iOffset
int iOffSet = 0;
for (int
iIndex_ = 0; iIndex_ < iColumnIndex;
iIndex_++)
{
iOffSet +=
GetColumnWidth(iIndex_);
}
// If x1 of cell rect is < x1 of ctrl rect or
// If x1 of
cell rect is > x1 of ctrl rect or **Should not ideally happen**
//
If the width of the cell extends beyond x2 of ctrl rect then
//
Scroll
CSize obScrollSize(0, 0);
if (((iOffSet + robCellRect.left) < rcClient.left) ||
((iOffSet + robCellRect.left) >
rcClient.right))
{
obScrollSize.cx = iOffSet +
robCellRect.left;
}
else if ((iOffSet + robCellRect.left +
iColumnWidth) > rcClient.right)
{
obScrollSize.cx =
iOffSet + robCellRect.left + iColumnWidth - rcClient.right;
}
Scroll(obScrollSize);
robCellRect.left -=
obScrollSize.cx;
// Set the width to the column
width
robCellRect.left += iOffSet;
robCellRect.right =
robCellRect.left + iColumnWidth;
}
void CMyComboListCtrl::OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO:
Add your control notification handler code here
if
(IsReadOnly(pDispInfo->item.iSubItem))
{
*pResult =
1;
return;
}
*pResult = 0;
}
int CMyComboListCtrl::InsertColumn(int nCol,LPCTSTR lpszColumnHeading,int
nFormat ,int nWidth,int
nSubItem)
{
m_iColumnCounts++;
return
CListCtrl::InsertColumn( nCol, lpszColumnHeading, nFormat, nWidth,
nSubItem);
}
int CMyComboListCtrl::GetColumnCounts()
{
return
m_iColumnCounts;
}
void CMyComboListCtrl::DeleteAllColumn()
{
for(int
i=0;i<m_iColumnCounts;i++)
{
DeleteColumn(0);
}
}
//应用
LRESULT
CRTUProtocolIndexInfoBaseDlg::PopulateComboList(WPARAM wParam, LPARAM
lParam)
{
// Get the Combobox window pointer
CComboBox*
pInPlaceCombo = static_cast<CComboBox *>(GetFocus());
// Get the inplace combbox top left
CRect obWindowRect;
pInPlaceCombo->GetWindowRect(&obWindowRect);
CPoint
obInPlaceComboTopLeft(obWindowRect.TopLeft());
// Get the
active list
// Get the control window rect
// If the inplace
combobox top left is in the rect then
// The control is the active
control
CWnd *pFocusWnd =
GetFocus();
pFocusWnd->GetWindowRect(&obWindowRect);
int
iColIndex = (int)wParam;
CStringList* pComboList =
reinterpret_cast<CStringList
*>(lParam);
pComboList->RemoveAll();
if(obWindowRect.PtInRect(obInPlaceComboTopLeft))
{
if((iColIndex
== 1) || (iColIndex ==
2))
{
pComboList->AddTail(_T("是"));
pComboList->AddTail(_T("否"));
}
}
return
true;
}
//初始化列
CFont
font;
VERIFY(font.CreateFont(
18,
// nHeight
0,
// nWidth
0,
// nEscapement
0,
// nOrientation
FW_NORMAL,
// nWeight
FALSE,
// bItalic
FALSE,
// bUnderline
0,
// cStrikeOut
ANSI_CHARSET,
// nCharSet
OUT_DEFAULT_PRECIS, //
nOutPrecision
CLIP_DEFAULT_PRECIS, //
nClipPrecision
DEFAULT_QUALITY, //
nQuality
DEFAULT_PITCH | FF_SWISS, //
nPitchAndFamily
_T("宋体")));
m_CtrlListBaseInfo.SetFont(&font);
m_CtrlListBaseInfo.SetExtendedStyle(LVS_EX_FULLROWSELECT
| LVS_EX_GRIDLINES);
m_CtrlListBaseInfo.InsertColumn(0, _T("序号"), LVCFMT_CENTER,
40);
m_CtrlListBaseInfo.InsertColumn(1, _T("有效标志"), LVCFMT_CENTER,
60);
m_CtrlListBaseInfo.SetReadOnlyColumns(0); //read
only
m_CtrlListBaseInfo.SetReadOnlyColumns(1); //read
only
m_CtrlListBaseInfo.SetComboColumns(1,
TRUE);
m_CtrlListBaseInfo.EnableVScroll();
m_CtrlListBaseInfo.InsertColumn(2, _T("功能码"), LVCFMT_CENTER,
80);
CString
strValidChars(_T("0123456789ABCDEFabcdef"));
m_CtrlListBaseInfo.SetColumnValidEditCtrlCharacters(strValidChars,
2);//HEX only edit