List Control

20/05/2005 - 18:30 por Willser F. González C. | Informe spam
Hola Grupo,

Necesito llenar un list control (en modo reporte) con 120.000 registros
provenientes de una tabla Sybase ASE.

Por ahora lo estoy haciendo manualmente porque necesito mostrar formateado
el contenido de cada campo.

Así:

void CEstViewView::OnUpdateEstreg()
{
int i = 0;

CString l_csChain;


BeginWaitCursor();

m_clcEstReg.DeleteAllItems();


// Con estas dos líneas se consigue disminuir en poco más del 50% el
tiempo de llenado.

m_clcEstReg.EnableWindow(false);
m_clcEstReg.ShowWindow(SW_HIDE);


m_crerEstReg.Requery(); // Toma 3 segundos.


if (!m_crerEstReg.IsBOF())
{
m_crerEstReg.MoveLast(); // Actualizar el contador de registros.
Toma 36 segundos.

m_crerEstReg.MoveFirst();
}

m_clcEstReg.SetItemCount(m_crerEstReg.GetRecordCount()); // Ahorro de
6 segundos.

// El siguiente while(...) toma 52 segundos.
// Sin el Format(...) ni el InsertItem(...): 50 segundos.
// Sólo con el Format(...) y el InsertItem(...) (sin MoveNext(...)): 6
segundos.

while (!m_crerEstReg.IsEOF())
{
l_csChain.Format("%d.%02d.%02d",
m_crerEstReg.m_opefecha.GetYear(),
m_crerEstReg.m_opefecha.GetMonth(),
m_crerEstReg.m_opefecha.GetDay());

// Por ahora, formatear y llenar sólo la primer columna.

m_clcEstReg.InsertItem(i++, l_csChain);

m_crerEstReg.MoveNext();
}

m_clcEstReg.ShowWindow(SW_SHOW);
m_clcEstReg.EnableWindow();

EndWaitCursor();
}

El tiempo actual oscila entre los 40 a 45 segundos.

Si se aplica el m_clcEstReg.SetItemCount(m_crerEstReg.GetRecordCount()) se
tiene un ahorro de 6 segundos, pero para poder conocer el número de
registros se necesita ejecutar un MoveLast(...), pero este comando implica
un consumo adicional de 36 segundos.

Aparte del SetItemCount(...), del EnableWindow(...) y del ShowWindow(...)
qué otras opciones se pueden aplicar a este método de llenado del List
Control para disminuir el tiempo?. Recuerdo haber leído algo al respecto un
tiempo atrás, pero ahora no sé dónde lo leí.

El acceso a la tabla es con CRecordset.

Mil Gracias.

Willser F.
willser@gmail.com

Preguntas similare

Leer las respuestas

#1 William GS
23/05/2005 - 04:27 | Informe spam
Hola, no soy expero en el tema, pero quizá una lista
virtual te ayude. Busca por "Virtual List" en
www.CodeProject.com y www.codeguru.com

William GS
Respuesta Responder a este mensaje
#2 jose
24/05/2005 - 18:10 | Informe spam
Hola Willser,

Como ha comentado William la solución pasa por utilizar una lista virtual
. Estas listas lo que hacen es consultar los valores a medida que
necesitan mostrarlos por lo que la inicialización es instantánea. Así, si
en pantalla solo se ven 10 filas, solo se accederá a 10 registros de la
base de datos. La obtención de los valores se realiza a través de una
función de callback que devuelve el valor a mostrar.

Te dejo el código de una clase base que utilizo para estos casos.
Debes crearte una clase derivada de la clase que te dejo. Sería algo así:

class CMiListCtrl : public CListCtrlCallBack{
public:
CMiListCtrl();
~CMiListCtrl();


void Inicializar()
{
InsertColumn( 0, _T("Columna0"), LVCFMT_LEFT, 100, 0 );
InsertColumn( 1, _T("Columna1"), LVCFMT_LEFT, 100, 1 );
...
InsertColumn( n, _T("ColumnaN"), LVCFMT_LEFT, 100, n );
DeleteAllItems();
for( int i = 0; i < nItems; i++ )
{
AddItem( i );
}
}
private:
CString QueryItemText( int n, int nColumna )
{
// Aqui obtienes el registro n
// y devuelves el texto de la columna nColumna
return csTextoPedido;
}
};

Saludos y espero que te sea útil,

Jose


/////////////////////////////////////////////////////////////////////////
////
/////////////////////////////////////////////////////////////////////////
////
// ListCtrlCallBack.h
/////////////////////////////////////////////////////////////////////////
////
/////////////////////////////////////////////////////////////////////////
////


#if !defined(AFX_LISTCTRLCALLBACK_H__ADABF951_2FC1_47B2_81E2_918662080130
__INCLUDED_)
#define AFX_LISTCTRLCALLBACK_H__ADABF951_2FC1_47B2_81E2_918662080130
__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ListCtrlCallBack.h : header file
//

/////////////////////////////////////////////////////////////////////////
////
// CListCtrlCallBack window

class CListCtrlCallBack : public CListCtrl
{
// Construction
public:
CListCtrlCallBack();

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListCtrlCallBack)
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CListCtrlCallBack();

// Generated message map functions
protected:
virtual CString QueryItemText( int nIndex, int nSubItem ) = 0;
BOOL AddItem( int nIndex, int nPos = -1 );
//{{AFX_MSG(CListCtrlCallBack)
afx_msg void OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
private:
LPTSTR AddPool( CString *pcs );
private:
CString m_csCPool[3];
LPTSTR m_pstrPool[3];
int m_nNextFree;
};

