Multiline Editable Subitems

This article illustrates two points:  another method of implementing subitem editing and the multiline edit control used in place of the single line edit control.  The basis of this implementation comes from the article, "Editable Subitems".
Usage Tip: To insert a return in the edit control without finishing the edit, type Ctrl-Enter.

This is part of an implementation for a custom drawn grid list control.  You can download the full gridlist control implementation at the bottom of the page. While this is based on the implementation of the Editable Subitems article, I chose to implement the newest (v4.72) common control features. In order to do the same, you will need to download the common control redistributable in order to run the sample. In order to build the sample, you will also need the Platform SDK build environment.  There is also documentation on the new common control features there as well.  All you need from the build environment are the CommCtrl.h and the ComCtl32.lib files. Make these available to your VC++ build environment.  I did this by backing up my old files and copying these into my include and lib directories respectively.
In this explanation, I call out certain functions from the grid list control sample which pertain to this article.

Step 1: Derive a class from CListCtrl

You will need to first derive a class from CListCtrl.  I derived CGridListCtrl. You will need to add a member variable to keep track of the current column which the user is interacting with. This variable is the column number of the item also called the column order.  Keep in mind that this may not be the same as the subitem when dragging the columns and changing their order.
// Attributes
public:
    // The current subitem or column number which is order based. 
    int m_CurSubItem;

Step 2: Enable user to edit the control

In order to access the editing of the cell, the user can do it through the mouse or keyboard.  For more information on the cell navigation with the keyboard see the article, "Grid List Control." For the mouse click, we must first determine which subitem was clicked.  The new common controls have a message which is macro-ed as ListView_SubItemHitTest that does the job nicely.  The function below also uses the Header_OrderToIndex macro to resolve the subitem clicked to an order variable. Also defined for this control is the IndexToOrder which goes the other direction in resolving the index to a column order.  After we determine that we want to edit, we send a message to the parent indicating the beginning of label editing.
void CGridListCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
        {
        LVHITTESTINFO ht;
        ht.pt = point;
        // Test for which subitem was clicked.
        // Use macro since this is new and not in MFC.
        int rval = ListView_SubItemHitTest( m_hWnd, &ht );

        // Store the old column number and set the new column value.
        int oldsubitem = m_CurSubItem;
        m_CurSubItem = IndexToOrder( ht.iSubItem );

        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
        // Make the column fully visible.
        // We have to take into account that the columns may be reordered
        MakeColumnVisible( Header_OrderToIndex( pHeader->m_hWnd, m_CurSubItem ) );

        // Store old state of the item.
        int state = GetItemState( ht.iItem, LVIS_FOCUSED );

        // Call default left button click is here just before we might bail.
        // Also updates the state of the item.
        CListCtrl::OnLButtonDown(nFlags, point);

        // Bail if the state from before was not focused or the 
        // user has not already clicked on this cell.
        if( !state 
                || m_CurSubItem == -1 
                || oldsubitem != m_CurSubItem ) return;

        int doedit = 0;
        // If we are in column 0 make sure that the user clicked on 
        // the item label.
        if( 0 == ht.iSubItem )
                {
                if( ht.flags & LVHT_ONITEMLABEL ) doedit = 1;
                }
        else
                {
                doedit = 1;
                }
        if( !doedit ) return;

        // Send Notification to parent of ListView ctrl
        CString str;
        str = GetItemText( ht.iItem, ht.iSubItem );
        LV_DISPINFO dispinfo;
        dispinfo.hdr.hwndFrom = m_hWnd;
        dispinfo.hdr.idFrom = GetDlgCtrlID();
        dispinfo.hdr.code = LVN_BEGINLABELEDIT;
        
        dispinfo.item.mask = LVIF_TEXT;
        dispinfo.item.iItem = ht.iItem;
        dispinfo.item.iSubItem = ht.iSubItem;
        dispinfo.item.pszText = (LPTSTR)((LPCTSTR)str);
        dispinfo.item.cchTextMax = str.GetLength();
        
        GetParent()->SendMessage( WM_NOTIFY, GetDlgCtrlID(), 
                (LPARAM)&dispinfo );
        }
int CGridListCtrl::IndexToOrder( int iIndex )
        {
        // Since the control only provide the OrderToIndex macro,
        // we have to provide the IndexToOrder.  This translates
        // a column index value to a column order value.
        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
        int colcount = pHeader->GetItemCount();
        int *orderarray = new int[ colcount ];
        Header_GetOrderArray( pHeader->m_hWnd, colcount, orderarray );
        int i;
        for( i=0; i<colcount; i++ )
                {
                if( orderarray[i] == iIndex )
                        return i;
                }
        return -1;
        }
