unit utilidades;

interface

uses
  Grids, SysUtils, StdCtrls, ImgList, Controls, Classes, Windows, Graphics,
  Messages, Forms;

const
  leftDef = 0;    //Coordenadas superior e izquerda del formulario principal por defecto
  topDef = 0;
  plusLeft = 5;  //Cuanto se le suma a las coordenadas del formulario hijo
  plusTop = 5;
  plusWidth = 10;
  plusHeight = 4;

type
  TID_Icono = (btEdit,
    btClonar,
    btEliminar,
    checkBox_0,
    checkBox_1,
    radioButton_0,
    radioButton_1);
  TDAOfColores = array of TColor;

  TTipoColumna = (
    TC_Texto,
    TC_TextoEditable,
    TC_btEditar,
    TC_btEliminar,
    TC_btClonar,
    TC_checkBox,
    TC_radioButton,
    TC_Color,
    TC_Disabled,
    TC_ComboBox,
    TC_RaiseException);

var
  tiposdeColuma: array of TTipoColumna;
  mouseAbajo: boolean;
  col, fila, uACol, uAFila: integer;

//Retornan el ancho total que aumento la tabla
function AutoSizeCol(Grid: TStringGrid; Column: integer): integer;
function AutoSizeTypedCol(Grid: TStringGrid; Column: integer;
  tipo: TTipoColumna; iconos: TImageList): integer;
function AutoSizeColsToMaxCol(Grid: TStringGrid): integer;

function AutosizeTableWidth(Grid: TStringGrid): integer;
function AutoSizeTableHeight(Grid: TStringGrid): integer;

//Retornan el alto y ancho ocupados por las celdas de una tabla
function realHeight(grid: TStringGrid): integer;
function realWidth(grid: TStringGrid): integer;

//Ajusta el tamaño de la tabla al de la grilla
procedure AutoSizeTableSinBajarControles(Grid: TStringGrid;
  maxWidth: integer; maxHeigth: integer);
//Ajusta el tamaño de la tabla al de la grilla y suma su
//delta altura a todos los controles por debajo de el
//en contenedor
procedure AutoSizeTable(contenedor: TWinControl; Grid: TStringGrid;
  maxWidth: integer; maxHeigth: integer);

procedure bajarControles(contenedor: TWinControl; controlBase: TControl;
  cantPixeles: integer);
//Baja todos los controles que esten por debajo de controlBase en cantPixeles

function AutoSizeComboBox(cb: TComboBox): integer;

procedure AgregarFormatoFecha(etiqueta: TLabel);

procedure ListadoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer);
procedure ListadoDrawCell(Sender: TObject; ACol, ARow: integer;
  Rect: TRect; State: TGridDrawState; tipoColumna: TTipoColumna;
  colores: TDAOfColores; iconos: TImageList);
procedure ListadoMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: integer; tiposdeColumna: array of TTipoColumna);
function ListadoMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer;
  tiposdeColumna: array of TTipoColumna): TTipoColumna;
procedure listadoSelectCell(Sender: TObject; ACol, ARow: integer;
  var CanSelect: boolean; tiposCol: array of TTipoColumna);
function listadoDblClick(Sender: TObject;
  tiposCols: array of TTipoColumna): TTipoColumna;
procedure PopUpComboBox(Sender: TObject; cb: TComboBox);

//Retorna la extensión del archivo con el punto ej .txt
function extension_(nombreArchivo: string): string;

//Retorna el titulo del archivo
function titulo(nombreArchivo: string): string;

type
  TControlStringgrid_ = class(TStringgrid)
  private
    procedure WMCommand(var msg: TWMCommand); message WM_COMMAND;
  end;

procedure Register;

var
  formatoFecha: string;

implementation

function Point( x, y: integer ): TPoint;
var
  r: TPoint;
begin
  r.x:= x;
  r.y:= y;
  result:= r;
end;

function AutoSizeCol(Grid: TStringGrid; Column: integer): integer;
var
  i, W, WMax, sizeIni, posicion: integer;
  texto: string;
