// EditListCtrl.cpp : implementation file // #include "stdafx.h" #include "EditListCtrl.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define IDC_EDIT 0X01 #define PROPERTY_ITEM 0x02 #define PROPERTY_SUB 0x03 #define IDC_ComboBox 0X04 /************************************************************************/ /* CEditListCtrl */ /************************************************************************/ IMPLEMENT_DYNAMIC(CListCtrlEdit, CEdit) CListCtrlEdit::CListCtrlEdit() { } CListCtrlEdit::~CListCtrlEdit() { } BEGIN_MESSAGE_MAP(CListCtrlEdit, CEdit) //{{AFX_MSG_MAP(CListCtrlEdit) ON_WM_KILLFOCUS() ON_WM_SETFOCUS() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CListCtrlEdit message handlers void CListCtrlEdit::SetCtrlData(DWORD dwData) { m_dwData = dwData; } DWORD CListCtrlEdit::GetCtrlData() { return m_dwData; } void CListCtrlEdit::SetInput(const DWORD dwRight) { } void CListCtrlEdit::SetOthers(const char* pOthers, const int nSize) { if (pOthers == NULL) return; } void CListCtrlEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); CWnd* pParent = this->GetParent(); ::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, m_bExchange, 0); #ifdef _DEBUG Global::WriteTextLog(_T("Edit:焦点丢失")); #endif } BOOL CListCtrlEdit::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { if (pMsg->wParam == VK_RETURN) { CWnd* pParent = this->GetParent(); m_bExchange = TRUE; ::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, m_bExchange, TRUE); #ifdef _DEBUG Global::WriteTextLog(_T("Edit:回车")); #endif } else if (pMsg->wParam == VK_ESCAPE) { CWnd* pParent = this->GetParent(); m_bExchange = FALSE; ::PostMessage(pParent->GetSafeHwnd(), WM_USER_EDIT_END, m_bExchange, TRUE); #ifdef _DEBUG Global::WriteTextLog(_T("Edit:退出键")); #endif } } return CEdit::PreTranslateMessage(pMsg); } void CListCtrlEdit::OnSetFocus(CWnd* pOldWnd) { CEdit::OnSetFocus(pOldWnd); m_bExchange = TRUE; } /************************************************************************/ /* CEditListCtrl */ /************************************************************************/ CEditListCtrl::CEditListCtrl() { m_nNumColumns = 0; m_edit.m_hWnd = NULL; m_mode = 0; m_pCallBackEditResult = NULL; } CEditListCtrl::~CEditListCtrl() { } BEGIN_MESSAGE_MAP(CEditListCtrl, CListCtrl) ON_WM_LBUTTONDBLCLK() ON_WM_PARENTNOTIFY() ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdrawList) ON_MESSAGE(WM_USER_EDIT_END, OnEditEnd) END_MESSAGE_MAP() #undef SubclassWindow void CEditListCtrl::PreSubclassWindow() { ASSERT(GetStyle() & LVS_REPORT); CListCtrl::PreSubclassWindow(); VERIFY(m_Ctrlheader.SubclassWindow(GetHeaderCtrl()->GetSafeHwnd())); } /************************************************************************/ /* 函数:[10/21/2016 IT]; /* 描述:; /* 参数:; /* [IN] :; /* [OUT] :; /* [IN/OUT] :; /* 返回:void; /* 注意:最后一个参数,必须以NULL结尾(请看示例); /* 示例:CListSortCtrl::SetHeadings(_T("示例1,100"),_T("示例2,100"),NULL); /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ BOOL CEditListCtrl::SetHeadings(IN LPCTSTR pszText, ...) { if (pszText == NULL) return FALSE; va_list list; INT nCommaPos = 0; // 逗号位置; CString strColumn = _T(""); va_start(list, pszText); do { strColumn = pszText; if (-1 != (nCommaPos = strColumn.Find(_T(",")))) { if (InsertColumn(m_nNumColumns++, strColumn.Left(nCommaPos), LVCFMT_LEFT, _tstoi(strColumn.Mid(nCommaPos + 1))) == -1) { va_end(list); return FALSE; } } pszText = va_arg(list, LPCTSTR); } while (pszText != NULL); va_end(list); SetExtendedStyle(LVS_EX_FLATSB | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP); return TRUE; } void CEditListCtrl::OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult) { NMLVCUSTOMDRAW* pLVCD = reinterpret_cast(pNMHDR); // Take the default processing unless we set this to something else below. *pResult = 0; // First thing - check the draw stage. If it's the control's prepaint // stage, then tell Windows we want messages for every item. if (CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; } else if (CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage) { // This is the prepaint stage for an item. Here's where we set the // item's text color. Our return value will tell Windows to draw the // item itself, but it will use the new color we set here. // We'll cycle the colors through red, green, and light blue. COLORREF crText; int pos = pLVCD->nmcd.dwItemSpec; if (pos % 2) { pLVCD->clrTextBk = RGB(242, 242, 242); } else { pLVCD->clrTextBk = RGB(235, 235, 235); } // Tell Windows to paint the control itself. *pResult = CDRF_DODEFAULT; } } void CEditListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) { CRect rcCtrl; LVHITTESTINFO lvhti; lvhti.pt = point; int nItem = CListCtrl::SubItemHitTest(&lvhti); if (nItem == -1) return; int nSubItem = lvhti.iSubItem; CListCtrl::GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl); #if 0 if (nSubItem == 3 + m_mode) { ShowEdit(TRUE, nItem, nSubItem, rcCtrl); } #else for (vector::iterator it = m_vtEditColumn.begin(); it != m_vtEditColumn.end(); it++ ) { if (nSubItem == *it + m_mode) { ShowEdit(TRUE, nItem, nSubItem, rcCtrl); } } #endif CListCtrl::OnLButtonDblClk(nFlags, point); } void CEditListCtrl::ShowEdit(BOOL bShow, int nItem, int nIndex, CRect rcCtrl) { if (m_edit.m_hWnd == NULL) { m_edit.Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN | WS_BORDER, CRect(0, 0, 0, 0), this, IDC_EDIT); m_edit.ShowWindow(SW_HIDE); CFont tpFont; tpFont.CreateStockObject(DEFAULT_GUI_FONT); m_edit.SetFont(&tpFont); tpFont.DeleteObject(); } if (bShow == TRUE) { CString strItem = CListCtrl::GetItemText(nItem, nIndex); m_edit.MoveWindow(rcCtrl); m_edit.ShowWindow(SW_SHOW); m_edit.SetWindowText(strItem); ::SetFocus(m_edit.GetSafeHwnd()); m_edit.SetSel(-1); m_edit.SetCtrlData(MAKEWPARAM(nIndex, nItem)); } else { m_edit.ShowWindow(SW_HIDE); GetParent()->SendMessage(WM_USER + 100, 0, 0); } } LRESULT CEditListCtrl::OnEditEnd(WPARAM wParam, LPARAM lParam) { INT nItem = -1; INT nSubItem = -1; CString strText = _T(""); if (wParam == TRUE) { m_edit.GetWindowText(strText); DWORD dwData = m_edit.GetCtrlData(); nItem = dwData >> 16; nSubItem = dwData & 0x0000ffff; CListCtrl::SetItemText(nItem, nSubItem, strText); } m_edit.ShowWindow(SW_HIDE); if (wParam == TRUE && lParam == FALSE) { #if 0 GetParent()->SendMessage(WM_USER + 100, 0, 0); #else // 使用回调函数通知上层; if (m_pCallBackEditResult && nItem != -1) m_pCallBackEditResult(nItem, nSubItem, strText); #endif } return 0; } void CEditListCtrl::OnParentNotify(UINT message, LPARAM lParam) { CListCtrl::OnParentNotify(message, lParam); ////////////////////////////////////////////////////////////////////////// CHeaderCtrl* pHeaderCtrl = CListCtrl::GetHeaderCtrl(); if (pHeaderCtrl == NULL) return; CRect rcHeader; pHeaderCtrl->GetWindowRect(rcHeader); ScreenToClient(rcHeader); //The x coordinate is in the low-order word and the y coordinate is in the high-order word. CPoint pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (rcHeader.PtInRect(pt) && message == WM_LBUTTONDOWN) { if (m_edit.m_hWnd != NULL) { DWORD dwStyle = m_edit.GetStyle(); if ((dwStyle&WS_VISIBLE) == WS_VISIBLE) { m_edit.ShowWindow(SW_HIDE); } } } } BOOL CEditListCtrl::PreTranslateMessage(MSG* pMsg) { if (0)//pMsg->message == WM_KEYDOWN) { if (pMsg->wParam == VK_TAB && m_edit.m_hWnd != NULL) { DWORD dwStyle = m_edit.GetStyle(); if ((dwStyle&WS_VISIBLE) == WS_VISIBLE) { OnEditEnd(TRUE, TRUE); CRect rcCtrl; int nItem; int nSub; if (FALSE == Key_Ctrl(nItem, nSub)) Key_Shift(nItem, nSub); CListCtrl::GetSubItemRect(nItem, nSub, LVIR_LABEL, rcCtrl); CPoint pt(rcCtrl.left + 1, rcCtrl.top + 1); OnLButtonDblClk(0, pt); POSITION pos = CListCtrl::GetFirstSelectedItemPosition(); if (pos == NULL) { } else { while (pos) { int ntpItem = CListCtrl::GetNextSelectedItem(pos); CListCtrl::SetItemState(ntpItem, 0, LVIS_SELECTED); } } CListCtrl::SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED); return TRUE; } } } return CListCtrl::PreTranslateMessage(pMsg); } BOOL CEditListCtrl::Key_Shift(int& nItem, int& nSub) { int nItemCount = CListCtrl::GetItemCount(); DWORD dwData = m_edit.GetCtrlData(); nItem = dwData >> 16; nSub = dwData & 0x0000ffff; CHeaderCtrl* pHeader = CListCtrl::GetHeaderCtrl(); if (pHeader == NULL) return FALSE; short sRet = GetKeyState(VK_SHIFT); int nSubcCount = pHeader->GetItemCount(); sRet = sRet >> 15; if (sRet == 0) { nSub += 1; if (nSub >= nSubcCount) { if (nItem == nItemCount - 1) { nItem = 0; nSub = 0; } else { nSub = 0; nItem += 1; } } if (nItem >= nItemCount) nItem = nItemCount - 1; return FALSE; } else { nSub -= 1; if (nSub < 0) { nSub = nSubcCount - 1; nItem--; } if (nItem < 0) nItem = nItemCount - 1; return TRUE; } return FALSE; } BOOL CEditListCtrl::Key_Ctrl(int& nItem, int &nSub) { short sRet = GetKeyState(VK_CONTROL); DWORD dwData = m_edit.GetCtrlData(); nItem = dwData >> 16; nSub = dwData & 0x0000ffff; sRet = sRet >> 15; int nItemCount = CListCtrl::GetItemCount(); if (sRet == 0) { } else { nItem = nItem >= nItemCount - 1 ? 0 : nItem += 1; return TRUE; } return FALSE; } void CEditListCtrl::InitStyle() { SetExtendedStyle(LVS_EX_FLATSB | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP); } BOOL CEditListCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText) { ASSERT(::IsWindow(m_hWnd)); ASSERT((GetStyle() & LVS_OWNERDATA) == 0); LVITEM lvi; lvi.iSubItem = nSubItem; lvi.pszText = (LPTSTR)lpszText; ::SendMessage(m_hWnd, LVM_SETITEMTEXT, nItem, (LPARAM)&lvi); return (BOOL) ::SendMessage(m_hWnd, LVM_SETITEMTEXT, nItem, (LPARAM)&lvi); } CString CEditListCtrl::GetItemText(int nItem, int nSubItem) { ASSERT(::IsWindow(m_hWnd)); LVITEM lvi; memset(&lvi, 0, sizeof(LVITEM)); lvi.iSubItem = nSubItem; CString str; int nLen = 1024 * 4; // int nRes; do { nLen *= 2; lvi.cchTextMax = nLen; lvi.pszText = str.GetBufferSetLength(nLen); nRes = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); } while (nRes == nLen - 1); str.ReleaseBuffer(); return str; }