WinCE下带编辑与下拉功能的ListCtrl

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

时间: 2024-10-06 14:48:49

WinCE下带编辑与下拉功能的ListCtrl的相关文章

使用google自带包实现下拉刷新功能

android 实现下拉刷新有很多开源的源码可以用 比如 :PullToRefreshListView  使用起来也很方便 现在还可以直接使用google libs下面的 android-support-v4.jar 这个包来实现了,请更新你的sdk到最新 使用 xml 布局 <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"

Android 聊天表情输入、表情翻页带效果、下拉刷新聊天记录

经过一个星期的折腾,终于做完了这个Android 聊天表情输入.表情翻页带效果.下拉刷新聊天记录.这只是一个单独聊天表情的输入,以及聊天的效果实现.因为我没有写服务器,所以没有双方聊天的效果.主要是聊天中表情的选择,发送.表情翻页带有不同的效果.我在主要代码中都写了注释.下面看代码实现.附上本文源码,代码较多. 下载地址:点击 一.先看实现的效果图 二.调用接口以及设置MainActivity package com.example.activity; import java.util.Arra

自制jquery可编辑的下拉框

昨天看到QQ登录的时候,可以选择以前登录过的账户,这个东西也可以在网站登录的时候用到,所以我就想做一个这样的插件:在网上查了很多,没有找到合适自己的,所以决定自动制作一个. 原理就是一个textbox加一个ul模拟下拉框,用font模拟一个下拉按钮. 一.制作静态效果 先用css和html,做出一个应该有的样子.这里这两个我使用的是字体,可以在icomoon网站上面自己制作.用字体的好处是和输入框定位很方便,而且还可以控制大小颜色等,唯一的不足是IE6和IE7由于不支持:before选择器,导致

别怕,手把手带你撕、拉、扯下SpringMVC的外衣

提到框架,就不得不提一下看源码,我们平时总是想求大神带我们飞,然而看源码就是一个向大神学习的最直接的一种方式,然而我们每次鼓起勇气看源码前是这样的但是一点开源码,顿时代码如洪流涌入,你的内心可能是这样的所以我在之前别怕看源码,一张图搞定Mybatis的Mapper原理的时候也提到过, Mybatis的源码相对其他框架而言比较简单, 比较适合刚开始克服恐惧心理看源码实战, 由于Struts2前不久又传出安全性问题, 所以Java开发中, 表现层框架基本都是SpringMVC,那么我们就来撕.拉.扯

C#下利用正则表达式实现字符串搜索功能的方法(转)

关键字:正则表达式.元字符.字符串.匹配: 1.正则表达式简介:正则表达式提供了功能强大.灵活而又高效的方法来处:.NET框架正则表达式并入了其他正则表达式实现的: 2.字符串搜索:正则表达式语言由两种基本字符类型组成:原义(正常:一般表达式语言是一种可以编写搜索表达式的语言: 3..NET框架的正则表达式类:下面通过介绍.NET框架的正则表达式类,熟悉一下: 1.正则表达式简介 正则表达式提供了功能强大.灵活而又高效的方法来处理文本.正则表达式的全面模式匹配表示法可以快速地分析大量的文本以找到

tableView编辑模式下删除多个cell

在编辑模式下,tableView有自带的删除多个cell的方法. 这种效果自定义写也可以,但是我这里用的是系统的. 先上效果图.核心代码: _tableView.allowsMultipleSelectionDuringEditing = YES; 至于全选删除和选择一部分删除就不上具体代码了. 如果想要点击cell后的颜色,代码如下: //选中cell的背景色 UIImageView *imageView = [[UIImageView alloc]init]; imageView.backg

datagrid combobox事件更新编辑状态下的datagrid行

请问如何从上图状态 点击下拉的combobox中值然后在不取消datagrid编辑状态下更新这一行另一列的数据,达到下图这样的效果: 非常感谢! 给你的combobox  绑定一个onSelect 事件, 然后   onSelect:function(){   var index =  $(this).parent("tr").index();   $("table tr:eq("+index+")").find("td:nth-chi

npm 是node.js下带的一个包管理工具

npm 是node.js下带的一个包管理工具          npm install -g webpack webpack是一个打包工具 gulp是一个基于流的构建工具,相对其他构件工具来说,更简洁更高效 npm install -g gulp //全局安装 npm install --save-dev gulp //安装到当前项目并在package.json中添加依赖cnpm install -g -vue-cli 安装脚手架 webpack是模块化管理的工具,使用webpack可实现模块按

一分钟带你了解下MyBatis的动态SQL!

MyBatis的强大特性之一便是它的动态SQL,以前拼接的时候需要注意的空格.列表最后的逗号等,现在都可以不用手动处理了,MyBatis采用功能强大的基于OGNL的表达式来实现,下面主要介绍下. 一.if标签 if是最常用的判断语句,主要用于实现某些简单的条件选择.基本使用示例如下: <select id="queryAllUsersByName" resultType="com.example.springboot.mybatisxml.entity.User&quo