The user should be able to start editing through the keyboard as well. The code below overrides the PreTranslateMessage function. As in Explorer, F2 commences nondestructive editing.
BOOL CGridListCtrl::PreTranslateMessage(MSG* pMsg) 
    {
    if(pMsg->message == WM_KEYDOWN)
        {
        // Handle the keystrokes for the left and right keys
        // to move the cell selection left and right.
        // Handle F2 to commence edit mode from the keyboard.
        // Only handle these if the grid control has the focus.
        // (Messages also come through here for the edit control
        // and we don't want them.
        if( this == GetFocus() )
            {
            switch( pMsg->wParam )
                {
                case VK_LEFT:
                    {
                    // Decrement the order number.
                    m_CurSubItem--;
                    if( m_CurSubItem < -1 ) 
                        {
                        // This indicates that the whole row is selected and F2 means nothing.
                        m_CurSubItem = -1;
                        }
                    else
                        {
                        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
                        // Make the column visible.
                        // We have to take into account that the header
                        // may be reordered.
                        MakeColumnVisible( Header_OrderToIndex( pHeader->m_hWnd, m_CurSubItem ) );
                        // Invalidate the item.
                        int iItem = GetNextItem( -1, LVNI_FOCUSED );
                        if( iItem != -1 )
                            {
                            CRect rcBounds;
                            GetItemRect(iItem, rcBounds, LVIR_BOUNDS);
                            InvalidateRect( &rcBounds );
                            }
                        }
                    }
                    return TRUE;
                case VK_RIGHT:
                    {
                    // Increment the order number.
                    m_CurSubItem++;
                    CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
                    int nColumnCount = pHeader->GetItemCount();
                    // Don't go beyond the last column.
                    if( m_CurSubItem > nColumnCount -1 ) 
                        {
                        m_CurSubItem = nColumnCount-1;
                        }
                    else
                        {
                        // We have to take into account that the header
                        // may be reordered.
                        MakeColumnVisible( Header_OrderToIndex( pHeader->m_hWnd, m_CurSubItem ) );
                        int iItem = GetNextItem( -1, LVNI_FOCUSED );
                        // Invalidate the item.
                        if( iItem != -1 )
                            {
                            CRect rcBounds;
                            GetItemRect(iItem, rcBounds, LVIR_BOUNDS);
                            InvalidateRect( &rcBounds );
                            }
                        }
                    }
                    return TRUE;
                case VK_F2: // Enter nondestructive edit mode.
                    {
                    int iItem = GetNextItem( -1, LVNI_FOCUSED );
                    if( m_CurSubItem != -1 && iItem != -1 )
                        {
                        // Send Notification to parent of ListView ctrl
                        CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
                        CString str;
                        // We have to take into account that the header
                        // may be reordered.
                        str = GetItemText( iItem, Header_OrderToIndex( pHeader->m_hWnd, m_CurSubItem ) );
                        LV_DISPINFO dispinfo;
                        dispinfo.hdr.hwndFrom = m_hWnd;
                        dispinfo.hdr.idFrom = GetDlgCtrlID();
                        dispinfo.hdr.code = LVN_BEGINLABELEDIT;
                        
                        dispinfo.item.mask = LVIF_TEXT;
                        dispinfo.item.iItem = iItem;
                        // We have to take into account that the header
                        // may be reordered.
                        dispinfo.item.iSubItem = Header_OrderToIndex( pHeader->m_hWnd, m_CurSubItem );
                        dispinfo.item.pszText = (LPTSTR)((LPCTSTR)str);
                        dispinfo.item.cchTextMax = str.GetLength();
                        // Send message to the parent that we are ready to edit.
                        GetParent()->SendMessage( WM_NOTIFY, GetDlgCtrlID(), 
                            (LPARAM)&dispinfo );
                        }
                    }
                    break;
                default:
                    break;
                }
            }
        }
    
    return CListCtrl::PreTranslateMessage(pMsg);
    }


 

Step 3: Add supporting function

If the user clicks on a column that is not fully visible, make it visible.  The function MakeColumnVisible makes the column visible by scrolling the control. It gets the current column ordering to do this.
void CGridListCtrl::MakeColumnVisible(int nCol)
	{
	if( nCol < 0 )
		return;
	// Get the order array to total the column offset.
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int colcount = pHeader->GetItemCount();
	ASSERT( nCol < colcount );
	int *orderarray = new int[ colcount ];
	Header_GetOrderArray( pHeader->m_hWnd, colcount, orderarray );
	// Get the column offset
	int offset = 0;
	for( int i = 0; orderarray[i] != nCol; i++ )
		offset += GetColumnWidth( orderarray[i] );
	int colwidth = GetColumnWidth( nCol );
	delete[] orderarray;
	
	CRect rect;
	GetItemRect( 0, &rect, LVIR_BOUNDS );
	
	// Now 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;
        }
	}

 

