⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editlistview.cpp

📁 VC++高级编程技巧与示例
💻 CPP
字号:
// EditListView.cpp : implementation file
//

#include "stdafx.h"
#include "ODBCTrans.h"
#include "EditListView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CEditListView
//●>
#include "ODBCTransDoc.h"
//<●
#define IDC_LISTEDIT WM_USER+100
// CListEdit

CListEdit::CListEdit(int iItem, int iSubItem, CString sInitText)
{
	m_iItem = iItem;
	m_iSubItem = iSubItem;
	m_bESC = FALSE;
}

CListEdit::~CListEdit()
{
}

void CListEdit::SetItemData(int iItem, int iSubItem, CString sInitText)
{
	m_iItem = iItem;
	m_iSubItem = iSubItem;
	m_bESC = FALSE;
}

BEGIN_MESSAGE_MAP(CListEdit, CEdit)
	//{{AFX_MSG_MAP(CListEdit)
	ON_WM_KILLFOCUS()
	ON_WM_NCDESTROY()
	ON_WM_CHAR()
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////
//CListEdit类的代码:
BOOL CListEdit::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 CListEdit::OnKillFocus(CWnd* pNewWnd) 
{
	CEdit::OnKillFocus(pNewWnd);

	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_iItem;
	dispinfo.item.iSubItem = m_iSubItem;
	dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str);
	dispinfo.item.cchTextMax = str.GetLength();
	GetParent()->GetParent()->SendMessage( WM_NOTIFY, GetParent()->GetDlgCtrlID(), 
					(LPARAM)&dispinfo );

	DestroyWindow();
}

void CListEdit::OnNcDestroy() 
{
	CEdit::OnNcDestroy();
	
	// TODO: Add your message handler code here
	delete this;
}

void CListEdit::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_bESC = TRUE;
		GetParent()->SetFocus();
		return;
	}
	CEdit::OnChar(nChar, nRepCnt, nFlags);
	// 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 );
	}
	//●
	m_Modified=TRUE;
	//●
//	CEdit::OnChar(nChar, nRepCnt, nFlags);
}


int CListEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CEdit::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	if (CEdit::OnCreate(lpCreateStruct) == -1)
		return -1;

	// Set the proper font
	CFont* font = GetParent()->GetFont();
	SetFont(font);

	SetWindowText( m_sInitText );
	SetFocus();
	SetSel( 0, -1 );
	m_Modified=FALSE;
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// CListEdit message handlers
//●●●●●●
IMPLEMENT_DYNCREATE(CEditListView, CListView)

CEditListView::CEditListView()
{
	m_dwDefaultStyle |= LVS_REPORT|LVS_EDITLABELS;
	m_bEditing=FALSE;
}

CEditListView::~CEditListView()
{
}


BEGIN_MESSAGE_MAP(CEditListView, CListView)
	//{{AFX_MSG_MAP(CEditListView)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
	ON_COMMAND(ID_TRANS, OnTrans)
	ON_UPDATE_COMMAND_UI(ID_TRANS, OnUpdateTrans)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CEditListView drawing

void CEditListView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CEditListView diagnostics

#ifdef _DEBUG
void CEditListView::AssertValid() const
{
	CListView::AssertValid();
}

void CEditListView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CEditListView message handlers
/////////////////////////////////////////////////////////////////////////////
void CEditListView::OnInitialUpdate() 
{
	CListView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
//●
    CODBCTransDoc * pDoc;
	pDoc=(CODBCTransDoc * )GetDocument();
	m_List=&GetListCtrl();
    if(pDoc->m_pSet==NULL)
	{
		AfxMessageBox("尚未初始化ODBC记录集!");
		return;
	}

	if(!pDoc->m_pSet->IsOpen())
	{
		pDoc->m_pSet->Open();
	}

	//1. 添加列:
	short i,j;
	CODBCFieldInfo Fi;
	CString tmp;
    LV_COLUMN lc;
    lc.mask = LVCF_FMT | LVCF_WIDTH |
    	          LVCF_TEXT | LVCF_SUBITEM;
	for(i=0;i<pDoc->m_pSet->m_nFields;i++)
	{
		pDoc->m_pSet->GetODBCFieldInfo(i,Fi);
	    lc.iSubItem = i;
		lc.fmt = LVCFMT_CENTER;
	    lc.cx = Fi.m_strName.GetLength()*10+16;
	    lc.pszText=Fi.m_strName.GetBuffer(Fi.m_strName.GetLength());
	    GetListCtrl().InsertColumn(i, &lc);
	}
	//2. 添加行:
	LV_ITEM Item;
	CString str;
	CDBVariant var;
	i=0;
	if(pDoc->m_pSet->IsEOF())
	{
		AfxMessageBox("当前视图没有记录!");
		return;
	}

	pDoc->m_pSet->MoveFirst();
	while(pDoc->m_pSet->IsEOF()==0)
	{
		Item.mask=LVIF_TEXT;
		//第i 行:
	    Item.iItem=i;

		//第一列:
   	    Item.iSubItem=0;
		pDoc->m_pSet->GetFieldValue((short)0,str);
		Item.pszText=str.GetBuffer(str.GetLength());
	    m_List->InsertItem(&Item);
		//其它各列:
		for(j=1;j<pDoc->m_pSet->m_nFields;j++)
		{
//==>Wrong!
			pDoc->m_pSet->GetFieldValue((short)j,str);//获取数据;
			m_List->SetItemText(i,j,str.GetBuffer(str.GetLength()));
		}

		pDoc->m_pSet->MoveNext();
		i++;//计数器;
    }
//★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★☆★
//●
	pDoc->m_pSet->m_pDatabase->BeginTrans();
//●
}

