Author: Tomas Rutkauskas
How to create columns of equal width in a TStringGrid
Answer:
The main problem we encounter, it’s that width of any object is translated to
screen pixels, thus - integer value. While we try to divide the TStringGrid columns
to fit the grid client area, we might get a non-integer value and a fractional
remainder. Therefore, in order to compensate for the insufficient gap we got (if
the total columns width is less than the grid client area) or to compensate the
exceeding gap (if the total columns width exceed the grid client area), we need to
adjust one or more of the columns width.
1 procedure WidthEqually(AGrid: TStringGrid);
2 var
3 I, GrdWidth: Integer;
4 FinalWidth: Double;
5 GoOn: Boolean;
6 begin
7 with AGrid do
8 begin
9 {Avoiding StringGrid to be repainted }
10 Perform(WM_SETREDRAW, 0, 0);
11 if FAutoWidth then
12 FAutoWidth := False;
13 try
14 GrdWidth := Width;
15 {Taking into consideration our vertical scrollbar width, if any ...}
16 if IsScrollBar(AGrid, WS_VSCROLL) then
17 Dec(GrdWidth, GetSystemMetrics(SM_CXVSCROLL));
18 {Here we subtract additional pixels for our GridLines width}
19 FinalWidth := (GrdWidth / ColCount) - (ColCount * GridLineWidth);
20 {The first sizing session}
21 for I := 0 to ColCount - 1 do
22 begin
23 Application.ProcessMessages;
24 ColWidths[I] := Trunc(FinalWidth);
25 end;
26 {Now we need to check where we ended. Either we are right on spot,
27 meaning columns could be divided equally to fit our FinalWidth.
28 If so, we should not have any horizontal scrollbar
29 or a gap between our last columns to the grid edge.}
30 GoOn := True;
31 {If we exceeded our FinalWidth, we start reducing widths starting
32 from our last columns.}
33 if IsScrollBar(AGrid, WS_HSCROLL) then
34 begin
35 while GoOn do
36 begin
37 Application.ProcessMessages;
38 for I := ColCount - 1 downto 0 do
39 begin
40 Application.ProcessMessages;
41 ColWidths[I] := ColWidths[I] - 1;
42 {We are Ok now, time to leave...}
43 if not IsScrollBar(AGrid, WS_HSCROLL) then
44 begin
45 GoOn := False;
46 Break;
47 end;
48 end;
49 end;
50 end
51 else
52 begin
53 {If we still have a gap, we increase our ColWidths}
54 while GoOn do
55 begin
56 Application.ProcessMessages;
57 for I := ColCount - 1 downto 0 do
58 begin
59 Application.ProcessMessages;
60 ColWidths[I] := ColWidths[I] + 1;
61 {We are Ok now, time to leave...}
62 if IsScrollBar(AGrid, WS_HSCROLL) then
63 begin
64 {We resize this column back. We don't want any horizontal scrollbar.}
65 ColWidths[I] := ColWidths[I] - 1;
66 GoOn := False;
67 Break;
68 end;
69 end;
70 end;
71 end;
72 finally
73 {Unlocking our grid and repainting}
74 Perform(WM_SETREDRAW, 1, 0);
75 Repaint;
76 end;
77 end;
78 end;
79
80 function IsScrollBar(AGrid: TStringGrid; nFlag: Cardinal): Boolean;
81 begin
82 Result := (GetWindowLong(AGrid.Handle, GWL_STYLE) and nFlag) <> 0;
83 end;
|