Step 4: Handle the scroll messages

The CInPlaceEdit class sends the end label edit message when it loses focus. Clicking on the scrollbars of the ListView control does not take away the focus from the edit control. We therefore add handlers for the scrollbar messages which force focus away from the edit control by setting the focus to the list view control itself.
void CMyListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
        if( GetFocus() != this ) SetFocus();
        CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
        if( GetFocus() != this ) SetFocus();
        CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}

Step 5: Add positioning function for the editing control

In case you have not noticed by now, the list control does not handle the beginning and ending label edit messages. This is unlike the "Edit Subitems" article. The reason for having the list control's parent handle the edit control instantiation and destruction is so that controls that take a long time to instantiate can be instantiated once and reused by the parent control. This might come in handy if a combobox was used and had 2,000 entries for instance. Since the parent creates the editing control, the list control still needs to position the control in the cell it is editing. That is what this function does.
BOOL CGridListCtrl::PositionControl( CWnd * pWnd, int iItem, int iSubItem )
	{
	ASSERT( pWnd && pWnd->m_hWnd );
	ASSERT( iItem >= 0 );
	// Make sure that the item is visible
	if( !EnsureVisible( iItem, TRUE ) ) return NULL;
	
	// Make sure that nCol is valid
	CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
	int nColumnCount = pHeader->GetItemCount();
	ASSERT( iSubItem >= 0 && iSubItem < nColumnCount );
	if( iSubItem >= nColumnCount || 
		// We have to take into account that the header may be reordered
		GetColumnWidth(Header_OrderToIndex( pHeader->m_hWnd,iSubItem)) < 5 )
		{
		return 0;
		}
	
	// Get the header order array to sum the column widths up to the selected cell.
	int *orderarray = new int[ nColumnCount ];
	Header_GetOrderArray( pHeader->m_hWnd, nColumnCount, orderarray );
	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;	
	}

Step 6: Subclass the CEdit class

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.
  • OnKillFocus still sends the parent of the list control the end label edit message, but it does not call the destroy window.
  • 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.
  • 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.
The CPP file contents are included here:
// 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 );
	}

Step 7: Handle the begin and end label messages

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.

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.

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.

Here is the source for these two functions:

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;
	}

Download Sample/Code,(95k)



