Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 05-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Centrar texto StringGrid

Hola a todos, antes de nada decir q he mirado en este foro pero no consigo aclararme con la información que busco, en concreto en este thread:
http://www.clubdelphi.com/foros/show...ght=stringgrid

Mi intención es a partir de un evento en un boton, recoger una serie de información y mostrarla en mi StringGrid. Parace que la información la recojo bien y se muestra correctamente, pero me sale el texto justificado a la izquierda.

Tras mucho pelearme he conseguido que el texto del nombre de cada columna salga en negrita, pero ahora me gustaría que todo el texto del grid apareciese centrado.

Alguien me podría explicar (si es en codigo se agradece), como deberia hacerlo en el evento drawcell?

Muchas gracias por anticipado, cualquier respuesta se agradece debido a los cabezazos que llevo ya... jeje

Un saludo!
Responder Con Cita
  #2  
Antiguo 06-05-2011
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Precisamente en ese hilo respondía a la misma pregunta que tu haces. El evento OnDrawCell expuesto se encarga de centrar los textos, sólo tienes que colocar ese código y rellenar las celdas con tus datos sin preocuparte de nada mas.

No termino de entender bien cual es tu duda.

Saludos.
Responder Con Cita
  #3  
Antiguo 06-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
pues que he probado con muchos codigos y no consigo nada. Con ese en concreto copiando y pegando tal cual me salta el siguiente error en la línea:

Código:
   char *Cadena = grid->Cells[ACol][ARow].c_str();
[BCC32 Error] MainForm.cpp(1013): E2034 Cannot convert 'wchar_t *' to 'char *'

Uso C++ Builder 2010 y en concreto el codigo compreto es:

Código:
  TStringGrid *grid = dynamic_cast<TStringGrid*>(Sender);
   HDC dc = grid->Canvas->Handle;
   char *Cadena = grid->Cells[ACol][ARow].c_str();


    StrGridTique->Canvas->Font = StrGridTique->Font;

    // Ponemos el título en negrita
    if (ACol>=0 && State.Contains(gdFixed)){
        StrGridTique->Canvas->Font->Style = TFontStyles()<< fsBold;
    }

    const AnsiString Conceptos[3]= {"Cantidad","Precio ud","Precio"};
    if(ARow==0 && ACol==0){
        StrGridTique->Canvas->TextOutA(Rect.Left, Rect.Top,"Producto");
        }
    else if(ARow==0){
        StrGridTique->Canvas->TextOutA(Rect.Left, Rect.Top, Conceptos[ACol-1] );
    }

   grid->Canvas->Brush->Style = bsClear;
   DrawText(dc, Cadena, strlen(Cadena), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );

Un saludo!
Responder Con Cita
  #4  
Antiguo 06-05-2011
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
El problema es que la versión 2010 usa Unicode.

Debes usar la versión unicode de la API DrawText: DrawTextW (el copmpilador lo hace automáticamente) y cambiar la línea
Código:
char *Cadena = grid->Cells[ACol][ARow].c_str();
a
Código:
wchar_t *Cadena = grid->Cells[ACol][ARow].c_str();
Saludos.
Responder Con Cita
  #5  
Antiguo 07-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Hola, perdona x no contestar antes pero he estado muy liado, gracias por la respuesta.

Tras hacer ese cambio ahora me pasa lo siguiente:


Error 1:Cannot convert wchar_t *' to const char *
Error 2: Type mismatch in parameter '__s' (wanted 'const char *', got 'wchar_t *')

en la 2ª línea:

Código:
grid->Canvas->Brush->Style = bsClear;
   DrawText(dc, Cadena, strlen(Cadena), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );

Un saludo!
Responder Con Cita
  #6  
Antiguo 07-05-2011
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Te explico:

Las APIs de Windows Que usan cadenas, tienen dos versiones, la terminada en A y la terminada en W. Para DrawText tenemos internamente DrawTextA y DrawTextW. Lo normal es que el compilador escoja ya apropiada según si usa Unicode (W) o no (A).

