Author: Tomas Rutkauskas
Does anyone know how to make a cell (that has text in it) look like a button with
the text written on it?
Answer:
The following example fakes a column of buttons in column 3 of the grid. The
buttons are "clickable". Events of the grid handled are OnMouseDown, OnMOuseUp,
OnDrawCell, OnSelectCell.
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ComCtrls, StdCtrls, Grids;
8
9 type
10 TForm1 = class(TForm)
11 StatusBar: TStatusBar;
12 Button1: TButton;
13 Label1: TLabel;
14 StringGrid1: TStringGrid;
15 procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
16 State: TGridDrawState);
17 procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
18 Shift: TShiftState; X, Y: Integer);
19 procedure StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
20 Shift: TShiftState; X, Y: Integer);
21 procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var
22 CanSelect: Boolean);
23 procedure FormCreate(Sender: TObject);
24 private
25 { Private declarations }
26 FButtonDown: Boolean;
27 FDownRow: Integer;
28 public
29 { Public declarations }
30 end;
31
32 var
33 Form1: TForm1;
34
35 implementation
36
37 {$R *.DFM}
38
39 const
40 ButtonCol = 3;
41 type
42 TGridCracker = class(TStringGrid);
43 {gives access to protected methods of grid}
44
45 procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
46 Rect: TRect; State: TGridDrawState);
47 var
48 grid: TStringGrid;
49 begin
50 grid := Sender as TStringGrid;
51 if (aCol = ButtonCol) and (aRow >= grid.FixedRows) then
52 begin
53 {draw a button in Rect}
54 DrawFrameControl(grid.Canvas.handle, Rect, DFC_BUTTON, DFCS_BUTTONPUSH or
55 DFCS_ADJUSTRECT or DFCS_PUSHED * Ord(FButtonDown and (Arow = FDOwnrow)));
56 grid.Canvas.Brush.Style := bsClear;
57 grid.Canvas.Font.Color := clBlack;
58 grid.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2, grid.Cells[aCol, aRow]);
59 grid.Canvas.Brush := grid.Brush;
60 end;
61 end;
62
63 procedure TForm1.StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
64 Shift: TShiftState; X, Y: Integer);
65 var
66 r: TPoint;
67 grid: TGridCracker;
68 begin
69 if (Button = mbLeft) and ((Shift - [ssLeft]) = []) then
70 begin
71 grid := TGridCracker(Sender as TStringGrid);
72 grid.MouseToCell(X, Y, r.x, r.y);
73 if (r.x = ButtonCol) and (r.y >= grid.FixedRows) then
74 begin
75 FDownRow := r.Y;
76 FButtonDown := true;
77 grid.InvalidateCell(r.x, r.y);
78 grid.MouseCapture := true;
79 grid.Options := grid.Options - [goRangeSelect];
80 end;
81 end;
82 end;
83
84 procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
85 Shift: TShiftState; X, Y: Integer);
86 var
87 grid: TGridCracker;
88 begin
89 if FButtonDown then
90 begin
91 grid := TGridCracker(Sender as TStringGrid);
92 grid.MouseCapture := false;
93 FButtonDown := False;
94 grid.InvalidateCell(ButtonCol, FDownRow);
95 grid.Options := grid.Options + [goRangeSelect];
96 { ... might do some click action here}
97 end;
98 end;
99
100 procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
101 var CanSelect: Boolean);
102 begin
103 CanSelect := aCol <> ButtonCol;
104 end;
105
106 procedure TForm1.FormCreate(Sender: TObject);
107 var
108 i: Integer;
109 begin
110 for i := 1 to StringGrid1.rowcount - 1 do
111 StringGrid1.cells[ButtonCol, i] := format('Button %d', [i]);
112 end;
113
114 end.
|