Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I work out what values to use for TListBox.ScrollWidth?

Tags:

winapi

delphi

I'm trying to work out how to set ScrollWidth on a TListBox to control the horizontal scroll bar. Here's my first attempt:

program ListBoxSizing;

uses
  Math, Forms, StdCtrls;

var
  Form: TForm;
  ListBox: TListBox;

procedure BuildForm;
begin
  //Form.Font.Size := 9;
  Form.ClientWidth := 200;
  Form.ClientHeight := 100;
  ListBox := TListBox.Create(Form);
  ListBox.Parent := Form;
  ListBox.SetBounds(0, 0, Form.ClientWidth, Form.ClientHeight);
  ListBox.Items.Add('ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ');
end;

procedure SetScrollWidth;
var
  i, MaxWidth: Integer;
begin
  MaxWidth := -1;
  for i := 0 to ListBox.Items.Count-1 do
    MaxWidth := Max(MaxWidth, ListBox.Canvas.TextWidth(ListBox.Items[i]));
  if MaxWidth<>-1 then
    ListBox.ScrollWidth := MaxWidth;
end;

begin
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm, Form);
  BuildForm;
  SetScrollWidth;
  Application.Run;
end.

This is how the result looks with the horizontal scroll bar moved as far right as possible:

enter image description here

Notice how the last part of the final character has been chopped off.

Now, if we uncomment the line that changes the form's font size, it looks like this:

enter image description here

Now, it seems that the change to font size hasn't been accounted for in the subsequent calls to TextWidth.

So, my question is, what code do I need to use to be able to set ScrollWidth accurately, based on the current contents of the list box.

like image 813
David Heffernan Avatar asked Nov 30 '12 10:11

David Heffernan


2 Answers

procedure SetScrollWidth;
var
  I, MaxWidth: Integer;
begin
  MaxWidth := -1;
  // assign control's font to canvas
  ListBox.Canvas.Font := ListBox.Font;
  for I := 0 to ListBox.Items.Count - 1 do
    MaxWidth := Max(MaxWidth, ListBox.Canvas.TextWidth(ListBox.Items[I]));
  // consider non-client area
  if MaxWidth <> -1 then
    ListBox.ScrollWidth := MaxWidth + ListBox.Width - ListBox.ClientWidth;
end;
like image 100
Ondrej Kelle Avatar answered Nov 09 '22 05:11

Ondrej Kelle


program Project2;

uses
  Math, Forms, StdCtrls,Windows,Graphics;

var
  Form: TForm;
  ListBox: TListBox;

procedure BuildForm;
begin
  //Form.Font.Size := 9;
  Form.ClientWidth := 200;
  Form.ClientHeight := 100;
  ListBox := TListBox.Create(Form);
  ListBox.Parent := Form;
  Listbox.Font.Size := 40;
  ListBox.SetBounds(0, 0, Form.ClientWidth, Form.ClientHeight);
  ListBox.Items.Add('ABCDEFGXXXXXXXXXXXXOXOXYQASEOOWW');
  ListBox.Items.Add('ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ');
  ListBox.Items.Add('ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ111111111111111111111111111111111111111O');

end;

function GetRealFontWidth(fnt: TFont; const text:string): Integer;
var
   dc: hdc;
   tsize : Windows.TSize;
   oldObj : Cardinal;
begin
   dc := GetDC(0);
   oldObj := SelectObject(DC, fnt.Handle);
   GetTextExtentPoint32(dc, PChar(text), Length(text), tsize);
   SelectObject(DC, oldObj);
   ReleaseDC(0, DC);
   Result := tsize.cx;
end;

procedure SetScrollWidth;
var
  i, MaxWidth: Integer;
begin
  MaxWidth := -1;
  for i := 0 to ListBox.Items.Count-1 do
    MaxWidth := Max(MaxWidth, GetRealFontWidth (ListBox.Font,ListBox.Items[i]));
  if MaxWidth<>-1 then
    ListBox.ScrollWidth := MaxWidth + 4;
end;

begin
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm, Form);
  BuildForm;
  SetScrollWidth;
  Application.Run;
end.
like image 20
bummi Avatar answered Nov 09 '22 04:11

bummi