23 julio 2007

Dibujar varias columnas en un ComboBox

Vamos a ver un ejemplo de dibujar tres columnas al desplegar un ComboBox. El truco está en guardar el valor de las tres columnas en el mismo item pero separado por un punto y coma.

Después implementamos nuestra propia función de dibujado de columnas para que muestre las tres columnas. Para ello metemos en el evento OnDrawItem del ComboBox:

procedure TFormulario.ComboBoxDrawItem( Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState );
var
sValor, sTodo: string;
i, iPos: Integer;
rc: TRect;
AnchoColumna: array[0..3] of Integer;
begin
ComboBox.Canvas.Brush.Style := bsSolid;
ComboBox.Canvas.FillRect( Rect );

// Las columnas deben ir separadas por un ;
sTodo := ComboBox.Items[Index];

// Establecemos el ancho de las columnas
AnchoColumna[0] := 0;
AnchoColumna[1] := 100; // Ancho de la columna 1
AnchoColumna[2] := 200; // Ancho de la columna 2
AnchoColumna[3] := 300; // Ancho de la columna 3

// Leemos el texto de la primera columna
iPos := Pos( ';', sTodo );
sValor := Copy( sTodo, 1, iPos - 1 );

for i := 0 to 3 do
begin
// Dibujamos la primera columna
rc.Left := Rect.Left + AnchoColumna[i] + 2;
rc.Right := Rect.Left + AnchoColumna[i+1] - 2;
rc.Top := Rect.Top;
rc.Bottom := Rect.Bottom;

// Escribimos el texto
Combobox.Canvas.TextRect( rc, rc.Left, rc.Top, sValor );

// Dibujamos las líneas que separan las columnas
if i < 3 then
begin
Combobox.Canvas.MoveTo( rc.Right, rc.Top );
Combobox.Canvas.LineTo( rc.Right, rc.Bottom );
end;

// Leemos el texto de la segunda columna
sTodo := Copy( sTodo, iPos + 1, Length( sTodo ) - iPos );
iPos := Pos( ';', sTodo );
sValor := Copy( sTodo, 1, iPos - 1 );
end;
end;

Modificando el bucle y el array de enteros AnchoColumna podemos crear el número de columnas que queramos. Ahora sólo hay que meter los items en el ComboBox separados por punto y coma:

with Combobox.Items do
begin
Add( 'JOSE;SANCHEZ;GARCIA;' );
Add( 'MARIA;PEREZ;GOMEZ;' );
Add( 'ANDRES;MARTINEZ;RUIZ;' );
end;

Por último hay que decirle al ComboBox que la rutina de pintar los items corre por nuestra cuenta:

procedure TFormulario.FormCreate(Sender: TObject);
begin
// Le decimos al ComboBox que lo vamos a pintar nosotros
Combobox.Style := csOwnerDrawFixed;
end;

Pruebas realizadas en Delphi 7.

Publicidad