ClistCtrl
2012-11-01 09:21 龙成 阅读(1296) 评论(0) 编辑 收藏 举报设置list Control风格
listCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES); LONG lStyle; lStyle = GetWindowLong(listCtrl.m_hWnd, GWL_STYLE);//获取当前窗口style lStyle &= ~LVS_TYPEMASK; //清除显示方式位 lStyle |= LVS_REPORT; //设置style SetWindowLong(listCtrl.m_hWnd, GWL_STYLE, lStyle);//设置style
listctrlex.h.
#if !defined(AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_) #define AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ListCtrlEx.h : header file // #include <afxtempl.h> #define COLUMN_STYLE_GENERAL 0x00000000 #define COLUMN_STYLE_EDIT 0x00000001 #define COLUMN_STYLE_COMBOBOX 0x00000002 #define WM_ITEM_CHANGED WM_USER+8 ////////////////////////////////////////////////////////////////////////// typedef struct tagSUBITEMINFO { tagSUBITEMINFO(){m_dwColumnType=0;m_parComboString=NULL;} DWORD m_dwColumnType; CStringArray* m_parComboString; } SUBITEMINFO,*LPSUBITEMINFO; ///////////////////////////////////////////////////////////////////////////// // CListCtrlEx window class CListCtrlEx : public CListCtrl { // Construction public: CListCtrlEx(); // Attributes public: // Operations public: int InsertColumn( int nCol, const LVCOLUMN* pColumn, DWORD nStyle = COLUMN_STYLE_GENERAL,CStringArray * pStringArray = NULL ); int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, DWORD nStyle = COLUMN_STYLE_GENERAL ,CStringArray * pStringArray = NULL, int nSubItem = -1 ); BOOL DeleteColumn( int nCol ); void ShowSubCtrl(int nItem, int nSubItem,DWORD dwCtrlType = COLUMN_STYLE_EDIT); int HitTestEx (CPoint& Point, int& nSubItem); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CListCtrlEx) //}}AFX_VIRTUAL // Implementation public: virtual ~CListCtrlEx(); // Generated message map functions protected: CArray<LPSUBITEMINFO,LPSUBITEMINFO> m_arColumnInfo; //{{AFX_MSG(CListCtrlEx) afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnDestroy(); //}}AFX_MSG public: virtual BOOL PreTranslateMessage(MSG* pMsg); protected: afx_msg void OnMouseMove(UINT nFlags, CPoint point); public: void CreateToolTip(); public: CToolTipCtrl m_ToolTip; CWnd pWnd; DECLARE_MESSAGE_MAP() }; ////////////////////////////////////////////////////////////////////////// // CListCellEdit window class CListCellEdit : public CEdit { // Construction public: CListCellEdit(int nItem, int nSubItem, CString strInitTex); void SetListItemText(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CListCellEdit) public: virtual BOOL PreTranslateMessage(MSG* pMsg); //}}AFX_VIRTUAL // Implementation public: virtual ~CListCellEdit(); protected: int m_nItem; int m_nSubItem; CString m_strInitText; BOOL m_bEscape; // Generated message map functions //{{AFX_MSG(CListCellEdit) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnNcDestroy(); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CListCellCombo window class CListCellCombo : public CComboBox { // Construction public: CListCellCombo(); CListCellCombo(int nItem,int nSubItem,CString strWindowText); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CListCellCombo) public: virtual BOOL PreTranslateMessage(MSG* pMsg); //}}AFX_VIRTUAL // Implementation public: virtual ~CListCellCombo(); // Generated message map functions protected: int m_iRowIndex;// Index of the item in the list control int m_iColumnIndex;// Index of the subitem in the list control CString m_strWindowText;// Previous selected string value in the combo control //{{AFX_MSG(CListCellCombo) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnNcDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_)
listctrl.cpp.
#include "stdafx.h" //#include "CListTest.h" #include "ListCtrlEx.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CListCtrlEx CListCtrlEx::CListCtrlEx() { } CListCtrlEx::~CListCtrlEx() { } BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl) //{{AFX_MSG_MAP(CListCtrlEx) ON_WM_HSCROLL() ON_WM_VSCROLL() ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit) ON_WM_LBUTTONDOWN() ON_WM_DESTROY() ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CListCtrlEx message handlers void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default if (GetFocus() != this) SetFocus(); CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar); } void CListCtrlEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // TODO: Add your message handler code here and/or call default if (GetFocus() != this) SetFocus(); CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar); } void CListCtrlEx::ShowSubCtrl(int nItem, int nSubItem,DWORD dwCtrlType/* = COLUMN_STYLE_EDIT*/) { // The returned pointer should not be saved // Make sure that the item is visible if (!EnsureVisible (nItem, TRUE)) return; // Make sure that nCol is valid CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0); int nColumnCount = pHeader->GetItemCount(); if (nSubItem >= nColumnCount || GetColumnWidth (nSubItem) < 5) { return; } // Get the column offset int Offset = 0; for (int iColumn = 0; iColumn < nSubItem; iColumn++) Offset += GetColumnWidth (iColumn); CRect Rect; GetItemRect (nItem, &Rect, LVIR_BOUNDS); // Now scroll if we need to expose the column CRect ClientRect; GetClientRect (&ClientRect); if (Offset + Rect.left < 0 || Offset + Rect.left > ClientRect.right) { CSize Size; if (Offset + Rect.left > 0) Size.cx = -(Offset - Rect.left); else Size.cx = Offset - Rect.left; Size.cy = 0; Scroll (Size); Rect.left -= Size.cx; } // Get nSubItem alignment 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.left += Offset+4; Rect.right = Rect.left + GetColumnWidth (nSubItem) - 3; if (Rect.right > ClientRect.right) Rect.right = ClientRect.right; dwStyle |= WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL; CString strCulText=GetItemText (nItem, nSubItem); if(dwCtrlType==COLUMN_STYLE_EDIT) { CEdit *pEdit = new CListCellEdit (nItem, nSubItem, strCulText); pEdit->Create (dwStyle, Rect, this, 101); } if(dwCtrlType==COLUMN_STYLE_COMBOBOX) { //显示组合框 CRect rc(Rect.left-2,Rect.top-2,Rect.right,Rect.bottom+100); CComboBox * pCombo = new CListCellCombo(nItem,nSubItem,strCulText); if (nSubItem==2)//如果是模板列。则创建成滚动条的 { pCombo->Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST|WS_HSCROLL,rc,this, 1); pCombo->SetHorizontalExtent(500); } else { pCombo->Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST,rc,this, 1); } if(m_arColumnInfo[nSubItem]->m_parComboString) { for(int i=0;i<m_arColumnInfo[nSubItem]->m_parComboString->GetSize();i++) { pCombo->AddString((*(m_arColumnInfo[nSubItem]->m_parComboString)).GetAt(i)); } } int nIndex=pCombo->FindString(0,strCulText); if(nIndex!=CB_ERR) { pCombo->SetCurSel(nIndex); } else { pCombo->SetCurSel(-1); } } } void CListCtrlEx::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; // TODO: Add your control notification handler code here LV_ITEM *plvItem = &pDispInfo->item; if (plvItem->pszText != NULL) { SetItemText (plvItem->iItem, plvItem->iSubItem, plvItem->pszText); } *pResult = 0; } int CListCtrlEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, DWORD nStyle,CStringArray * pStringArray, int nSubItem) { DeleteColumn(nCol); int nIndex=CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat ,nWidth ,nSubItem ); if(nIndex!=-1) { LPSUBITEMINFO pSII=new SUBITEMINFO; pSII->m_dwColumnType=nStyle; pSII->m_parComboString=pStringArray; m_arColumnInfo.InsertAt(nIndex,pSII); } return nIndex; } int CListCtrlEx::InsertColumn( int nCol, const LVCOLUMN* pColumn, DWORD nStyle,CStringArray * pStringArray) { DeleteColumn(nCol); int nIndex=CListCtrl::InsertColumn(nCol,pColumn); if(nIndex!=-1) { LPSUBITEMINFO pSII=new SUBITEMINFO; pSII->m_dwColumnType=nStyle; pSII->m_parComboString=pStringArray; m_arColumnInfo.InsertAt(nIndex,pSII); } return nIndex; } BOOL CListCtrlEx::DeleteColumn(int nCol ) { BOOL bResult=CListCtrl::DeleteColumn(nCol); if(bResult) { delete m_arColumnInfo.GetAt(nCol); m_arColumnInfo.RemoveAt(nCol); } return bResult; } void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) { CListCtrl::OnLButtonDown(nFlags, point); // TODO: Add your message handler code here and/or call default int nItem; int nSubItem; if ((nItem = HitTestEx (point, nSubItem)) ==-1) { return; } switch(m_arColumnInfo[nSubItem]->m_dwColumnType) { case COLUMN_STYLE_GENERAL: return; break; case COLUMN_STYLE_EDIT: ShowSubCtrl(nItem,nSubItem,COLUMN_STYLE_EDIT); break; case COLUMN_STYLE_COMBOBOX: ShowSubCtrl(nItem,nSubItem,COLUMN_STYLE_COMBOBOX); break; default: break; } } int CListCtrlEx::HitTestEx (CPoint& Point, int& nSubItem) { nSubItem = 0; int ColumnNum = 0; int Row = HitTest (Point, NULL); // Make sure that the ListView is in LVS_REPORT if ((GetWindowLong (m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT) return Row; // Get the top and bottom row visible Row = GetTopIndex(); int Bottom = Row + GetCountPerPage(); if (Bottom > GetItemCount()) Bottom = GetItemCount(); // Get the number of columns CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0); int nColumnCount = pHeader->GetItemCount(); // Loop through the visible rows for(; Row <= Bottom; Row++) { // Get bounding rect of item and check whether point falls in it. CRect Rect; GetItemRect (Row, &Rect, LVIR_BOUNDS); if (Rect.PtInRect (Point)) { // Now find the column for (ColumnNum = 0; ColumnNum < nColumnCount; ColumnNum++) { int ColWidth = GetColumnWidth (ColumnNum); if (Point.x >= Rect.left && Point.x <= (Rect.left + ColWidth)) { nSubItem = ColumnNum; return Row; } Rect.left += ColWidth; } } } return -1; } void CListCtrlEx::OnDestroy() { // TODO: Add your message handler code here int nCount=m_arColumnInfo.GetSize(); for(int i=0;i<nCount;i++) { delete m_arColumnInfo.GetAt(i); } m_arColumnInfo.RemoveAll(); CListCtrl::OnDestroy(); } void CListCtrlEx::OnMouseMove(UINT nFlags, CPoint point) { if (m_ToolTip.m_hWnd == NULL) { CreateToolTip(); } LVHITTESTINFO Info; int iItemIndex; Info.pt = point; iItemIndex = SubItemHitTest(&Info); if (-1 == iItemIndex) { return; } //if (1 == Info.iSubItem) //{ CString strText; strText = this->GetItemText(iItemIndex, Info.iSubItem); m_ToolTip.UpdateTipText(strText, this); //} CListCtrl::OnMouseMove(nFlags, point); } void CListCtrlEx::CreateToolTip() { if (m_ToolTip.m_hWnd != NULL) { m_ToolTip.DestroyToolTipCtrl(); } m_ToolTip.Create(this); m_ToolTip.SetTipTextColor(RGB(0,0,255)); m_ToolTip.AddTool(this, TTS_ALWAYSTIP); } BOOL CListCtrlEx::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class switch (pMsg->message) { case WM_MOUSEMOVE: if (m_ToolTip.m_hWnd != NULL) { m_ToolTip.RelayEvent(pMsg); } break; default: break; } return CListCtrl::PreTranslateMessage(pMsg); } ///////////////////////////////////////////////////////////////////////////// // CListCellEdit CListCellEdit:: CListCellEdit(int nItem, int nSubItem, CString strInitText) { m_nItem = nItem; m_nSubItem = nSubItem; m_strInitText = strInitText; m_bEscape=FALSE; } CListCellEdit::~CListCellEdit() { } BEGIN_MESSAGE_MAP(CListCellEdit, CEdit) //{{AFX_MSG_MAP(CListCellEdit) ON_WM_KILLFOCUS() ON_WM_NCDESTROY() ON_WM_CHAR() ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CListCellEdit message handlers void CListCellEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); // TODO: Add your message handler code here SetListItemText(); DestroyWindow(); } void CListCellEdit::OnNcDestroy() { CEdit::OnNcDestroy(); // TODO: Add your message handler code here delete this; } BOOL CListCellEdit::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class if( pMsg->message == WM_KEYDOWN ) { if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_DELETE || pMsg->wParam == VK_ESCAPE || GetKeyState( VK_CONTROL) ) { ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); return TRUE; // DO NOT process further } } return CEdit::PreTranslateMessage(pMsg); } void CListCellEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default if( nChar == VK_ESCAPE || nChar == VK_RETURN) { if( nChar == VK_ESCAPE ) m_bEscape = TRUE; GetParent()->SetFocus(); return; } // Resize edit control if needed // Get text extent CString str; GetWindowText( str ); CWindowDC dc(this); CFont *pFont = GetParent()->GetFont(); CFont *pFontDC = dc.SelectObject( pFont ); CSize size = dc.GetTextExtent( str ); dc.SelectObject( pFontDC ); size.cx += 5; // add some extra buffer // Get client rect CRect rect, parentrect; GetClientRect( &rect ); GetParent()->GetClientRect( &parentrect ); // Transform rect to parent coordinates ClientToScreen( &rect ); GetParent()->ScreenToClient( &rect ); // Check whether control needs to be resized // and whether there is space to grow if( size.cx > rect.Width() ) { if( size.cx + rect.left < parentrect.right ) rect.right = rect.left + size.cx; else rect.right = parentrect.right; MoveWindow( &rect ); } CEdit::OnChar(nChar, nRepCnt, nFlags); } int CListCellEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CEdit::OnCreate(lpCreateStruct) == -1) return -1; // Set the proper font CFont* font = GetParent()->GetFont(); SetFont(font); SetWindowText( m_strInitText ); SetFocus(); SetSel( 0, -1 ); return 0; } void CListCellEdit::SetListItemText() { CString Text; GetWindowText (Text); // 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_nItem; dispinfo.item.iSubItem = m_nSubItem; dispinfo.item.pszText = m_bEscape ? NULL : LPTSTR ((LPCTSTR) Text); dispinfo.item.cchTextMax = Text.GetLength(); GetParent()->GetParent()->SendMessage (WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM) &dispinfo); //如果已经修改则向主窗体发送消息 if(Text.Compare(m_strInitText) !=0 ) { GetParent()->GetParent()->SendMessage(WM_ITEM_CHANGED,(WPARAM)m_nItem,(LPARAM)m_nSubItem); } } ///////////////////////////////////////////////////////////////////////////// // CListCellCombo CListCellCombo::CListCellCombo() { } CListCellCombo::CListCellCombo(int nItem,int nSubItem,CString strWindowText) { m_iRowIndex=nItem; m_iColumnIndex=nSubItem; m_strWindowText=strWindowText; } CListCellCombo::~CListCellCombo() { } BEGIN_MESSAGE_MAP(CListCellCombo, CComboBox) //{{AFX_MSG_MAP(CListCellCombo) ON_WM_KILLFOCUS() ON_WM_CREATE() ON_WM_NCDESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CListCellCombo message handlers BOOL CListCellCombo::PreTranslateMessage(MSG* pMsg) { // TODO: Add your specialized code here and/or call the base class // 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 CListCellCombo::OnKillFocus(CWnd* pNewWnd) { CComboBox::OnKillFocus(pNewWnd); // TODO: Add your message handler code here 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 = LPTSTR((LPCTSTR)str); dispinfo.item.cchTextMax = str.GetLength(); GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo); //如果已经修改则向主窗体发送消息 if(str.Compare(m_strWindowText) !=0 ) { GetParent()->GetParent()->SendMessage(WM_ITEM_CHANGED,(WPARAM)m_iRowIndex,(LPARAM)m_iColumnIndex); } // Close the control PostMessage(WM_CLOSE); } int CListCellCombo::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CComboBox::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here CFont* pFont = GetParent()->GetFont(); SetFont(pFont); SetFocus(); return 0; } void CListCellCombo::OnNcDestroy() { CComboBox::OnNcDestroy(); // TODO: Add your message handler code here delete this; }