//根据point值,判断point所在行和列:
int CEditListView::HitTestEx(CPoint &point, int *col)
{
	int column = 0;
	int row = m_List->HitTest( point,NULL );
	if( col ) *col = 0;
	
	// Make sure that the ListView is in LVS_REPORT
	if( (GetWindowLong(m_List->m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
		return row;

	// Get the top and bottom row visible
	row = m_List->GetTopIndex();
	int bottom = row + m_List->GetCountPerPage();
	if( bottom > m_List->GetItemCount() )
		bottom = m_List->GetItemCount();
	
	// Get the number of columns
	CHeaderCtrl* pHeader = (CHeaderCtrl*)m_List->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;
		m_List->GetItemRect( row, &rect, LVIR_BOUNDS );
		if( rect.PtInRect(point) )
		{
			// Now find the column
			for( column = 0; column < nColumnCount; column++ )
			{
				int colwidth = m_List->GetColumnWidth(column);
				if( point.x >= rect.left 
					&& point.x <= (rect.left + colwidth ) )
				{
					if( col ) *col = column;
					CString tp;
					return row;
				}
				rect.left += colwidth;
			}
		}
	}
	if( col ) *col = -1;
	return -1;
}

///////////////////////////////////////////////////////////
CEdit * CEditListView::EditSubLabel(int nItem, int nCol)
{
	// The returned pointer should not be saved

	// Make sure that the item is visible
	if( !m_List->EnsureVisible( nItem, TRUE ) ) return NULL;

	// Make sure that nCol is valid
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();
	if( nCol >= nColumnCount ||m_List->GetColumnWidth(nCol) < 5 )
		return NULL;

	// Get the column offset
	int offset = 0;
	for( int i = 0; i < nCol; i++ )
		offset += m_List->GetColumnWidth( i );

	CRect rect;
	m_List->GetItemRect(nItem,&rect,LVIR_BOUNDS);
	// Now scroll if we need to expose the column
	CRect rcClient;
	m_List->GetClientRect( &rcClient );
	if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
	{
		CSize size;
		size.cx = offset + rect.left;
		size.cy = 0;
		m_List->Scroll( size );
		rect.left -= size.cx;
	}

	// Get Column alignment
	LV_COLUMN lvcol;
	lvcol.mask = LVCF_FMT;
	m_List->GetColumn( nCol, &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 + m_List->GetColumnWidth( nCol ) - 3 ;
	if( rect.right > rcClient.right) rect.right = rcClient.right;
	dwStyle |= WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL;
	pEdit = new CListEdit(nItem, nCol,m_List->GetItemText( nItem, nCol ));
	pEdit->Create(dwStyle,rect,this,IDC_LISTEDIT );
	pEdit->m_sInitText=m_List->GetItemText(nItem,nCol);
	pEdit->SetWindowText(pEdit->m_sInitText);
	pEdit->SetSel(0,-1,FALSE);
	m_bEditing=TRUE;
	return pEdit;
}

void CEditListView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	if( GetFocus() != this ) SetFocus();
	CListView::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CEditListView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	if( GetFocus() != this ) SetFocus();
	CListView::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CEditListView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CListView::OnLButtonDown(nFlags, point);
	int index;
	int column;
	if( ( index = HitTestEx( point, &column )) != -1 )
	{
		UINT flag = LVIS_FOCUSED;
		if( (m_List->GetItemState( index, flag ) & flag) == flag && column > 0)
		{
			// Add check for LVS_EDITLABELS
			if( GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS )
				EditSubLabel( index, column );
		}
		else
			m_List->SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
				    	LVIS_SELECTED | LVIS_FOCUSED); 
	}
//	CListView::OnLButtonDown(nFlags, point);
}

void CEditListView::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)
	{
		m_List->SetItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
	}
	m_bEditing=FALSE;
	*pResult = 0;
	//●
	m_Modified=pEdit->m_Modified;
	if(m_Modified)
	{
		Modify(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
	}
	//●
}