Usa la versión DrawTextW;
Código:
DrawTextW(dc, Cadena, wcslen(Cadena), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
o bien:

Código:
DrawTextW(grid->Canvas->Handle, grid->Cells[ACol][ARow].c_str(), grid->Cells[ACol][ARow].Length(), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

Saludos.
Responder Con Cita
  #7  
Antiguo 07-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Muchisimas gracias por la respuesta, pero... sigo teneniendo un problema ...

Resulta q el texto se centra bien, pero me sale dos veces, a la izquierda y centrado

Lo que me gustaría es que se viera todo centrado tanto en la fila 0 que es fija (y en negrita) como en todos los campos.

Yo lo que hago es a partir de una serie de botones, recojo unos campos y hago que se muestren en el string grid usando:
Código:
StrGridTique->Cells[0][posFila]=DBText->Caption;
y controlando posFila voy añadiendo registros y diferentes nombres en el Caption del DBText.

Y luego en el evento hago:

Código:
void __fastcall TfrmMain::StrGridTiqueDrawCell(TObject *Sender, int ACol, int ARow,
          TRect &Rect, TGridDrawState State)
{
   TStringGrid *grid = dynamic_cast<TStringGrid*>(Sender);
   HDC dc = grid->Canvas->Handle;
   wchar_t *Cadena = grid->Cells[ACol][ARow].c_str();

   grid->Canvas->Brush->Style = bsClear;
   DrawTextW(grid->Canvas->Handle, grid->Cells[ACol][ARow].c_str(), grid->Cells[ACol][ARow].Length(), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

   StrGridTique->Canvas->Font = StrGridTique->Font;

    // Ponemos el título en negrita
    if (ACol>=0 && State.Contains(gdFixed)){
        StrGridTique->Canvas->Font->Style = TFontStyles()<< fsBold;
    }

    // Preparamos la rejilla con el tique
    const AnsiString Conceptos[3]= {"Precio unitario","Cantidad","Precio"};
    if(ARow==0 && ACol==0){
        StrGridTique->Canvas->TextOutA(Rect.Left, Rect.Top,"Producto");
    }
    else if(ARow==0){
        StrGridTique->Canvas->TextOutA(Rect.Left, Rect.Top, Conceptos[ACol-1] );
    }
    else if (ARow>0){
        tposFila=ARow;
        bEditarCantidad=true;
    }
}

Uff perdona por mi insistencia, pero es que voy dando tumbos constantemente, veo que la solución está cerca pero no consigo llegar, jeje

Muchísimas gracias por adelantado.

Un saludo!
Responder Con Cita
  #8  
Antiguo 07-05-2011
Avatar de aams01
aams01 aams01 is offline
Miembro
 
Registrado: ago 2010
Posts: 44
Poder: 0
aams01 Va por buen camino
Hola soy re-novato espero comprension si es que me equivoco.
Por que no desde que se active la forma pones los titulos de la rejilla
en cuanto se active la forma.
Código:
void __fastcall TTfrmMain::FormActivate(TObject *Sender)
{
	StrGridTique->Cells[0][0]="Precio unitario";
	StrGridTique->Cells[1][0]="Cantidad";
	StrGridTique->Cells[2][0]="Precio";

}
Para poner en negritas y centrar con lo siguiente recorte tu codigo asi que le hace falta el ultimo if por lo demas yo creo si lo hace
Código:
void __fastcall TTfrmMain::StrGridTiqueDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect,
		  TGridDrawState State)
{

  StrGridTique->Canvas->Brush->Color = clBtnFace; // Color por default, 
//  cambialo al que gustes, Esto es para que no te empalme la informacion
  StrGridTique->Canvas->Rectangle(Rect);
  InflateRect(&Rect, -2, -2);
  if (ARow==0) {
	   StrGridTique->Canvas->Font->Style = TFontStyles()<< fsBold;
  }

  DrawTextW(StrGridTique->Canvas->Handle, StrGridTique->Cells[ACol][ARow].c_str(), StrGridTique->Cells[ACol][ARow].Length(), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

  if (ARow>0){
        tposFila=ARow;
        bEditarCantidad=true;
    }
}
Todo este codigo fue tomado de escafandra en uno de los temas, ojala y no enoje por tomar su codigo


Buno yo tengo unas preguntas para que utilizas
Código:
StrGridTique->Canvas->Brush->Style = bsClear;
__________________
El Software es como el Sexo, si es de gratis es Mejor

Última edición por aams01 fecha: 07-05-2011 a las 22:59:09.
Responder Con Cita
  #9  
Antiguo 08-05-2011
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
aams01 te está dando parte de la solución.

Piensa que estás escribiendo textos en las rejillas dos veces, una centrado con DrawTextW y la otra a la izquierda con TextOutA. Lo propio es añadir los nuevos textos en otro procedimiento, de carga o en todo caso, con DrawTextW para poder centrarlos.

Pero aún te falta otra cosa. La VCL escribe por su cuenta las celdas a la izquierda. Si quieres redibujarlas debes borrarlas previamente y luego reescribirlas.

Código:
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
   TStringGrid *grid = dynamic_cast<TStringGrid*>(Sender);
  
   InflateRect(&Rect, -1, -1);
  
   // Ajusto los colores de las celdas a las preestablecidos   
   if(State.Contains(gdFixed))
      grid->Canvas->Brush->Color = grid->FixedColor;
   else
      grid->Canvas->Brush->Color = grid->Color;

   // Borro las celdas
   grid->Canvas->FillRect(Rect);

   DrawText(grid->Canvas->Handle, grid->Cells[ACol][ARow].c_str(), grid->Cells[ACol][ARow].Length(), &Rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

   // Restauro el Rect que se pasó por referencia, no por valor...
   InflateRect(&Rect, 1, 1);
}
Saludos.

Última edición por escafandra fecha: 08-05-2011 a las 00:51:00.
Responder Con Cita
  #10  
Antiguo 08-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Hola a ambos, muchisimas gracias por las respuestas.

aams01, esa parte del código es porque en la propiedad del StringGrid Drawing Style uso gdsGradient

Cita:

Buno yo tengo unas preguntas para que utilizas
Código:
StrGridTique->Canvas->Brush->Style = bsClear;
Y al aplicar el código que has aportado con los cambios de escafranda veo que las celdas fijas se ponen del color que hay puesto en la propiedad fixedColor...

He probado cambiando el Style e incluso poniendo clNone, pero no consigo que salga con efecto degradado..., se podría aplicar al Canvas el estilo gdsGradient? o al menos que sea transparente?

Muchisimas gracias! , Un saludo!
Responder Con Cita
  #11  
Antiguo 08-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Hola de nuevo, ¿sabeis si existe alguna forma de detectar cuando se entra 2 veces en la misma celda?, me explico.

Resulta que cuando entro una celda la detecto con la propiedad OnSelectCell, recojo la fila en donde se ha hecho click y así actualizo los datos cuando se introduce un nuevo valor.

Si pulso un boton actualizo de nuevo el StringGrid y si me da por hacer click otra vez en la misma celda de antes, como no la detecta no modifico los datos que corresponden.

He probado con eventos OnMouseEnter/Leave, OnGetEditText, etc..., pero no consigo que me funcionen

¿Existe alguna manera de coger y mover en ejecución la celda seleccionada?

Se me ocurre que de esta forma si siempre tras pulsar el boton selecciono la Cells[0][0], siempre detectare cuando hago click en la misma celda.


Alguna idea??, muchas gracias
Responder Con Cita
  #12  
Antiguo 08-05-2011
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por mizzard Ver Mensaje
...se podría aplicar al Canvas el estilo gdsGradient?...
Puedes escribir una función que pinte un rectángulo con un degradado para sustituir a grid->Canvas->FillRect(Rect);

Cita:
Empezado por mizzard Ver Mensaje
...¿sabeis si existe alguna forma de detectar cuando se entra 2 veces en la misma celda?...
Yo usaría algo como esto:
Código:
void __fastcall TForm1::StringGrid1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
   int ACol, ARow;
   StringGrid1->MouseToCell(X, Y, ACol, ARow);
   //..............
   // Tu código....
}
Saludos.
Responder Con Cita
  #13  
Antiguo 08-05-2011
Avatar de aams01
aams01 aams01 is offline
Miembro
 
Registrado: ago 2010
Posts: 44
Poder: 0
aams01 Va por buen camino
Cita:
Empezado por mizzard Ver Mensaje
Se me ocurre que de esta forma si siempre tras pulsar el boton selecciono la Cells[0][0], siempre detectare cuando hago click en la misma celda.
Para seleccionar un selda es con lo siguiente reucuerda que un StringGrid o DBGrid contiene renglones y columnas

Código:
StrGridTique->Col=0;
StrGridTique->Row=0;
Aunq me agrada mas el codigo de escafandra.
No obstante toy seguro de que este codigo te podra servir para otra cosa.
__________________
El Software es como el Sexo, si es de gratis es Mejor
Responder Con Cita
  #14  
Antiguo 10-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Gracias a ambos por las respuestas ya que me han sido de gran ayuda.

Ahora estoy mirando bugs e intentar corregirlos para mejorar la estabilidad del programa y uno que me surge como consecuencia directa de ir incorporando estos cambios es que me he dado cuenta que cuando se queda marcada una de las celdas el texto aparece dos veces una a la izquierda y otra vez centrado y cuando hago clic en otra celda todo vuelve a la normalidad.

Tras diversas pruebas, me he dado cuenta que si no hay ninguna celda marcada parece q todo va bien.

Comento este problema pq mi código de repente se vuelve inestable cuando pasa esto, lo que pasa es que tendré que mirarlo con más detenimiento para sacar una conclusión clara.

Como siempre, pinto con el evento ondrawcell en funcion de unas banderas que activo desde otras secciones del codigo.

Alguna idea de pq puede pasar esto?

Un saludo!
Responder Con Cita
  #15  
Antiguo 10-05-2011
Avatar de aams01
aams01 aams01 is offline
Miembro
 
Registrado: ago 2010
Posts: 44
Poder: 0
aams01 Va por buen camino
Post

Hola como mencionas si solo pasa eso cuando dejas seleccionada una celda por que no quitas el focus de ese componente y lo pasas ya sea a un botón o a un edit.
El problema creo es por q tienes el stringrid en modo edición.
Si el stringrid solo lo quieres para mostrar y jalar información yo diría que le quites la opción de editar, ya q te ahorraras tiempo en validar
__________________
El Software es como el Sexo, si es de gratis es Mejor
Responder Con Cita
  #16  
Antiguo 10-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Hola aams01,

Al final tras muchos intentos consigo quitar el foco, pero estableciéndoselo a otro elemento no funciona. Buscando por el foro he encontrado este que sí que funciona (aporte de escafandra):

Código:
    TGridRect NoRect;
    NoRect.Top = NoRect.Left = NoRect.Right = NoRect.Bottom = -1;
    frmMain->StrGridTique->Selection=NoRect;
El caso es que funciona, pero nuevamente vuelvo a tener problemas. En mi StringGrid cambio a la opcion de editar cuando hago clic en una columna, en el resto de casos deshabilito la opcion de editar (esto parece que funciona bien).

El error en concreto sale cuando al terminar de realizar rellenar el StringGrid y de realizar las operaciones pertinentes (únicamente cuando edito un dato en una celda, si no lo edito no sale el error), quito la celda seleccionada, la limpio de información y entonces aparece un mensaje de error, a continuación muestro el codigo y cuándo aparece el mensaje:

Cuando termino de operar con el StringGrid... (hasta aquí sin problemas) hago lo siguiente:

Código:
quitarFocoGrid(); // función que contiene el código de arriba

// Limpiamos el Grid de información
// RowCount-2 porque no me interesa la fila fija ni la que se crea despues de la que contiene informacion (esto probado a parte funciona)
        for (int cont = frmMain->StrGridTique->RowCount-2; cont > 0; cont--) {
            frmMain->StrGridTique->Rows[cont]->Clear();
            frmMain->StrGridTique->RowCount=frmMain->StrGridTique->RowCount-1;
        }
        frmMain->StrGridTique->Cells[0][0]="";
        frmMain->StrGridTique->Cells[1][0]="";
        frmMain->StrGridTique->Cells[2][0]="";
        frmMain->StrGridTique->Cells[3][0]="";

// Mostramos un mensaje informativo
Application->MessageBoxA(L"Puede retirar la tarjeta.",L"Información",MB_OK+ MB_ICONINFORMATION);
Y cuando le doy a aceptar sale el siguiente mensaje de error:

EListError with message 'List indexof bounds (-1)'

He probado a poner la de quitar el foco al final del borrado de la tabla y pasa lo mismo pero el mensaje sale en otra parte del código, por lo que el problema es el mismo.

Alguna idea de cómo puedo hacer el borrado y quitar la fila seleccionada (o al revés) sin que dé este problema??

Muchas gracias y un saludo!

Última edición por mizzard fecha: 10-05-2011 a las 11:47:44.
Responder Con Cita
  #17  
Antiguo 10-05-2011
Avatar de aams01
aams01 aams01 is offline
Miembro
 
Registrado: ago 2010
Posts: 44
Poder: 0
aams01 Va por buen camino
Hola por curiosidad solo cambia
Código:
    Application->MessageBoxA(L"Puede retirar la tarjeta.",L"Información",MB_OK + MB_ICONINFORMATION);
por
Código:
Application->MessageBoxA(L"Puede retirar la tarjeta.",L"Información",MB_OK| MB_ICONINFORMATION);
y con respecto al error que te manda probe tu codigo y no marca ningun error
__________________
El Software es como el Sexo, si es de gratis es Mejor
Responder Con Cita
  #18  
Antiguo 11-05-2011
mizzard mizzard is offline
Miembro
NULL
 
Registrado: feb 2011
Posts: 100
Poder: 14
mizzard Va por buen camino
Hola aams01, al final lo solucioné revisando código y añadiendo en una sección que no fuera editable.

Cita:
Hola por curiosidad solo cambia
Código:
Application->MessageBoxA(L"Puede retirar la tarjeta.",L"Información",MB_OK + MB_ICONINFORMATION);
por
Código:
Application->MessageBoxA(L"Puede retirar la tarjeta.",L"Información",MB_OK| MB_ICONINFORMATION);
y con respecto al error que te manda probe tu codigo y no marca ningun error
Probé esto pero es indiferente, funciona igual.

Muchas gracias por las molestias, un saludo!
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Centrar imagen que esta en las celdas de un StringGrid gulder Varios 4 11-12-2008 19:48:02
Centrar texto en un memo Tilk Varios 1 12-11-2008 01:19:13
Centrar el texto de un edit Sayuri Varios 2 19-03-2008 21:28:59
Centrar el texto de una columna en el componente DrawGrid Aprendiendo OOP 0 30-09-2004 00:55:00
Centrar bmp en celda de stringgrid mosorio OOP 2 31-03-2004 06:15:27


La franja horaria es GMT +2. Ahora son las 15:24:02.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi