Tengo un control CRichEditCtrl y quiero guardar en disco su contenido
¿Que tengo que hacer si supera los 65025 caracteres?
Lo que intente es esto:
unsigned long Tam;
Tam=m_CtrlVistaTexto.GetTextLength();
LPTSTR Texto;
m_CtrlVistaTexto.GetWindowText(Texto,Tam);
Arch.Write(Texto,Tam);
Arch.Close();
Pero resulta q la funcion Write de CFile solo acepta como segundo parametro un UINT
Y si pruebo a escribirlo a trozos no me deja hacer esto: Arch.Write(Texto,1) Para asi poder escribir caracter a caracter.
Y ya de paso; si sabeis algun tutorial del CRichEditCtrl bienvenida sea la URL :)
Asias de antemano
Antares
Hola!
Lo primero... el limite de un UINT es de 4000 millones, creo, no de 65000.
Sobre la funcion Write, no la conozco pero prueba esto:
Write( &texto[ i ], 1 );
Te pide una direccion, y tu no se la estas dando.
Espero que te ayude!
Adios!
Aunque no lo he podido probar creo q tienes razon en lo de direccionar, crei q como ya era un puntero bastaba.
Tenia entendido que UINT era unsigned int, o sea 2 bytes, 65000.
No encuentro manera de conseguir todo el texto. La unica forma que veo es leerlo y escribirlo linea a linea. Algo asi.
int NumLineas,TamLinea,Linea,LongMaxLinea=32000;
LPTSTR pTexto;
NumLineas=m_CtrlVistaTexto.GetLineCount();
for(Linea=0;Linea<=NumLineas;Linea++)
{
TamLinea=m_CtrlVistaTexto.GetLine(Linea,pTexto,LongMaxLinea);
Arch.Write(&pTexto,TamLinea);
}
Compila sin problemas pero al ejecutar la linea del GetLine me da un error de Unhandle Exception Creo que es por que LPTSTR esta mal referenciada o mal iniciada y esq no encuentro info sobre LPTSTR.
En la MSDN la referencia a GetLine viene asi:
Citar
CRichEditCtrl::GetLine
int GetLine( int nIndex, LPTSTR lpszBuffer ) const;
int GetLine( int nIndex, LPTSTR lpszBuffer, int nMaxLength ) const;
Return Value
The number of characters copied into lpszBuffer.
Parameters
nIndex
Zero-based index of the line to retrieve.
lpszBuffer
Points to the buffer to receive the text. The first word of the buffer must specify the maximum number of bytes that can be copied into the buffer.
nMaxLength
Maximum number of characters that can be copied into lpszBuffer. The second form of GetLine places this value into the first word of the buffer specified by lpszBuffer.
Remarks
Call this function to retrieve a line of text from this CRichEditCtrl object. The copied line does not contain a terminating null character.
Note Because the first word of the buffer stores the number of characters to be copied, make sure that your buffer is at least 4 bytes long.
1 ¿Como me aseguro de que mi buffer tiene 4 bytes?
2 ¿Que significa la constante 'const' que pone antes del final ';' de la funcion?
3 ¿Donde esta la info de LPTSTR en la MSDN?
4 Y como no; ¿donde esta el fallo?
Ayuda plis
El novato de Antares
Hola,
LPTSTR es un puntero a una cadena de caracteres, o sea *char.
Hay cosas que no vienen en las MSDN, pero que puedes buscar dandole al botón derecho del ratón encima de la palabra en cuestión (en el código) y seleccionando Go To Definition Of .... Si tienes activado "Generate Browse Info" en Proyect->Setings->C/C++, te aparecerá el fichero donde está definida la palabreja, con lo que podrás averiguar qué tipo de dato es.
En cuanto a la llamada a GetLine, tienes que pasarle un puntero a una cadena de caracteres. Esa cadena de caracteres es la que recibirá la linea. Sin embargo tú le pasas un puntero sin inicializar, o sea, sin espacio reservado (aunque le dices a la función que tiene 32000 bytes para poner los datos), por eso es normal que de errores. También para que un bucle for se repita N veces, si empiezas en el 0, debes poner
int NumLineas,TamLinea,Linea,LongMaxLinea=32000;
char pTexto[32000];
NumLineas=m_CtrlVistaTexto.GetLineCount();
for(Linea=0;Linea<NumLineas;Linea++)
{
TamLinea=m_CtrlVistaTexto.GetLine(Linea,pTexto,LongMaxLinea);
Arch.Write(pTexto,TamLinea);
}
tambien podrias hacer esto, que es lo mismo:
int NumLineas,TamLinea,Linea,LongMaxLinea=32000;
char *pTexto;
pTexto=new char[LongMaxLinea];
NumLineas=m_CtrlVistaTexto.GetLineCount();
for(Linea=0;Linea<NumLineas;Linea++)
{
TamLinea=m_CtrlVistaTexto.GetLine(Linea,pTexto,LongMaxLinea);
Arch.Write(pTexto,TamLinea);
}
delete pTexto;
De todas formas, no necesitas escribir en el fichero línea a línea, ya que como dijo MChiz, un entero en windows tiene 32 Bits (4 bytes), o sea, que puedes escribir 4 Gigas de golpe. Seguro que te confundes con MSDOS y con el Borland, que un entero era de 16 bits, pero aquello ya pasó :ojo:
un saludo
Ya esta solucionado: He sido prudente y he esperado unos dias teniendolo a prueba creo q ya funciona bien he remplazado 20000 palabras en un archivo de 17 Mg le cuesta lo suyo pero son 20000 palabras en 17 Gigas:P
Sabiendo q puedo escribir cuatro gigas, lo dificil me fue conseguir el texto entero en un puntero pq con GetDlgItemText solo pillaba 32000 un SHORT... asi q la unica manera que conozco de conseguir todo el texto del control CRichEditCtrl es seleccionandolo y usando GetSelText si alguien conoce una manera no tan chapucera encantado de atenderle :P aunque la verdad casi no se nota restaurando la seleccion anterior y la primera linea a la vista.
Respecto a lo de los limites al fin encontre la pag q tanto deseaba se titula C Integer Limits
Asi q un short es lo mismo que en msdos un int pero el long no ha aumentado sino q queda ahora igual que el int.
El uint 4.294.967.295 uf ¡Que guay! :)
No veo ninguna diferencia entre el int y el long.
Enga... y gracias por vuestra ayuda, por sacarme de ese tremendo error
Y para que quede constancia esto es lo que he hecho:
void CReempView::OnGuardar()
{
CFile Arch;
if(Arch.Open(RutaCompleta,CFile::modeWrite))//CFile::modeCreate |
{
UINT TamArch,PrimLineaMem,PrimLinea,Dif;
//Declaramos un puntero a una cadena de texto y la inicializamos con el tamaño del archivo;
TamArch=m_CtrlVistaTexto.GetTextLength();
char *pTexto;
pTexto=new char[TamArch+1];//es lo mismo que char pTexto[TamArch];
pTexto[TamArch+1]=0;//Metemos el caracter de fin de cadena
CHARRANGE RangoMem;//Creamos una estructura donde metera el inicio y fin de la seleccion actual
m_CtrlVistaTexto.GetSel(RangoMem);//Guardamos la seleccion actual o posicion del cursor en RangoMem
PrimLineaMem=m_CtrlVistaTexto.GetFirstVisibleLine();
//LineaCurso=m_CtrlVistaTexto.LineFromChar(-1);
CHARRANGE Rango;//Creamos otra estructura para indicarle lo que queremos seleccionar
Rango.cpMin=0;
Rango.cpMax=-1;//TamArch;//Si ponemos -1 selecciona todo el texto
//Obtenemos el texto seleccionandolo y luego volvemos la vista y la seleccion anterior
m_CtrlVistaTexto.HideSelection(true,true);
m_CtrlVistaTexto.SetSel(Rango);
m_CtrlVistaTexto.GetSelText(pTexto);
m_CtrlVistaTexto.HideSelection(false,false);
m_CtrlVistaTexto.SetSel(RangoMem);
PrimLinea=m_CtrlVistaTexto.GetFirstVisibleLine();
Dif=PrimLineaMem-PrimLinea;
m_CtrlVistaTexto.LineScroll(Dif,NULL);
//Lo escribimos
Arch.Write(pTexto,TamArch);
Arch.SetLength(TamArch);
Arch.Close();
m_CtrlVistaTexto.SetModify(false);
Cambios=false;
Cancel=false;
//delete pTexto;
//Si intento borrar la variable me da un error DAMAGE: after Nomal block
}
else if(Cambios==false)
AfxMessageBox("No se han efectuado cambios",MB_ICONINFORMATION);
else
AfxMessageBox("No se puede abrir el archivo para guardar",MB_ICONERROR);
}
Antares
Hey, eso podría servir como un buen code of the week ;)
Enserioooooo
:oops:
Que es lo que te ha gustado. ¿"La trampa" de seleccionar para conseguir el texto?
O lo dices solo por el volumen?
Antares :P
El código en sí, que puede resultar instructivo para otros que tengan el mismo problema :)