BOOL CEditListView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(m_bEditing)
	{
       switch (((NMHDR*)lParam)->code)
        {
                case HDN_BEGINTRACKW:
                case HDN_BEGINTRACKA:
                        *pResult = TRUE;                // disable tracking
                        return TRUE;                    // Processed message
        }
 	}
	return CListView::OnNotify(wParam, lParam, pResult);
}

void CEditListView::Modify(int r,int c, CString Val)
{
    CODBCTransDoc * pDoc;
	pDoc=(CODBCTransDoc * )GetDocument();
    if(!pDoc->m_pSet->IsOpen())
	{
		AfxMessageBox("记录集对象尚未打开!");
		return;
	}
	if(pEdit->m_Modified)
	{
		pDoc->m_pSet->MoveFirst();
		pDoc->m_pSet->Move(r);
		TRY
		{
			pDoc->m_pSet->Edit();
			switch(c)
			{
				case 0:
					{
						pDoc->m_pSet->m_ID=atol(Val);
						break;
					}
				case 1:
					{
						pDoc->m_pSet->m_column1=Val;
						break;
					}
				case 2:
					{
						pDoc->m_pSet->m_column2=Val;
						break;
					}
				case 3:
					{
						pDoc->m_pSet->m_column3=atol(Val);
						break;
					}
				case 4:
					{
						CString Year,Month,Day,Hour,Min,Sec;
						CString OldTime;
						int yy,mm,dd,hh,mi,ss;
						if(Val.GetLength()!=19)
						{
							pDoc->m_pSet->GetFieldValue(c,OldTime);
							AfxMessageBox("时间格式不对!");
							m_List->SetItemText(r,c,OldTime);
							break;
						}

						Year=Val.Left(4);
						Month=Val.Mid(5,2);
						Day=Val.Mid(8,2);
						Hour=Val.Mid(11,2);
						Min=Val.Mid(14,2);
						Sec=Val.Mid(17,2);
                        
						yy=atoi(Year);
						mm=atoi(Month);
						dd=atoi(Day);
						hh=atoi(Hour);
						mi=atoi(Min);
						ss=atoi(Sec);
						if(!(dd>= 1 && dd<= 31))
						{
							AfxMessageBox("日期应该在1-31之间!");
							break;
						}
						if(!(mm>= 1 &&mm<= 12))
						{
							AfxMessageBox("月份应该在1-12之间!");
							break;
						}
						if(!(yy>= 1900))
						{
							AfxMessageBox("年份应该在1900年之后!");
							break;
						}
						CTime time(yy,mm,dd,hh,mi,ss);
						pDoc->m_pSet->m_column4=time;
						break;
					}
				case 5:
					{
						pDoc->m_pSet->m_column5=Val;
						break;
					}
				case 6:
					{
						pDoc->m_pSet->m_column6=atol(Val);
						break;
					}
				case 7:
					{
						pDoc->m_pSet->m_column7=Val;
						break;
					}
			};
			pDoc->m_pSet->Update();
		}
		CATCH_ALL(e)
		{
			AfxMessageBox("更新数据库失败,将事务回滚!");
			pDoc->m_pSet->m_pDatabase->Rollback();
		}
		END_CATCH_ALL
	}
}

void CEditListView::OnTrans() 
{
	// TODO: Add your command handler code here
    CODBCTransDoc * pDoc;
	pDoc=(CODBCTransDoc * )GetDocument();
	if(pEdit->m_Modified)
	{
		TRY
		{
			pDoc->m_pSet->m_pDatabase->CommitTrans();
		}
		CATCH(CDBException,e)
		{
			AfxMessageBox("提交事务失败,开始回滚事务!");
            pDoc->m_pSet->m_pDatabase->Rollback();
		}
		END_CATCH
	}
	m_Modified=FALSE;
}

void CEditListView::OnUpdateTrans(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if(m_Modified&&(!m_bEditing))
	{
		pCmdUI->Enable(TRUE);
	}
	else
	{
		pCmdUI->Enable(FALSE);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -