Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Buscar texto en ComboBox conociendo el comienzo (https://www.clubdelphi.com/foros/showthread.php?t=8414)

Tomás 22-03-2004 00:01:27

Buscar texto en ComboBox conociendo el comienzo
 
Hola a todos:

Tengo un ComboBox con varias líneas cuyos tres primeros caracteres son un código:
G.1 Gastos nocturnos
G.2 Gastos de juego
...
I.1 Ingresos apuestas
...
El usuario escoge y guardo sólo el código, G.3, G.7, I.2, etc.
Para modificar un registro lo leo: ComboBox1.Text := TextoRegistro, con lo que el combo solo muestra el código pero no el texto explicativo.

¿Hay alguna manera de mostrar toda la linea conociendo solo sus tres primeros caracteres?

Gracias. Tomás.

marcoszorrilla 22-03-2004 08:01:11

La cuestión no es que esté muy clara, pero se infiere por lo que dices que TextoRegistro contiene los tres caracteres y TextoRegistro2 contendría el resto?

ComboBox1.Text := TextoRegistro + TextoRegistro2


Un Saludo.

__cadetill 22-03-2004 09:44:05

A parte de lo comentado por el amigo Marcos, decirte que si quieres hacer que tu combo tengas más de una columna, en mi web tienes un ejemplo de cómo lograrlo

Espero te sirva

Tomás 22-03-2004 21:19:19

Hola:

Parece ser que no me he hecho entender bien, por lo que voy a intentarlo de nuevo:

Tabla con estos campos: CANTIDAD, CONCEPTO, PARTIDA

Añado un registro nuevo y edito en ficha con:
DBEditCantidad (pongo por j. "12,34")
DBEditConcepto (pongo por ej. "Seguro")
ComboBox con las partidas donde escojo por ej. "G.6 Responsabilidad civil"
y al aceptar guardo solo G.6 [Copy(CBPartidas.Text,1,3]

Si quiero modificar este registro presento los datos en la ficha:
En el primer DBEdit se verá "12,34" que puedo modificar
En el segundo se verá "Seguro" que puedo modificar
En el Combo quiero que se vea la línea del combo que pone "G.6 Responsabilidad civil", pero no se como lograrlo, solo consigo poner "G.6" que es el texto que tengo guardado.

Espero haberme hecho entender. Gracias.

roman 22-03-2004 21:37:34

Lo único que tienes que hacer es usar el método IndexOf de ComboBox.Items para hallar el índice de la cadena deseada ("G.6 Responsabilidad civil" por ejemplo) y asignarle el índice a la propiedad ItemIndex del combo.

Pero por otra parte no creo que sea muy conveniente este método que estás usando. Considero que lo más correcto sería crear una tabla catálogo con dos campos:

codigo y descripcion

para separar limpiamente el código ("G.6" por ejemplo) de su descripción ("Responsabilidad civil").

De esta forma, en lugar de usar un ComboBox, usarías un DbLookupComboBox apuntando sus propiedades DataSource y DataField al campo de la tabla original y sus propiedades ListSource, KeyField y ListField a la tabla catálogo.

Así el usuario seleccionará igual que con tu método con la ventaja de que automáticamente se guardará sólo el código e igualmente el despliegue de la descripción en el combo también será automática. Además, cualquier cambio en la descripción se reflejará inmediatamente sin tener que cambiar a mano las cadenas en el código.

// Saludos

marcoszorrilla 22-03-2004 21:38:20

Es que si solamente guardas 3 caracteres no vas a poder ver 6.

[Copy(CBPartidas.Text,1,x]) -> x sería el número de caracteres que deseas guardar porque si en el combo solamente hay 3 no te puede mostrar más.

Un Saludo.

roman 22-03-2004 22:06:02

Tengo que corregir lo que dije en el mensaje anterior.

El método IndexOf no va a servir ya que según entiendo ahora tú tienes que buscar toda la cadena conociendo sólo el código, es decir, tal como sucede si escribiésemos directamente en el combo usando la propiedad AutoComplete.

El ComboBox tiene un método, SelectItem, que, éste sí, me parece que es lo qe buscas. El inconveniente es que es un método protegido pero puedes usar el conocido truco de desprotección declarando un descendiente 'de palo':

Código:

type
  THackComboBox = class(TComboBox);

Posteriormente lo usas para acceder al método protegido:

Código:

THackComboBox(ComboBox1).SelectItem('G.6');
Esto colocará al combo en el primer ítem que empiece con "G.6" mostrando el texto completo.

De cualquier forma insisto en lo que te dije antes respecto de la tabla catálogo.

// Saludos

Tomás 23-03-2004 00:00:54

Hola:

He estado probando lo que me indica "roman" y funciona bien:

THackComboBox = class(TComboBox);
THackComboBox(CBPartidas).SelectItem(DM.IBDSContaPARTIDA.AsString);

Buscando yo había encontrado una solucción aunque con más lineas de código, poniendo la propiedad DroppedDown a True y luego a False:

CBPartidas.Text := DM.IBDSContaPARTIDA.AsString;
CBPartidas.DroppedDown := True;
CBPartidas.DroppedDown := False;

De todas formas voy a intentar hacerlo con DbLookupComboBox, ya que la tabla PARTIDAS con los campos CODIGO y DESCRIPCIÓN ya la tengo.

¿Por qué no lo he hecho antes? Porque no sabía de la existencia de DbLookupComboBox, ni de como se utiliza. No hay que olvidar que soy un simple novato, aficionado a Delphi, que intenta hacerse alguna aplicación simple, entreteniéndose...

Seguramente la próxima consulta tendrá que ver con DbLookupComboBox.

Muchas gracias a todos. Tomás.

marto 23-03-2004 00:34:48

Con todos los respetos, pero creo que declarar una clase que hereda de TComboBox en la unit para poder acceder al método protected Selectitem, no es, precisamente demsiado "metódico "*. Máxime, cuando emularlo desde fuera es tan sencillo como:
Código:

var
  i: Integer;
begin
  i := 0;
  while (i < Combo.Items.Count) and (Copy(Combo.Items[i], 1, 3) <> ValorABuscar) do
        Inc(i);
  if (i < Combo.Items.Count) then
        Combo.ItemIndex := i;
end;

Este código, no lo he probado porque no tengo aquí el Delphi, pero juraría que funciona "tal cual".


*Por supuesto que lo que es o no metódico es totalmente subjetivo :D :D :D

__cadetill 23-03-2004 00:38:03

sólo quería poner el método que propone Román ;)

Código:

function TCustomComboBox.SelectItem(const AnItem: String): Boolean;
var
  Idx: Integer;
  ValueChange: Boolean;
begin
  if Length(AnItem) = 0 then
  begin
    Result := False;
    ItemIndex := -1;
    Change;
    exit;
  end;
  Idx := SendMessage(Handle, CB_FINDSTRING, -1, LongInt(PChar(AnItem)));
  Result := (Idx <> CB_ERR);
  if not Result then exit;
  ValueChange := Idx <> ItemIndex;
  SendMessage(Handle, CB_SETCURSEL, Idx, 0);
  if (Style in [csDropDown, csSimple]) then
  begin
    Text := AnItem + Copy(Items[Idx], Length(AnItem) + 1, MaxInt);
    SendMessage(Handle, CB_SETEDITSEL, 0, MakeLParam(Length(AnItem), Length(Text)));
  end
  else
  begin
    ItemIndex := Idx;
    FFilter := AnItem;
  end;
  if ValueChange then
  begin
    Click;
    Select;
  end;
end;

Lo que no entiendo es por qué no hacen públicos este tipo de métodos!! :confused:

roman 23-03-2004 07:29:10

Aquí podríamos abrir un debate.

Crear un ciclo para implementar algo que ya está implementado lo veo como reinventar la rueda, máxime que ni siquiera es menester un ciclo ya que, como nos muestra cadetill, el mensaje LB_FINDSTRING, implementado en los controles estandar de Windows hace todo el trabajo. Si somos muy estrictos lo más correcto quizá sería derivar una nueva componente de TComoboBox implementando la funcionalidad deseada usando el método protegido SelectItem, pero si se trata de un sólo caso no veo ningún problema pero sí más eficiente usar el truco de la desprotección que, por otra parte, va totalmente de acuerdo a las "reglas" de herencia de Delphi.

// Saludos

marto 24-03-2004 21:47:08

Pues sí, podríamos abrir un debate :D
Primero, reconocer que fui un poco provocador en el tono para que se explicasen las ventajas del tu método.
Repecto a lo del ciclo... al final se ejecuta igual, el tema es si lo haces tú o o si lo hace el control nativo de windows. No me gusta más mi método porque sea más eficiente, sinó porque creo que la otra técnica es un abuso del lenguaje. No obstante, he de reconocer que, en momentos de apuro, he echado mano de ella en más de una ocasión.
La solución ideal seria la de crear el nuevo componente, pero quizá sea un poco desproporcionada con el problema.

roman 24-03-2004 22:05:45

Cita:

Empezado por marto
Repecto a lo del ciclo... al final se ejecuta igual, el tema es si lo haces tú o o si lo hace el control nativo de windows.

No necesariamente, muy probablemente el ciclo que utiliza internamente el control nativo de Windows está programado en C o incluso directamente en ensamblador.

Cita:

Empezado por marto
sinó porque creo que la otra técnica es un abuso del lenguaje.

Este es el punto, ¿por qué es un abuso del lenguaje? Los métodos protegidos están para ser usados por clases descendientes- como lo es THackComboBox - y el moldeo de datos a una clase descendiente es perfectamente válido.

// Saludos

marto 24-03-2004 22:09:23

Cita:

Empezado por roman
Este es el punto, ¿por qué es un abuso del lenguaje? Los métodos protegidos están para ser usados por clases descendientes- como lo es THackComboBox - y el moldeo de datos a una clase descendiente es perfectamente válido.

Claro! eso lo vería genial si creas un componente, pero no es lo mismo hacer un artificio unicamente para acceder a un método que su diseñador declaro como protected... llamame tiquis miquis, pero yo lo veo distinto.


La franja horaria es GMT +2. Ahora son las 12:31:38.

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