Comments

  • por qué debemos elegir la calidad de Dr Dre

    Posted by cheneason on 06/04/2013 12:42am

    [url=http://www.beatsbydrdrebaratos.weebly.com/]beats by dre baratos[/url] Dr. Dre Beats by Dre hovedtelefoner tendens til at være så dygtige i mange hovedtelefoner producerer. Blandt det store udvalg af Monster Beatshovedtelefoner med næsten alle håndsæt kan individuelt kunne være Fahion trend med blanding, med fremragende fordele. De behøver ikke nødvendigvis giver et individ af Dr. Dre hovedtelefoner som de to sider. [url=http://www.beats-by-dr-dre-2013.webstarts.com/]auriculares beats[/url] Hvis du interesserer lyden, hvordan man kan lytte til din musik, så vil du elske deBeats by Dr. Dre solo højtydende hovedtelefoner. Uanset om du er fagfolk eller entusiaster, de er den perfekte høj kvalitet at lytte til dig igen, hvis du interesserer lyd, hvordan du kan lytte til din musik på farten, så vil du elske beat af Dr. Dre Solo high-performance hovedtelefoner. Uanset om du er fagfolk eller entusiaster, de er perfekte, høj kvalitet lytter til dig på vejen. [url=http://www.beatsbydre2013.moonfruit.com/]beats by dre españa[/url] Ligegyldigt om nogen efterspørgsel en ny hookup vedrørende personlig ansætte i dit hus samt med henblik på at venstre arm din nuværende lille vedrørende institution, dette er den meget specielle, der vil sikre en favorit BIII øretelefoner spørgende, Min ægtefælle og jeg gravede lidt dybere involveret med det sammen med min ægtefælle og jeg, din ml i allexpect en ny, netop hvad jeg lige kigger ind nedenfor besøgende i de mange standard fornødenheder. Sandheden er, jeg er bare planlægning for dig at adskille idéen sammen i dit tilfælde for at sige det kort sort.

    Reply
  • Fashion Party, billige ghd glattejern giver dig en unik frisure

    Posted by motherdhmm on 05/30/2013 09:27am

    [url=http://www.buy-beatsdrdre.com/]beats by dre headphones[/url] Få et glattejern som din frisør også ville bruge. De fleste frisør saloner har brug for unedbrydelige glattejern som ghd fladjern tilbud holder til at blive brugt hver eneste dag. Derfor har hoveddelen af saloner verden over valgt at benytte GHD glattejernene. [url=http://www.buy-beatsdrdre.com/category/new-beats-dr-dre-headphones]Beats By Dr Dre[/url] GHD Fladjern elsker i øjnene af beskueren, den mest romantiske Valentinsdag i Kina, som udgør deres egen skønhed. Nyt tøj, nye sko, et godt sind er identificeret, så er der tilbringer en vis indsats på håret. Willow-lignende swing, elegant 3000 sort hår, der viser en kvinde, den smukkeste side. Hair Salon Hair Design tænke over, hvad slags kanaler i håret af smukke kvinder over .. [url=http://www.buy-beatsdrdre.com/]beats by dre headphones[/url] Din særskilt web-site kan være din person i den vigtigste form for bare at leve netto web-sites inden for de britiske øer denne særlige tilbyder en utrolig mængde af krøllet hår behandling metode variabler ved hjælp af en række forskellige producenter. Disse former for god hår dag krøllet hår produkter igennem flere situationer tilbydes i form af faldende gebyrer. Denne unikke God hår dag Power Suppressor er normalt normalt en stærk tilstrækkeligt godkendt vilde hår terapi om at samle meget følsom med hinanden med sårede Lokker.

    Reply
  • Noticeable delay in specific instance

    Posted by Golovko on 11/03/2005 01:44pm

    When the user clicks from one subitem to any other subitem on the same row, there is a noticable delay until the focus is drawn on the newly selected subitem. Has anyone noticed this and/or know a way to fix this?

    Reply
  • Correction for PositionControl

    Posted by zandr on 03/03/2004 07:12am

    rect.left -= size.cx; produces incorrect results when a column wasn't scrolled by Scroll( size ); to be very first visible column on the screen. It should be removed and replaced by yet another call of GetItemRect( iItem, &rect, LVIR_BOUNDS ); if( offset + rect.left < 0 || offset + colwidth + rect.left > rcClient.right ) { CSize size; size.cx = offset + rect.left; size.cy = 0; Scroll( size ); GetItemRect( iItem, &rect, LVIR_BOUNDS ); }

    Reply
  • Bug

    Posted by Legacy on 05/26/2003 12:00am

    Originally posted by: ajeet

    When u select a cell and drag it to another it crashes.Why it happens so.
    ajeet

    Reply
  • How can I program to get the effect of one click subitem?

    Posted by Legacy on 10/04/2002 12:00am

    Originally posted by: jchen

    When I left click one of the subitem, the selected line become blue and the subitem become grey .
    How can I program to get the effect ?

    Reply
  • Process a Dialog box on a click of a list view row selected

    Posted by Legacy on 06/04/2002 12:00am

    Originally posted by: Mahesh

    hi .. 
    
    i need to process a dialog box when i click on a selected row . the fields which are in the selected row of the list control should be displayed in the new dialog boxes edit controls ..anyway to do this .?can anyone guide me .. ??

    thanks & regards

    Reply
  • Possible bugs?

    Posted by Legacy on 03/22/2002 12:00am

    Originally posted by: Dan

    First off, thanks for the code -- it's a very handy control.

    There appears to be one bug in which if the text of the editcontrol is empty, the CInPlaceEdit::CalculateSize makes the control the full width of the parent. I just added a check for an empty string and returned accordingly.

    There's a second bug that I haven't figured out yet, which is if "Single Selection" Style of the ListView is set on (in, say, MSDEV resource editor), clicking on subitem fields sometimes doesn't highlight the field. A second click does properly create and show the edit control, but typically clicking once on a row, first column, then clicking on the second column, causes no "subitem highlighting" to appear on the second column. Works fine with Single Select turned off. Haven't figured this one out yet.

    Reply
  • Link Error

    Posted by Legacy on 09/15/2000 12:00am

    Originally posted by: Carla

    When I compile with the new Microsoft SDK, it gave me the kernel32.lib link error with the message "invalid file or disk full...". Is there any way to fix? Thanks!

    Reply
  • Text Truncated

    Posted by Legacy on 11/18/1999 12:00am

    Originally posted by: stoweg

    Very useful codes!

    I input double-byte texts longer than 256 charactors into the Editbox, and save it to Database (I check DB to make sure it's stored in DB correctly).

    But it's always truncated to 256 chars when I try to edit the content by clicking the subitem.

    Anyone could give me some suggestions?
    Thank you very much!

    stowe

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

  • With 81% of employees using their phones at work, companies have stopped asking: "Is corporate data leaking from personal devices?" and started asking: "How do we effectively prevent corporate data from leaking from personal devices?" The answer has not been simple. ZixOne raises the bar on BYOD security by not allowing email data to reside on the device. In addition, Zix allows employees to maintain complete control of their personal device, therefore satisfying privacy demands of valued employees and the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds