unit Unit1;

interface

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


type
	TID_Icono= ( btEdit, btClonar, btEliminar, checkBox_0, checkBox_1, radioButton_0, radioButton_1 );

type
	TTipoColumna= (
		TC_Texto,
		TC_TextoEditable,
		TC_btEditar,
		TC_btEliminar,
		TC_btClonar,
		TC_checkBox,
		TC_radioButton );




	TForm1 = class(TForm)
		iconos: TImageList;
		StringGrid1: TStringGrid;
		StatusBar1: TStatusBar;
    BitBtn1: TBitBtn;
	procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
			Rect: TRect; State: TGridDrawState);
		procedure StringGrid1MouseMove(Sender: TObject; Shift: TShiftState; X,
			Y: Integer);
		procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
			Shift: TShiftState; X, Y: Integer);
		procedure StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
			Shift: TShiftState; X, Y: Integer);
		procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
	private
		{ Private declarations }
		uARow, uACol: Integer;
		mdARow, mdACol: integer;
		MouseAbajo: boolean;
	public
		{ Public declarations }

		TiposDeColumna: array of TTipoColumna;

		procedure ini;
		function eliminarRecord( ARow: integer ): boolean;
	end;

var
	Form1: TForm1;

implementation

{$R *.DFM}


function TForm1.eliminarRecord( ARow: integer ): boolean;
var
	jRow, jCol: integer;
	NRows, NCols: integer;
begin
 if Application.MessageBox(
				'Está seguro que quiere borrar el registo',
				'Confirmar eliminación.',
				MB_OKCANCEL + MB_DEFBUTTON1) <> IDOK then
					showmessage( 'Eliminación cancelada.')
	else
	begin
		NRows:= stringGrid1.RowCount;
		NCols:= stringGrid1.ColCount;

		for jRow:= ARow+1 to NRows-1 do
			for jCol:= 0 to NCols-1 do
			begin
				stringGrid1.cells[jCol, jRow-1 ]:= stringGrid1.cells[jCol, jRow ];
				stringGrid1.objects[jCol, jRow-1]:= stringGrid1.objects[jCol, jRow];
			end;
		stringGrid1.RowCount:= NRows-1;
	end;
end;



procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
	Rect: TRect; State: TGridDrawState);
var
	k: integer;
	TC: TTipoColumna;

procedure DibujarBoton( kicono: TID_ICono; apretable: boolean );
begin
	with Sender as TDrawGrid 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= mdArow) and ( ACol= mdACol)) 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;



begin

// bloque muerto
	if ( ACol >= 0 ) and ( ACol < StringGrid1.FixedCols )
			and ( ARow>= 0 ) AND  ( ARow < StringGrid1.FixedRows ) then
	begin
		StringGrid1.Canvas.Pen.Color:= clWhite;
		StringGrid1.Canvas.Brush.Color:= clWhite;		
		StringGrid1.Canvas.FillRect( Rect );
		exit;
	end;

	with Sender as TStringGrid do
	begin
		if ( ARow < 1 ) or ( ACol < 0 ) then exit;
		TC:= TiposDeColumna[ ACol ];
		case TC of
			TC_Texto,	TC_TextoEditable: exit; // nada que hacer
			TC_btEditar: DibujarBoton( btEdit , true );
			TC_btEliminar: DibujarBoton( btEliminar , true );
			TC_btClonar: DibujarBoton( btClonar , true );
			TC_checkBox: if cells[ACol, ARow]='1' then
											DibujarBoton( checkBox_1 , false)
										else
											DibujarBoton( checkBox_0 , false);
			TC_radioButton: if cells[ACol, ARow]= '1' then
											DibujarBoton( radioButton_1 , false)
										else
											DibujarBoton( radioButton_0 , false);
		end; // del case
	end;

end;

procedure TForm1.StringGrid1MouseMove(Sender: TObject; Shift: TShiftState;
	X, Y: Integer);
var
	ACol, ARow: integer;
	TC: TTipoColumna;
begin
	StringGrid1.ShowHint:= false;
	StringGrid1.MouseToCell(X, Y, ACol, ARow);
	statusbar1.SimpleText:= 'ACol: '+IntToStr( ACol )+' ARow: '+IntToStr(ARow);

	if MouseAbajo then
	begin
		if (ACol<> mdACol) or ( ARow <> mdARow ) then
		begin
			MouseAbajo:= false;
			StringGrid1.Invalidate;
		end
		else
			exit;
	end;

	if ( ARow < 1 ) or ( ACol < 0 ) then exit;

	TC:= TiposDeColumna[ ACol ];
	StringGrid1.ShowHint:= true;
	case TC of
			TC_btEditar: StringGrid1.Hint:= 'Editar';
			TC_btEliminar: StringGrid1.Hint:= 'Eliminar';
			TC_btClonar: StringGrid1.Hint:= 'Clonar';
	else
		StringGrid1.ShowHint:= false;
	end; // del case

	if ( ARow <> uARow ) or ( ACol<> uACol) then
		StringGrid1.ShowHint:= false;

	uARow:= ARow;
	uACol:= ACol;
	if ( ARow <> mdARow ) or ( ACol<> mdACol) then
	begin
		mdARow:= -1;
		mdACol:= -1;
	end;
end;

procedure TForm1.ini;
var
	N, k: integer;
begin
	StringGrid1.RowCount:= 21;
	StringGrid1.ColCount:= 10;
	N:= StringGrid1.ColCount;

	SetLength(  TiposDeColumna, N );
	for k:= 0 to N - 1 do
		TiposDeColumna[k]:= TC_TextoEditable;

	TiposDeColumna[N-1]:= TC_btEliminar;
	TiposDeColumna[N-2]:= TC_btClonar;
	TiposDeColumna[N-3]:= TC_btEditar;
	TiposDeColumna[N-4]:= TC_CheckBox;
	TiposDeColumna[N-5]:= TC_RadioButton;

	for k:= 1 to 5 do
		StringGrid1.ColWidths[ N-k ]:= 25;

	for k:= 1 to 20 do
		StringGrid1.cells[0, k ]:= IntToStr( random(1000) );

end;

procedure TForm1.StringGrid1MouseDown(Sender: TObject;
	Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
	index: integer;
begin
	case Button of
	mbLeft: begin
			StringGrid1.MouseToCell(X, Y, mdACol, mdARow);
			MouseAbajo:= true;
	end;
	end;
end;

procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
	Shift: TShiftState; X, Y: Integer);
var
	index: integer;
	jRow, ACol, ARow: integer;
	TC: TTipoColumna;
begin

	case Button of
	mbLeft: begin
			StringGrid1.MouseToCell(X, Y, mdACol, mdARow);


	if not MouseAbajo then exit;
	MouseAbajo:= false;

	StringGrid1.MouseToCell(X, Y, ACol, ARow);

	if ( ARow <> mdARow ) or ( ACol <> mdACol ) then
		exit;
	if ARow < 1 then exit;

		TC:= TiposDeColumna[ ACol ];
		StringGrid1.ShowHint:= true;
		StringGrid1.Options:= StringGrid1.Options - [goEditing];



		case TC of
			TC_Texto:	StringGrid1.ShowHint:= false;
			TC_TextoEditable:
				begin
					StringGrid1.ShowHint:= false;
					StringGrid1.Options:= StringGrid1.Options + [goEditing];
				end;

			TC_btEditar: showmessage( 'Editar( '+StringGrid1.cells[0,ARow]+' )' );
			TC_btEliminar: eliminarRecord( ARow ); //showmessage('Eliminar( '+StringGrid1.cells[0,ARow]+' )' );
			TC_btClonar:showmessage('Clonar( '+StringGrid1.cells[0,ARow]+' )' );
			TC_checkBox:
				begin
					StringGrid1.ShowHint:= false;
					if StringGrid1.cells[ACol, ARow]= '1' then
						StringGrid1.cells[ACol,ARow]:= ''
					else
						StringGrid1.cells[ACol,ARow]:='1';
				end;
			TC_radioButton:
				begin
					StringGrid1.ShowHint:= false;
					for jRow:= 1 to StringGrid1.RowCount-1 do
						StringGrid1.cells[ACol, jRow]:= '' ;
					StringGrid1.cells[ACol, ARow]:= '1';
				end;
		end; // del case

	StringGrid1.Invalidate;

	end;
	end;
	
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
	MouseAbajo:= false;
	SetLength(  TiposDeColumna, StringGrid1.ColCount );
	ini;
end;


procedure TForm1.BitBtn1Click(Sender: TObject);
begin
	StringGrid1.RowCount:= StringGrid1.RowCount + 1;
end;

end.
