[dopisana odpowiedź na samym dole]

Cześć. W swoim programie bazodanowym umożliwiam drukowanie różnych danych. Robię to na dobrą sprawę jedną instrukcją: CreateColumnsFromGrid(Grid: TDBGrid);

Funkcja ta otwiera nową formę, na której są wypisane kolumny z ptaszkami(pokazujemy lub nie). POnadto wypełnia mi tablicę rekordów(PrintCol) mówiących o różnych rzeczach kolumny takich jak jej szerokość, caption, fieldName i takie tam pomocnicze.

Następnie wywołuje funkcję, która ustala szerokości wszystkich kolumn w taki sposób, że szerokość kolumny to szerokość największego rekordu w danej kolumnie + 10 pikseli(największym rekordem może być nagłówek). No i o tą funkcję mi chodzi. Interesujący fragment wygląda tak:
FDS to DataSet z danymi
PixToInch to moja funkcja, która zamienia piksele na cale(potrzebne, bo wydruki robię za pomocą RaveReport :)), a wygląda tak:

function PixToInch(Pix: integer): double;
begin
  Result:=Pix / PixelsPerInch;
end;
var
  i: integer;
  cWidth, nWidth: double;
  c: TCanvas;
begin 
  c:=TCanvas.Create;
  c.Handle:=self.Canvas.Handle;
  c.Font.Name:='Arial';
  c.Font.Size:=10;

  for i:=0 to length(PrintCol)-1 do
  begin
    c.Font.Style:=[fsBold];  //bold, bo najpierw sprawdzam nagłówek
    cWidth:=PixToInch(c.TextWidth(PrintCol[i].cCaption)+10);
    c.Font.Style:=[];

    //teraz szukam najszerszej kolumny
    FDS.DisableControls;
    FDS.First;

    while not FDS.Eof do
     begin
       nWidth:=PixToInch(c.TextWidth(FDS.FieldByName(PrintCol[i].FieldName).AsString)+10);
       if nWidth>cWidth then cWidth:=nWidth;
       FDS.Next;
     end;
     FDS.EnableControls;

    PrintCol[i].cWidth:=cWidth;
    if i>0 then PrintCol[i].cLeft:=PrintCol[i-1].cLeft+PrintCol[i-1].cWidth;
  end;

  c.Free;
end;

I teraz kwestia wygląda tak, że to działa, ale połowicznie. Tzn. jeśli raz się ten kod wywołuje, to wtedy wartość nWidth jest zawsze taka sama, chociaż do funkcji PixToInch przekazywane są różne wartości. Natomiast przy kolejnych uruchomieniach tego kodu wszystko jest w porządku.
Sprawa jest tym dziwniejsza, że forma z tą funkcją jest tworzona dynamicznie i za każdym razem zwalniana.
Jeśli fromy nie zwolnie, to za kolejnym razem też jest źle.

Oczywiście mogę ww funkcję wykonać 2 razy pod rząd, ale to nie rozwiązanie, bo przy dużej ilości rekordów to będzie trwało.

[odpowiedź]
No, w końcu doszedłem i zostawiam odpowiedź dla potomności ;)

Zamiast
c.Handle:=self.Canvas.Handle;
powinno być:
c.Handle:=GetWindowDC(self.Handle);