#include "stdafx.h" #include "AECListCtrl.h" #include "AECInplaceEdit.h" #include "AECInplaceComboBox.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif AECListCtrl::AECListCtrl() { } AECListCtrl::~AECListCtrl() { RemoveAllColXData(); } BEGIN_MESSAGE_MAP(AECListCtrl, CListCtrl) //{{AFX_MSG_MAP(AECListCtrl) ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit) ON_NOTIFY_REFLECT(NM_CLICK, OnClick) ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown) //}}AFX_MSG_MAP END_MESSAGE_MAP() BOOL AECListCtrl::SetColumnItemData(int nCol,void * pXData,EType eType) { CHeaderCtrl * pHead = GetHeaderCtrl(); int nCount = pHead->GetItemCount(); if(nCol > nCount) { return FALSE; } m_mapColEnum.SetAt(nCol,eType); if(pXData != NULL) { m_mapColXData.SetAt(nCol,pXData); } return TRUE; } BOOL AECListCtrl::DeleteColumn( int nCol ) { void * pXData = NULL; BOOL bFind = this->m_mapColXData.Lookup(nCol,pXData); if(bFind) { m_mapColXData.RemoveKey(nCol); delete pXData; } return CListCtrl::DeleteColumn(nCol); } BOOL AECListCtrl::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS; return CListCtrl::PreCreateWindow(cs); } void AECListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO *plvDispInfo = (LV_DISPINFO*)pNMHDR; LV_ITEM *plvItem = &plvDispInfo->item; if( plvItem->iItem != -1 && // valid item plvItem->pszText ) // valid text { SetItemText( plvItem->iItem, plvItem->iSubItem, plvItem->pszText); // this will invoke an ItemChanged handler in parent if ( plvItem->iSubItem != 0 ) { TCHAR szText[0x10+1]; GetItemText( plvItem->iItem, 0, szText, 0x10); SetItemText( plvItem->iItem, 0, szText); } } *pResult = 0; } void AECListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) { if( GetFocus() != this) { SetFocus(); } NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int nItem = pNMListView->iItem; int nCol = pNMListView->iSubItem ; EType eType; BOOL bFind = this->m_mapColEnum.Lookup(nCol,eType); if(bFind) { if(eType == ET_Edit) { EditItem(pNMListView->iItem, pNMListView->iSubItem); } else if(eType == ET_Combo) { ComboItem(pNMListView->iItem, pNMListView->iSubItem); } } *pResult = 0; } void AECListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) { LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR; switch(pLVKeyDow->wVKey) { case VK_DELETE: { int nItem = GetSelectionMark(); if(nItem!=-1) { DeleteItem( nItem ); } } break; default :break; } *pResult = 0; } CComboBox * AECListCtrl::ComboItem( int nItem, int nSubItem) { CString strFind = GetItemText(nItem, nSubItem); //basic code start CRect rect; int offset = 0; // Make sure that the item is visible if( !EnsureVisible(nItem, TRUE)) return NULL; GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect); // Now scroll if we need to expose the column CRect rcClient; GetClientRect(rcClient); if( offset + rect.left < 0 || offset + rect.left > rcClient.right ) { CSize size; size.cx = offset + rect.left; size.cy = 0; Scroll(size); rect.left -= size.cx; } rect.left += offset; rect.right = rect.left + GetColumnWidth(nSubItem); if(rect.right > rcClient.right) { rect.right = rcClient.right; } rect.bottom += 30 * rect.Height();//dropdown area DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL|CBS_DROPDOWN; #define IDC_COMBOBOXINLISTVIEW 0x1235 CStringList * pStrList = NULL; BOOL bFind = m_mapColXData.Lookup(nSubItem,(void *&)pStrList); if(bFind == FALSE) { return NULL; } if(nSubItem == 0) { rect.DeflateRect(1,0,0,0); } CComboBox *pList = new AECInplaceComboBox(nItem, nSubItem,pStrList); pList->Create(dwStyle, rect, this, IDC_COMBOBOXINLISTVIEW); pList->ModifyStyleEx(0,WS_EX_CLIENTEDGE);//can we tell at all pList->ShowDropDown(); pList->SelectString(-1, strFind.GetBuffer(1)); return pList; } CEdit * AECListCtrl::EditItem( int nItem, int nSubItem) { CRect rect; int offset = 0; if(!EnsureVisible(nItem, TRUE)) { return NULL; } GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect); CRect rcClient; GetClientRect(rcClient); if( offset + rect.left < 0 || offset + rect.left > rcClient.right ) { CSize size(offset + rect.left,0); Scroll(size); rect.left -= size.cx; } rect.left += offset; rect.right = rect.left + GetColumnWidth(nSubItem); if(rect.right > rcClient.right) rect.right = rcClient.right; LV_COLUMN lvcol; lvcol.mask = LVCF_FMT; GetColumn(nSubItem, &lvcol); DWORD dwStyle; if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT) dwStyle = ES_LEFT; else if((lvcol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT) dwStyle = ES_RIGHT; else dwStyle = ES_CENTER; rect.DeflateRect(2,0,3,1); rect.bottom = rect.top + 14; rect.OffsetRect(3,2); dwStyle |= WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL; CString _s(GetItemText(nItem, nSubItem)); CEdit *pEdit = new AECInplaceEdit(nItem, nSubItem, _s); #define IDC_EDITCTRL 0x1234 pEdit->Create(dwStyle, rect, this, IDC_EDITCTRL); return pEdit; } void AECListCtrl::RemoveAllColXData() { int nCol = 0; void * pXData = NULL; POSITION pos = NULL; for(pos = m_mapColXData.GetStartPosition();pos != NULL;) { m_mapColXData.GetNextAssoc(pos,nCol,pXData); } }