begin
  WMax := 0;
  sizeIni := Grid.Width;
  for i := 0 to (Grid.RowCount - 1) do
  begin
    posicion := pos(#13, Grid.Cells[column, i]);
    if posicion <> 0 then
    begin
      texto := Grid.Cells[column, i] + #13;
      repeat
        W := Grid.Canvas.TextWidth(copy(texto, 1, posicion - 1));
        if W > WMax then
          WMax := W;
        Delete(texto, 1, posicion);
        posicion := pos(#13, texto);
      until Posicion = 0;
    end
    else
    begin
      W := Grid.Canvas.TextWidth(Grid.Cells[Column, i]);
      if W > WMax then
        WMax := W;
    end;
  end;
  WMax := WMax + plusWidth;
  Grid.Width := Grid.Width + (WMax - Grid.ColWidths[column]);
  Grid.ColWidths[Column] := WMax;
  Result := Grid.Width - sizeIni;
end;

function AutoSizeTypedCol(Grid: TStringGrid; Column: integer;
  tipo: TTipoColumna; iconos: TImageList): integer;
var
  iniWidth: integer;
begin
  case tipo of
    TC_Texto, TC_TextoEditable, TC_ComboBox: Result := AutoSizeCol(Grid, Column);
    TC_btEditar, TC_btEliminar, TC_btClonar, TC_checkBox, TC_radioButton,
    TC_Color, TC_Disabled:
    begin
      iniWidth := Grid.Width;
      grid.Width := grid.Width + (iconos.Width - Grid.ColWidths[Column]);
      grid.ColWidths[Column] := iconos.Width;
      Result := Grid.Width - iniWidth;
    end;
    else
      Result := 0;
  end;
end;

function AutoSizeColsToMaxCol(Grid: TStringGrid): integer;
var
  i, j, W, WMax, SizeIni, posicion: integer;
  texto: string;
begin
  WMax := 0;
  SizeIni := Grid.Width;
  for j := 0 to Grid.ColCount - 1 do
  begin
    for i := 0 to (Grid.RowCount - 1) do
    begin
      posicion := pos(#13, Grid.Cells[j, i]);
      if posicion <> 0 then
      begin
        texto := Grid.Cells[j, i] + #13;
        repeat
          W := Grid.Canvas.TextWidth(copy(texto, 1, posicion - 1));
          if W > WMax then
            WMax := W;
          Delete(texto, 1, posicion);
          posicion := pos(#13, texto);
        until Posicion = 0;
      end
      else
      begin
        W := Grid.Canvas.TextWidth(Grid.Cells[j, i]);
        if W > WMax then
          WMax := W;
      end;
    end;
  end;
  WMax := WMax + plusWidth;
  for i := 0 to Grid.ColCount - 1 do
  begin
    Grid.ColWidths[i] := WMax;
  end;
  Grid.Width := Grid.ColCount * (WMax + Grid.GridLineWidth) + Grid.GridLineWidth + 2;
  Grid.DefaultColWidth := WMax;
  Result := Grid.Width - SizeIni;
end;

function AutosizeTableWidth(Grid: TStringGrid): integer;
var
  SizeIni: integer;
begin
  SizeIni := Grid.Width;
  grid.Width := realWidth(Grid);

  if (GetWindowlong(Grid.Handle, GWL_STYLE) and WS_HSCROLL) <> 0 then
    //'Horizontal scrollbar is visible!';
    grid.Width := Grid.Width + GetSystemMetrics(SM_CXVSCROLL) + 1;
  //ancho de una scroll bar vertical

  Result := Grid.Width - SizeIni;
end;

function AutoSizeTableHeight(Grid: TStringGrid): integer;
var
  SizeIni: integer;
begin
  SizeIni := Grid.Height;
  Grid.Height := realHeight(Grid);

  if (GetWindowlong(Grid.Handle, GWL_STYLE) and WS_VSCROLL) <> 0 then
    //'Vertical scrollbar is visible!';
    Grid.Height := Grid.Height + GetSystemMetrics(SM_CXHSCROLL) + 1;
  //alto de una scroll bar horizontal

  Result := Grid.Height - SizeIni;
end;

function realHeight(grid: TStringGrid): integer;
var
  res, i: integer;
begin
  res := grid.GridLineWidth * (grid.RowCount + 1) + 2;
  for i := 0 to grid.RowCount - 1 do
    Inc(res, Grid.RowHeights[i]);
  Result := res;
end;

function realWidth(grid: TStringGrid): integer;
var
  res, i: integer;
begin
  res := grid.GridLineWidth * (grid.ColCount + 1) + 2;
  for i := 0 to grid.ColCount - 1 do
    Inc(res, Grid.ColWidths[i]);
  Result := res;
end;

procedure AutoSizeTableSinBajarControles(Grid: TStringGrid;
  maxWidth: integer; maxHeigth: integer);
var
  i, Width, heigth, anchoScrollBarV, altoScrollBarH: integer;
begin
  Width := Grid.GridLineWidth + 2;
  heigth := Width;

  anchoScrollBarV := GetSystemMetrics(SM_CXVSCROLL);
  altoScrollBarH := GetSystemMetrics(SM_CXHSCROLL);

  for i := 0 to Grid.RowCount - 1 do
    if heigth < maxHeigth then
      heigth := heigth + (Grid.RowHeights[i] + Grid.GridLineWidth)
    else
    begin
      heigth := maxHeigth;
      Inc(Width, anchoScrollBarV);
      break;
    end;
  for i := 0 to Grid.ColCount - 1 do
    if Width < maxWidth then
      Inc(Width, (Grid.ColWidths[i] + Grid.GridLineWidth))
    else
    begin
      Width := maxWidth;
      Inc(heigth, altoScrollBarH);
      break;
    end;

  Grid.Height := heigth;
  Grid.Width := Width;
end;

procedure AutoSizeTable(contenedor: TWinControl; Grid: TStringGrid;
  maxWidth: integer; maxHeigth: integer);
var
  i, Width, heigth, hIni, anchoScrollBarV, altoScrollBarH: integer;
begin
  hIni := Grid.Height;

  Width := Grid.GridLineWidth + 2;
  heigth := Width;

  anchoScrollBarV := GetSystemMetrics(SM_CXVSCROLL);
  altoScrollBarH := GetSystemMetrics(SM_CXHSCROLL);

  for i := 0 to Grid.RowCount - 1 do
    if heigth < maxHeigth then
      Inc(heigth, (Grid.RowHeights[i] + Grid.GridLineWidth))
    else
    begin
      heigth := maxHeigth;
      Inc(Width, anchoScrollBarV);
      break;
    end;
  for i := 0 to Grid.ColCount - 1 do
    if Width < maxWidth then
      Inc(Width, (Grid.ColWidths[i] + Grid.GridLineWidth))
    else
    begin
      Width := maxWidth;
      Inc(heigth, altoScrollBarH);
      break;
    end;

  Grid.Height := heigth;
  Grid.Width := Width;
  bajarControles(contenedor, Grid, heigth - hIni);
end;

procedure bajarControles(contenedor: TWinControl; controlBase: TControl;
  cantPixeles: integer);
var
  i: integer;
begin
  for i := 0 to contenedor.ControlCount - 1 do
    if contenedor.Controls[i].Top > controlBase.Top then
      contenedor.Controls[i].Top := contenedor.Controls[i].Top + cantPixeles;
end;

function AutoSizeComboBox(cb: TComboBox): integer;
var
  i, MaximoAncho, iniSize: integer;
begin
  iniSize := cb.Width;
  if cb.Items.Count > 0 then
  begin
    MaximoAncho := cb.Canvas.TextWidth(cb.items[0]);
    for i := 1 to cb.Items.Count - 1 do
      if cb.Canvas.TextWidth(cb.items[i]) > MaximoAncho then
        MaximoAncho := cb.Canvas.TextWidth(cb.items[i]);
    cb.Width := MaximoAncho + plusWidth;
  end;
  Result := cb.Width - iniSize;
end;

procedure AgregarFormatoFecha(etiqueta: TLabel);
begin
  etiqueta.Caption := etiqueta.Caption + formatoFecha;
  etiqueta.Width := etiqueta.Canvas.TextWidth(etiqueta.Caption);
end;

procedure ListadoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer);
begin
  case Button of
    mbLeft:
    begin
      (Sender as TStringGrid).MouseToCell(X, Y, col, fila);
      MouseAbajo := True;
    end;
  end;
end;

procedure ListadoMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: integer; tiposdeColumna: array of TTipoColumna);
var
  aCol, aFila: integer;
  SenderAsGrid: TStringGrid;
begin
  SenderAsGrid := Sender as TStringGrid;
  SenderAsGrid.ShowHint := False;
  SenderAsGrid.MouseToCell(X, Y, aCol, aFila);

  if MouseAbajo then
  begin
    if (aCol <> Col) or (aFila <> Fila) then
    begin
      MouseAbajo := False;
      SenderAsGrid.Invalidate;
    end
    else
      exit;
  end;

  if (aFila < 1) or (aCol < 0) then
    exit;

  SenderAsGrid.ShowHint := True;
  case tiposdeColumna[aCol] of
    TC_checkBox:
    begin
      if SenderAsGrid.Cells[aCol, aFila] = '1' then
        SenderAsGrid.Hint := 'Desmarcar'
      else
        SenderAsGrid.Hint := 'Marcar';
    end;
    TC_btEditar: SenderAsGrid.Hint := 'Editar';
    TC_btEliminar: SenderAsGrid.Hint := 'Eliminar';
    TC_btClonar: SenderAsGrid.Hint := 'Clonar';
    else
      SenderAsGrid.ShowHint := False;
  end;

  if (aCol <> uACol) or (aFila <> uAFila) then
    SenderAsGrid.ShowHint := False;

  uACol := aCol;
  uAFila := aFila;
  if (aFila <> Fila) or (aCol <> Col) then
  begin
    Fila := -1;
    Col := -1;
  end;
end;

procedure ListadoDrawCell(Sender: TObject; ACol, ARow: integer;
  Rect: TRect; State: TGridDrawState; tipoColumna: TTipoColumna;
  colores: TDAOfColores; iconos: TImageList);
var
  SenderAsGrid: TStringGrid;

  procedure DibujarColor(colores: TDAOfColores);
  var
    SenderAsGrid: TDrawGrid;
  begin
    SenderAsGrid := Sender as TDrawGrid;
    if (ARow < SenderAsGrid.FixedRows) or (SenderAsGrid.FixedRows = 0) or
      (ACol < SenderAsGrid.fixedCols) then
      exit;
    SenderAsGrid.Canvas.Brush.Color := colores[ARow - 1];
    SenderAsGrid.Canvas.FillRect(Rect);
  end;

  procedure DibujarBoton(kicono: TID_ICono; apretable: boolean; iconos: TImageList);
  var
    SenderAsGrid: TDrawGrid;
  begin
    SenderAsGrid := Sender as TDrawGrid;
    if (ARow < SenderAsGrid.FixedRows) or (SenderAsGrid.FixedRows = 0) or
      (ACol < SenderAsGrid.fixedCols) then
      exit;
    with SenderAsGrid do
    begin
      Canvas.Brush.Color := clWhite;
      Canvas.FillRect(Rect);
      iconos.Draw(Canvas, Rect.Left, Rect.Top, Ord(kicono));
      if gdFocused in State then
        Canvas.DrawFocusRect(Rect);

      if apretable and MouseAbajo and ((ARow = fila) and (ACol = col)) then
      begin
        Canvas.Pen.Color := clBlack;
        Canvas.Pen.Width := 2;
        Canvas.Polyline([ Point( Rect.Left + 2, Rect.bottom - 2),
          Point(Rect.Left + 2, Rect.Top + 2), Point(Rect.Right -
          2, Rect.Top + 2)]);
      end;
    end;
  end;

  procedure dibujarDisabled(Sender: TObject; Col, Row: integer;
    Rect: TRect; State: TGridDrawState);
  begin
    with TStringGrid(Sender).Canvas do
    begin
      Brush.Color := TStringGrid(Sender).FixedColor;
      FillRect(Rect);
      Pen.Style := psSolid;
      Pen.Width := 1;
      Pen.Color := clBlack;
      Polyline([point(rect.left - 1, rect.bottom + 1),
        point(rect.TopLeft.X - 1, rect.TopLeft.Y - 1),
        point(rect.Right + 1, rect.top - 1)]);
      Pen.Color := clBtnHighlight;
      Polyline([point(rect.Left, rect.Bottom - 1), rect.TopLeft,
        point(rect.Right, rect.Top)]);
      Pen.Color := clBtnShadow;
      Polyline([point(rect.Left + 1, rect.Bottom - 1),
        point(rect.Right - 1, Rect.Bottom - 1), point(rect.Right - 1, rect.Top)]);
    end;
  end;

  procedure dibujarTexto(Sender: TObject; Col, Row: integer; Rect: TRect;
    State: TGridDrawState);

  var
    Texto: string;
    Indice: integer;
    Posicion: integer;
    grid: TStringGrid;
  begin
    grid := Sender as TStringGrid;
    if Pos(#13, grid.Cells[Col, Row]) <> 0 then
    begin
      Texto := grid.Cells[Col, Row] + #13;
      grid.Canvas.FillRect(Rect);
      Indice := 0;
      repeat
        Posicion := Pos(#13, Texto);
        with grid.Canvas do
          TextOut(Rect.left + 2,
            Rect.Top + (Indice * TextHeight(Copy(Texto, 1, Posicion - 1))) + 2,
            Copy(Texto, 1, Posicion - 1));
        Inc(Indice);
        Delete(Texto, 1, Posicion);
      until Posicion = 0;
      grid.RowHeights[Row] := (Indice - 1) * grid.Canvas.TextHeight(
        grid.Cells[Col, Row]) + utilidades.plusHeight + 1;
    end;
  end;

begin
  SenderAsGrid := Sender as TStringGrid;
  //Celdas fijas
  //  if ( ACol >=  0 ) and ( ACol < 1 )
  if ARow = 0 then
  begin
    SenderAsGrid.Canvas.Pen.Color := clBlack;
    SenderAsGrid.Canvas.Brush.Color := SenderAsGrid.FixedColor;
    SenderAsGrid.Canvas.FillRect(Rect);
    SenderAsGrid.Canvas.Pen.Style := psSolid;
    SenderAsGrid.Canvas.Pen.Width := 1;
    SenderAsGrid.Canvas.Pen.Color := clBlack;
    SenderAsGrid.Canvas.Polyline([point(rect.left - 1, rect.bottom + 1),
      point(rect.TopLeft.X - 1, rect.TopLeft.Y - 1),
      point(rect.Right + 1, rect.top - 1)]);
    SenderAsGrid.Canvas.Pen.Color := clBtnHighlight;
    SenderAsGrid.Canvas.Polyline([point(rect.Left, rect.Bottom - 1),
      rect.TopLeft, point(rect.Right, rect.Top)]);
    SenderAsGrid.Canvas.Pen.Color := clBtnShadow;
    SenderAsGrid.Canvas.Polyline([point(rect.Left + 1, rect.Bottom - 1),
      point(rect.Right - 1, Rect.Bottom - 1), point(rect.Right - 1, rect.Top)]);
    SenderAsGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2,
      SenderAsGrid.cells[ACol, Arow]);
  end
  else
  begin
    case tipoColumna of
      TC_Disabled: dibujarDisabled(Sender, ACol, ARow, Rect, State);
      TC_Texto, TC_TextoEditable: dibujarTexto(Sender, ACol, ARow, Rect, State);
      TC_btEditar: DibujarBoton(btEdit, True, iconos);
      TC_btEliminar: DibujarBoton(btEliminar, True, iconos);
      TC_btClonar: DibujarBoton(btClonar, True, iconos);
      TC_checkBox: if SenderAsGrid.cells[ACol, ARow] = '1' then
          DibujarBoton(checkBox_1, False, iconos)
        else
          DibujarBoton(checkBox_0, False, iconos);
      //      TC_ComboBox                  : nada
      TC_radioButton: if SenderAsGrid.cells[ACol, ARow] = '1' then
          DibujarBoton(radioButton_1, False, iconos)
        else
          DibujarBoton(radioButton_0, False, iconos);
      TC_Color: DibujarColor(colores);
    end; // del case
  end;
end;

function ListadoMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer;
  tiposdeColumna: array of TTipoColumna): TTipoColumna;
var
  aFila, aCol: integer;
  res: TTipoColumna;
  SenderAsGrid: TStringGrid;
begin
  res := TC_RaiseException; // agrego esto para que salte si estaba mal

  SenderAsGrid := Sender as TStringGrid;
  case Button of
    mbLeft:
    begin
      SenderAsGrid.MouseToCell(X, Y, Col, Fila);
    end;
  end;
  if not MouseAbajo then
  begin
    Result := TC_Texto;
    exit;
  end;
  MouseAbajo := False;

  SenderAsGrid.MouseToCell(X, Y, aCol, aFila);

  if (aFila <> Fila) or (aCol <> Col) then
  begin
    Result := TC_Texto;
    exit;
  end;
  if (aFila < SenderAsGrid.FixedRows) or (aFila = 0) then
  begin
    Result := TC_Disabled;
    exit;
  end;

  SenderAsGrid.MouseToCell(X, Y, aCol, aFila);
  if (aFila > SenderAsGrid.FixedRows - 1) and (aCol = Col) and (aFila = Fila) then
  begin
    SenderAsGrid.ShowHint := True;
    SenderAsGrid.Options := SenderAsGrid.Options - [goEditing];
    case tiposdeColumna[aCol] of
      TC_Texto:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_Texto;
      end;
      TC_TextoEditable:
      begin
        SenderAsGrid.ShowHint := False;
        SenderAsGrid.Options := SenderAsGrid.Options + [goEditing];
        res := TC_TextoEditable;
      end;
      TC_btEditar:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_btEditar;
      end;
      TC_btEliminar:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_btEliminar;
      end;
      TC_btClonar:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_btClonar;
      end;
      TC_checkBox:
      begin
        SenderAsGrid.ShowHint := False;
        if SenderAsGrid.cells[aCol, aFila] = '1' then
          SenderAsGrid.cells[aCol, aFila] := ''
        else
          SenderAsGrid.cells[aCol, aFila] := '1';
        res := TC_checkBox;
      end;
      TC_radioButton:
      begin
        SenderAsGrid.ShowHint := False;
        for aFila := 1 to SenderAsGrid.RowCount - 1 do
          SenderAsGrid.cells[aCol, aFila] := '';
        SenderAsGrid.cells[aCol, aFila] := '1';
        res := TC_radioButton;
      end;
      TC_Color:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_Color;
      end;
      TC_Disabled:
      begin
        res := TC_Disabled;
      end;
      TC_ComboBox:
      begin
        SenderAsGrid.ShowHint := False;
        res := TC_ComboBox;
      end;
    end; //del case
  end //del if
  else
    res := TC_Disabled;
  SenderAsGrid.Invalidate;
  if res = TC_RaiseException then
    raise Exception.Create('ListadoMouseUp, res llegó con valor no asignado');
  Result := res;
end;

function listadoDblClick(Sender: TObject;
  tiposCols: array of TTipoColumna): TTipoColumna;
begin
  if (col >= TStringGrid(Sender).FixedCols) and
    (fila >= TStringGrid(Sender).FixedRows) then
    Result := tiposCols[col]
  else
    Result := TC_Disabled;
end;

procedure listadoSelectCell(Sender: TObject; ACol, ARow: integer;
  var CanSelect: boolean; tiposCol: array of TTipoColumna);
begin
  if tiposCol[ACol] = TC_Disabled then
    CanSelect := False;
end;

procedure PopUpComboBox(Sender: TObject; cb: TComboBox);
var
  R: TRect;
  org: TPoint;
begin
  with Sender as TStringGrid do
  begin
    if (Col >= FixedCols) and (Row >= FixedRows) then
    begin
      // entered the column associated to the combobox
      // get grid out of selection mode
      Perform(WM_CANCELMODE, 0, 0);
      // position the control on top of the cell
      R := CellRect(col, row);
      //        org:= Self.ScreenToClient( ClientToScreen( R.topleft ));
      org := R.TopLeft;
      with cb do
      begin
        setbounds(org.X, org.Y, r.right - r.left, Height);
        ItemIndex := Items.IndexOf(Cells[Col, Row]);
        Show;
        BringTofront;
        // focus the combobox and drop down the list
        SetFocus;
        DroppedDown := True;
      end;
    end;
  end;
end;

function extension_(nombreArchivo: string): string;
var
  ext: string;
begin
  ext := ExtractFileExt(nombreArchivo);
  Result := ext;
end;

function titulo(nombreArchivo: string): string;
var
  i, posUltimoPunto: integer;
begin
  posUltimoPunto := Length(nombreArchivo);
  for i := Length(nombreArchivo) - 1 downto 0 do
    if nombreArchivo[i] = '.' then
    begin
      posUltimoPunto := i;
      break;
    end;
  Result := copy(nombreArchivo, 0, posUltimoPunto - 1);
end;

procedure Register;
begin
  RegisterComponents('PBGoodies', [TControlStringgrid_]);
end;

procedure TControlStringgrid_.WMCommand(var msg: TWMCommand);
begin
  if EditorMode and (msg.Ctl = InplaceEditor.Handle) then
    inherited
  else
  if msg.Ctl <> 0 then
    msg.Result :=
          SendMessage(msg.ctl, WM_COMMAND, TMessage(msg).wparam,  TMessage(msg).lparam);
//OJO, puse lo de arriba      SendMessage(msg.ctl, CN_COMMAND, TMessage(msg).wparam,  TMessage(msg).lparam);
end;

initialization
  begin
    formatoFecha := ' (' + SysUtils.ShortDateFormat + ')';
  end;

end.