/////////////////////////////////////////////////////////////////////////
////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
before the previous line.

#endif // !defined(AFX_LISTCTRLCALLBACK_H__ADABF951_2FC1_47B2_81E2_
918662080130__INCLUDED_)


/////////////////////////////////////////////////////////////////////////
////
/////////////////////////////////////////////////////////////////////////
////
// ListCtrlCallBack.cpp
/////////////////////////////////////////////////////////////////////////
////

/////////////////////////////////////////////////////////////////////////
////
// ListCtrlCallBack.cpp : implementation file
//

#include "stdafx.h"
#include "ListCtrlCallBack.h"

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

/////////////////////////////////////////////////////////////////////////
////
// CListCtrlCallBack

CListCtrlCallBack::CListCtrlCallBack()
{
m_nNextFree = 0;
}

CListCtrlCallBack::~CListCtrlCallBack()
{
}


BEGIN_MESSAGE_MAP(CListCtrlCallBack, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlCallBack)
ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////
////
// CListCtrlCallBack message handlers

BOOL CListCtrlCallBack::AddItem( int nIndex, int nPos /* = -1 */ )
{
int nNumItems = GetItemCount();
int nInsertPos = (nPos >= 0 && nPos <= nNumItems)? nPos :
nNumItems;
LV_ITEM Item;
Item.lParam = (LPARAM) nIndex; // Guardar el indice del
item
Item.pszText = LPSTR_TEXTCALLBACK; // using callbacks to get
the text
Item.mask = LVIF_TEXT | LVIF_PARAM; // lParam and pszText
fields active
Item.iItem = nInsertPos; // position to insert new
item
Item.iSubItem = 0;
if (InsertItem(&Item) < 0) return FALSE;
else return TRUE;
}

void CListCtrlCallBack::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO *pDispInfo = (LV_DISPINFO*)pNMHDR;

if (pDispInfo->item.mask & LVIF_TEXT)
{
int nIndex = (int)pDispInfo->item.lParam;
CString csField = QueryItemText( nIndex, pDispInfo->
item.iSubItem );
LPTSTR pstrBuffer = AddPool( &csField );
pDispInfo->item.pszText = pstrBuffer;
}
*pResult = 0;
}

LPTSTR CListCtrlCallBack::AddPool(CString *pcs)
{
int nOldest = m_nNextFree;
m_csCPool[m_nNextFree] = *pcs;
LPTSTR pstrRetVal = m_csCPool[m_nNextFree].LockBuffer();
m_pstrPool[m_nNextFree++] = pstrRetVal;
m_csCPool[nOldest].ReleaseBuffer();
if( m_nNextFree == 3 ) m_nNextFree = 0;
return pstrRetVal;
}






"Willser F. González C." wrote in
news::

Hola Grupo,

Necesito llenar un list control (en modo reporte) con 120.000
registros provenientes de una tabla Sybase ASE.

Por ahora lo estoy haciendo manualmente porque necesito mostrar
formateado el contenido de cada campo.

Así:

void CEstViewView::OnUpdateEstreg()
{
int i = 0;

CString l_csChain;


BeginWaitCursor();

m_clcEstReg.DeleteAllItems();


// Con estas dos líneas se consigue disminuir en poco más del 50%
el
tiempo de llenado.

m_clcEstReg.EnableWindow(false);
m_clcEstReg.ShowWindow(SW_HIDE);


m_crerEstReg.Requery(); // Toma 3 segundos.


if (!m_crerEstReg.IsBOF())
{
m_crerEstReg.MoveLast(); // Actualizar el contador de
registros.
Toma 36 segundos.

m_crerEstReg.MoveFirst();
}

m_clcEstReg.SetItemCount(m_crerEstReg.GetRecordCount()); //
Ahorro de
6 segundos.

// El siguiente while(...) toma 52 segundos.
// Sin el Format(...) ni el InsertItem(...): 50 segundos.
// Sólo con el Format(...) y el InsertItem(...) (sin
MoveNext(...)): 6
segundos.

while (!m_crerEstReg.IsEOF())
{
l_csChain.Format("%d.%02d.%02d",
m_crerEstReg.m_opefecha.GetYear(),
m_crerEstReg.m_opefecha.GetMonth(),
m_crerEstReg.m_opefecha.GetDay());

// Por ahora, formatear y llenar sólo la primer columna.

m_clcEstReg.InsertItem(i++, l_csChain);

m_crerEstReg.MoveNext();
}

m_clcEstReg.ShowWindow(SW_SHOW);
m_clcEstReg.EnableWindow();

EndWaitCursor();
}

El tiempo actual oscila entre los 40 a 45 segundos.

Si se aplica el
m_clcEstReg.SetItemCount(m_crerEstReg.GetRecordCount()) se tiene un
ahorro de 6 segundos, pero para poder conocer el número de registros
se necesita ejecutar un MoveLast(...), pero este comando implica un
consumo adicional de 36 segundos.

Aparte del SetItemCount(...), del EnableWindow(...) y del
ShowWindow(...) qué otras opciones se pueden aplicar a este método de
llenado del List Control para disminuir el tiempo?. Recuerdo haber
leído algo al respecto un tiempo atrás, pero ahora no sé dónde lo leí.

El acceso a la tabla es con CRecordset.

Mil Gracias.

email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida