| 
			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;
			 |