PDA

Ver la Versión Completa : Ajustar un Form al ancho de un texto


salvica
01-05-2004, 02:07:26
Hola y gracias por adelantado :)

Estoy intentando ajustar un Form a la línea más larga de un TListBox y después de estrujarme el "coco" :mad: ya no sé si cortarme las venas o dejármelas crecer :confused:

Lo intento en el evento OnShow del form tal que así

var
i : integer;
w : integer;
begin
w := 0;
for i:=0 to Lista.Items.Count-1 do
if( Lista.Canvas.TextWidth(Lista.Items[i])>w ) then
w := Lista.Canvas.TextWidth(Lista.Items[i]);
Form1.Width := w;
end;


Siempre se me queda corto (y eso que aún no he intentado cambiar las fuentes, el estilo ni nada)

¿Donde estoy metiendo la pata????????
Lo dicho, agradecido por la ayuda que podais prestarme

Nota: Antes de que me echeis la bronca, que conste que me he leido el foro de cabo a rabo, con búsquedas, a pelo y sigo como entré (ni repajolera idea)

jachguate
01-05-2004, 02:10:58
te has olvidado de los bordes... de los de la forma, y de los del listbox...

Has de hacer:

Form1.ClientWidth := w + Unos5o10PixelsPorElBordeDelList;

Hasta luego ;)

salvica
01-05-2004, 02:16:24
Gracias por responder tan rápido :)

Lo del borde ya lo sé, pero como de todas formas se come casi un cuarto del texto, no nos vamos a pegar por 10 ó 12 pixels de nada :D

No se te ocurre nada?
Dicen que cuatro ojos ven más que dos, ¿donde me estoy colando?
Abrazotes
Salvador

jachguate
01-05-2004, 02:24:03
en que versión de delphi estas trabajando???

Yo acabo de hacerlo en mi ya desempolvado delphi4, y con 12 pixels funciona de maravilla!

salvica
01-05-2004, 02:34:29
Hola jachguate, buenas noches-madrugadas desde Albacete

Estoy utilizando Delphi-7 porque quiero pasar los trabajos que tengo en la 3 a Kylix y aún no he instalado Linux, asi que como verás el salto es olímpico

En Delphi-3 siempre he utilizado esa forma de ajustar los Forms y funcionaba ¿?
El trabajo consiste en visualizar la respuesta de una query a un servidor mySql y que el usuario escoja entre una de los textos que devolvió el servidor, pero siempre se me queda unos dos cetímetros corto (utilizo un monitor de 19 pulgadas a 1024x800) y quiero que se vea en otros con menos resolución, por lo que he de ajustar el forma de salida en tiempo de ejecución

Gracias, voy a probar a utilizar la propiedad ClientWidth del TListBox para ver si funciona

jachguate
01-05-2004, 02:50:26
Pues yo hice la prueba original en delphi4, pero ahora la he compilado en delphi7 y funciona perfectamente...

La resolución del monitor no creo que tenga nada que ver... por si las dudas, yo uso 1280x1024.

el código:


procedure TForm1.Ajustar;
var
i : integer;
w : integer;
begin
w := 0;
for i:=0 to Lista.Items.Count-1 do
if( Lista.Canvas.TextWidth(Lista.Items[i])>w ) then
w := Lista.Canvas.TextWidth(Lista.Items[i]);
ClientWidth := w + 12;
end;


Hasta luego.

;)

jachguate
01-05-2004, 02:51:38
solo he de resaltar que este código, en caso de estar vacio el ListBox, reducirá la forma a "invisible"... :eek:

Hasta luego, y buenas noches, en Guatemala, buenos dias en Albacete ;)

;)

salvica
01-05-2004, 03:03:06
Lo más gracioso del caso, es que en el evento OnShow le he puesto que me escriba en una etiqueta y me dá un ancho de línea de 651, mientras que en el evento OnDrawItem del TListBox le he puesto otra y me dá lineas con 744 y 780

¿porqué esta diferencia?
¿Donde debo calcular el ancho de línea, antes de visualizar el Form o al "repintar" el TListBox?

jachguate
01-05-2004, 03:09:46
¿Donde debo calcular el ancho de línea, antes de visualizar el Form o al "repintar" el TListBox?Eso depende de cómo estes llenando el listbox. Si este está lleno en tiempo de diseño, o se llena antes de mostrar la forma, el evento OnShow es el adecuado.

Hasta luego.

;)

salvica
01-05-2004, 03:27:07
Haber si soy capaz de explicarlo sin ocupar más de 500.000 líneas :D

Tengo un form principal en el que le meto una clave y llama a un segundo form (con ShowModal) que con la clave del anterior hace una consulta a un servidor de mySql, el cual responde con una serie de registros que almaceno en un TListBox (hasta aqui todo funciona)

Este es el código del form principal

Application.CreateForm(TWin_GetNubes, Win_GetNubes);
with Win_GetNubes do begin
if( Alias='BAJAS' )
then CLV_GRUPO := '001'
else if( Alias='MEDIAS' )
then CLV_GRUPO := '002'
else CLV_GRUPO := '003';
GroupBox_TABLA.Caption := ' TIPOS DE NUBES ' + Alias + ' ';
ShowModal;
Free;
end; // del with


El problema viene, que al visualizar el form, este no se ajusta al texto máximo del TListBox (para que se vea toda la línea)

Este es el código del for problematico


procedure TWin_GetNubes.Form_OnShow(Sender: TObject);
var
Activo : integer;
Ancho : integer;
Cadena : string;
begin
Ancho := 0;
with Query_NUBES do begin
SQL.Clear;
SQL.Add( 'SELECT * FROM nubes WHERE grupo=''' + CLV_GRUPO + '''');
SQL.Add( ' AND orden<''100''');
SQL.Add( ' ORDER BY orden;' );
Open;
if IsEmpty then begin
{no hacer nada}
end else begin
First;
Activo := -1;
while not eof do begin
Cadena := FieldByName('NOTAS' ).AsString;
if( ListBox_NOTAS.Canvas.TextWidth(Cadena)>Ancho )
then Ancho := ListBox_NOTAS.Canvas.TextWidth(Cadena);
ListBox_GRUPO.Items.Add( FieldByName('GRUPO').AsString );
ListBox_ORDEN.Items.Add( FieldByName('ORDEN').AsString );
ListBox_CLV_SYNOP.Items.Add( FieldByName('CLV_SYNOP').AsString );
ListBox_CLV_METAR.Items.Add( FieldByName('CLV_METAR').AsString );
ListBox_CLV_TCU.Items.Add( FieldByName('CLV_TCU').AsString );
ListBox_NOTAS.Items.Add( Cadena );
if( FieldByName('ORDEN').AsString=CLV_ORDEN )
then Activo := ListBox_ORDEN.Items.Count-1;
Next;
end;
GroupBox_TABLA.Height := (ListBox_NOTAS.Items.Count*(ListBox_NOTAS.ItemHeight+2));
Win_GetNubes.ClientWidth := Ancho + ListBox_CLV_SYNOP.Width + 32;
Win_GetNubes.Height := Panel_SUPERIOR.Height + Panel_SEPARADOR_1.Height + GroupBox_TABLA.Height + Panel_INFERIOR.Height;
Panel_BOTONES.Left := (Win_GetNubes.Width-Panel_BOTONES.Width) div 2;
{ activar las listas }
ListBox_GRUPO.ItemIndex := Activo;
ListBox_ORDEN.ItemIndex := Activo;
ListBox_CLV_SYNOP.ItemIndex := Activo;
ListBox_CLV_METAR.ItemIndex := Activo;
ListBox_CLV_TCU.ItemIndex := Activo;
ListBox_NOTAS.ItemIndex := Activo;
ListBox_CLV_SYNOP.SetFocus;
end;
end;
Win_GetNubes.Caption := '['+IntToStr( Ancho )+']';
Win_GetNubes.Activate;
end;


Todos los TListBox están sincronizados y responden al teclado, solo eso... que no se vé el texto completo :o

Haber si te vale de algo

salvica
01-05-2004, 04:11:02
Eso depende de cómo estes llenando el listbox. Si este está lleno en tiempo de diseño, o se llena antes de mostrar la forma, el evento OnShow es el adecuado.
Bueno, pues parece ser que no :cool: hay que ponerlo en el evento OnDrawItem del TListBox (o sea al "repintarlo") y sumarle 15 del borde ;)

Gracias a todos, teneis pagado un carajillo en el bar de la esquina :D
Son la 04:00 (locales) en Albacete y parece que la cosa funciona

Os pongo el código por ai a algún otro le vale :p


{$R *.xfm}
var
WIN_ANCHO : integer; // global al form, inicializar a CERO en el OnCreate

procedure TForm1.ListBox_OnDrawItem(Sender: TObject;
Index: Integer; Rect: TRect; State: TOwnerDrawState;
var Handled: Boolean);
var
newArea : TRect; // para que pinte el área completa
oldStyle : TFontStyles; // el estilo de la fuente del TListBox
begin
newArea.Left := 0;
newArea.Top := 0;
newArea.Right := Rect.Right + 1;
newArea.Bottom := Rect.Bottom + 1;
with (Sender as TListBox).Canvas do begin
oldStyle := Font.Style;
Font.Style := [fsBold];
if( TextWidth((Sender as TListBox).Items[Index])>WIN_ANCHO ) then begin
WIN_ANCHO := TextWidth((Sender as TListBox).Items[Index]);
Win_GetNubes.ClientWidth := WIN_ANCHO + 15;
end;
Font.Style := oldStyle;
if( (odSelected in State) or (odFocused in State) )
then Font.Style := [fsBold] // seleccionado o con el fofo, a negrita
else Font.Style := []; // texto normal
FillRect( newArea );
TextOut( Rect.Left, Rect.Top, (Sender as TListBox).Items[Index] );
end;
end;



Alguien puede indicarme un manual sobre el orden de los eventos en los controles?

Lo dicho, agradecido por el tiempo perdido