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

📄 multiline_edit_subitems.shtml.htm

📁 mfc资料集合5
💻 HTM
📖 第 1 页 / 共 2 页
字号:
	int offset = 0;
	int i;
	for( i = 0; orderarray[i] != iSubItem; i++ )
		offset += GetColumnWidth( orderarray[i] );
	int colwidth = GetColumnWidth( iSubItem );
	delete[] orderarray;
	
	CRect rect;
	GetItemRect( iItem, &rect, LVIR_BOUNDS );
	
	// Scroll if we need to expose the column
	CRect rcClient;
	GetClientRect( &rcClient );
	if( offset + rect.left < 0 || offset + colwidth + rect.left > rcClient.right )
        {
		CSize size;
		size.cx = offset + rect.left;
		size.cy = 0;
		Scroll( size );
		rect.left -= size.cx;
        }
	
	rect.left += offset+4;
	rect.right = rect.left + colwidth - 3 ;
	// The right end of the control should not go past the edge 
	// of the grid control.
	if( rect.right > rcClient.right) 
		rect.right = rcClient.right;
	pWnd->MoveWindow( &rect );

	return 1;	
	}
</FONT></TT></PRE>

<H4>
Step 6: Subclass the CEdit class</H4>
While this CEdit subclass is similar to the CInPlaceEdit class from the 
article "Editable Subitems," there are some differences worth mentioning here.
In this implementation, the class is created by the parent of the 
list control. Therefore the parent is also responsible for destroying (or hiding) it.
The self-destruction has therefore been removed.  Some functionality is 
introduced to handle the multiline capabilities.
<UL>
<LI>
OnKillFocus still sends the parent of the list control the end label edit message,
but it does not call the destroy window.
<LI>
OnChar still handles the return and escape, but it now calls a calculate size 
method which resizes the control to fit the text.  This routine handles changes
in height as well as width.  When the control would extend beyond the 
bottom of the parent list control, it displays the edit window's 
scrollbar.
<LI>
A subtle change in PreTranslateMessage is that when the multiline edit control
receives an escape key down message, it normally sends a destroy window message
to its parent.  It is bypassed here since we don't want to destroy the list control
if the user decides to back out of cell editing changes.
</UL>

The CPP file contents are included here:


<PRE><TT><FONT COLOR="#990000">
// InPlaceEdit.cpp : implementation file
//

#include "stdafx.h"
#include "InPlaceEdit.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit

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

CInPlaceEdit::~CInPlaceEdit()
	{
	}


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

/////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit message handlers

BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg)
	{
	if( pMsg->message == WM_KEYDOWN )
        {
		SHORT sKey = GetKeyState( VK_CONTROL);
		if(pMsg->wParam == VK_RETURN
			|| pMsg->wParam == VK_DELETE
			|| pMsg->wParam == VK_ESCAPE
			|| sKey
			)
			{
			::TranslateMessage(pMsg);
			/* Strange but true:
			If the edit control has ES_MULTILINE and ESC
			is pressed the parent is destroyed if the 
			message is dispatched.  In this 
			case the parent is the list control. */
			if( !(GetStyle() & ES_MULTILINE) || pMsg->wParam != VK_ESCAPE )
				{
				::DispatchMessage(pMsg);
				}
			return TRUE;                    // DO NOT process further
			}
        }
	
	return CEdit::PreTranslateMessage(pMsg);
	}


void CInPlaceEdit::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 = m_bESC ? 0 : str.GetLength();
	
	GetParent()->GetParent()->SendMessage( WM_NOTIFY, GetParent()->GetDlgCtrlID(), 
		(LPARAM)&dispinfo );
	
	}


void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
	{
	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
	CalculateSize();
	}

int CInPlaceEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
	{
	if (CEdit::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// Set the proper font
	CFont* font = GetParent()->GetFont();
	SetFont(font);
	
	SetWindowText( m_sInitText );
	SetFocus();
	CalculateSize();
	SetSel( 0, -1 );
	return 0;
	}

void CInPlaceEdit::CalculateSize()
	{
	// Get text extent
	CString str;
	
	GetWindowText( str );
	CWindowDC dc(this);
	CFont *pFont = GetParent()->GetFont();
	CFont *pFontDC = dc.SelectObject( pFont );
	CSize size;

	// Get client rect
	CRect rect, parentrect;
	GetClientRect( &rect );
	GetParent()->GetClientRect( &parentrect );
	
	// Transform rect to parent coordinates
	ClientToScreen( &rect );
	GetParent()->ScreenToClient( &rect );
	
	if( !(GetStyle() & ES_MULTILINE ) )
		{
		size = dc.GetTextExtent( str );
		dc.SelectObject( pFontDC );
		size.cx += 5;                           // add some extra buffer
		}
	else
		{
		CRect thinrect( rect );  // To measure the skinniest text box
		CRect widerect( rect );  // To measure the wides text box
		widerect.right = parentrect.right;
		// Use the shortest of the two box sizes.
		int thinheight = dc.DrawText( str, &thinrect, DT_CALCRECT|DT_NOPREFIX|DT_LEFT|DT_EXPANDTABS|DT_WORDBREAK );
		int wideheight = dc.DrawText( str, &widerect, DT_CALCRECT|DT_NOPREFIX|DT_LEFT|DT_EXPANDTABS|DT_WORDBREAK );
		if( thinheight >= wideheight )
			{
			size.cy = wideheight + 5;
			size.cx = widerect.right - widerect.left + 5;
			}
		else
			{
			size.cy = thinheight + 5;
			size.cx = thinrect.right - thinrect.left + 5;
			}
		}
	
	// Check whether control needs to be resized
	// and whether there is space to grow
	int changed = 0;
	if( size.cx > rect.Width() )
		{
		if( size.cx + rect.left < parentrect.right-2 )
			rect.right = rect.left + size.cx;
		else
			rect.right = parentrect.right-2;
		changed = 1;
		}
	if( size.cy > rect.Height() )
		{
		if( size.cy + rect.top < parentrect.bottom-2 )
			rect.bottom = rect.top + size.cy;
		else
			{
			rect.bottom = parentrect.bottom-2;
			ShowScrollBar( SB_VERT );
			}
		changed = 1;
		}
	// If the size became larger rposition the window.
	if( changed )
		MoveWindow( &rect );
	}
</FONT></TT></PRE>


<H4>
Step 7: Handle the begin and end label messages</H4>
<p>
The parent of the list control needs to handle the begin and end label
edit messages sent by the list control.  The list control's parent must 
create the edit control for editing and destroy it when done.  It could just
as easily create the edit control once and destroy it when it is destroyed.
This would enable the control to be reused.  Keep in mind that this
method of editing items and subitems enables the application to determine
the way a particular item/subitem is to be edited.  For instance
one subitem may be edited with a single line edit control, another a multi line
edit control, and yet another with a comobox.
<p>
Since the parent's handling of the beginning label edit includes the
creation of an edit control, it does not need the list control to create 
one as well. Therefore  it returns TRUE so that the lsit control does not 
do a label edit.
<p>
After creating the edit control (with ES_MULTILINE and the list control
as the parent window), the control is positioned in the cell and 
sized to fit its content.
<p>
Here is the source for these two functions:

<PRE><TT><FONT COLOR="#990000">
void TestDlg::OnBeginlabeleditList(NMHDR* pNMHDR, LRESULT* pResult) 
	{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;

	CString str = pDispInfo->item.pszText;
	int item = pDispInfo->item.iItem;
	int subitem = pDispInfo->item.iSubItem;
	// Construct and create the custom multiline edit control.
	// We could just as well have used a combobox, checkbox, 
	// rich text control, etc.
	m_pListEdit = new CInPlaceEdit( item, subitem, str );
	// Start with a small rectangle.  We'll change it later.
	CRect  rect( 0,0,1,1 );
	DWORD dwStyle = ES_LEFT;
	dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL;
	m_pListEdit->Create( dwStyle, rect, &m_GridListCtrl, 103 );
	// Have the Grid position and size the custom edit control
	m_GridListCtrl.PositionControl( m_pListEdit, item, subitem );
	// Have the edit box size itself to its content.
	m_pListEdit->CalculateSize();
	// Return TRUE so that the list control will NOT handle the edit label itself. 
	*pResult = TRUE;
	}

void TestDlg::OnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult) 
	{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	int item = pDispInfo->item.iItem;
	int subitem = pDispInfo->item.iSubItem;
	// This is coming from the grid list control notification.
	if( m_pListEdit )
		{
		CString str;
		if( pDispInfo->item.pszText )
			m_GridListCtrl.SetItemText( item, subitem, pDispInfo->item.pszText );
		delete m_pListEdit;
		m_pListEdit = 0;
		}
	*pResult = 0;
	}
</FONT></TT></PRE>
<P>
<A HREF="GridList.zip" tppabs="http://www.codeguru.com/listview/GridList.zip">Download Sample/Code,<A>(95k)





<P>
<HR>
<TABLE BORDER=0 WIDTH="100%" >
<TR>
<TD WIDTH="33%"><FONT SIZE=-1><A HREF="../index.htm" tppabs="http://www.codeguru.com/">Goto HomePage</A></FONT></TD>

<TD WIDTH="33%">
<CENTER><FONT SIZE=-2>&copy; 1997 Zafir Anjum</FONT>&nbsp;</CENTER>
</TD>

<TD WIDTH="34%">
<DIV ALIGN=right><FONT SIZE=-1>Contact me: <A HREF="mailto:zafir@home.com">zafir@home.com</A>&nbsp;</FONT></DIV>
</TD>
</TR>
</TABLE>
<CENTER>&nbsp;<IMG SRC="../cgi/Count.cgi-ft=2&dd=E-df=lv_add_checkbox.cnt" tppabs="http://www.codeguru.com/cgi/Count.cgi?ft=2&dd=E%7cdf=lv_add_checkbox.cnt" ALIGN="BOTTOM" BORDER="0"></CENTER>
</BODY>
</HTML>

⌨️ 快捷键说明

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