Board index » delphi » ListBox.TextWidth doesn't seem to get the right value

ListBox.TextWidth doesn't seem to get the right value

 I want to make the width of a listbox the same as that of its longest
string.  Scanning through the items, I find that the longest  is the i-th
element, then do this:

Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]);

The last few characters get clipped.  If I add some extra space so that
there'll be a margin at each side, like this:

Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]) +
                    Listbox.Canvas.TextWidth('MMMM');

things are better, but a long enough string will still get clipped.  The
font is MS San Serif (a proportional font) but that's why I'm using
TextWidth in the first place.   What's the story here?  Are there some
margins or fudge factors I'm not aware of or something?

--
Michael D. Spence
Mockingbird Data Systems, Inc.

 

Re:ListBox.TextWidth doesn't seem to get the right value


Michael -

 > Are there some
 > margins or fudge factors I'm not aware of or something?

Yes. There are things called "borders". And there's also some internal
spacing that needs to be accounted for.

Good luck.

Kurt

Re:ListBox.TextWidth doesn't seem to get the right value


Michael:

You have to make sure that the Canvas' Font is the same as the Listbox's. Then
factor in the border of the form and the size of the scrollbar plus a little
fudge. Something like the following should do it for you:

procedure TForm1.FormShow(Sender: TObject);
var
  i:         integer;
  maxWidth:  integer;
  thisWidth: integer;
begin
  maxWidth := 0;

  with ListBox1 do begin
    Canvas.Font.Assign(Font);
    for i := 0 to Items.Count - 1 do begin
      thisWidth := Canvas.TextWidth(Items[i]);
      if thisWidth > maxWidth then
        maxWidth := thisWidth;
    end;

    Width := maxWidth
             + (GetSystemMetrics(SM_CXBORDER) * 2)
             + GetSystemMetrics(SM_CXVSCROLL)
             + (Canvas.TextWidth('Mi') div 2)
             ;
  end;
end;

--
Regards
Ralph (TeamB)
Herrsching, Germany
(TeamB cannot respond to questions received via email)

Michael D. Spence < <@panix.com>> wrote in message
<6skb7l$fq...@forums.borland.com>...
| I want to make the width of a listbox the same as that of its longest
|string.  Scanning through the items, I find that the longest  is the i-th
|element, then do this:
|
|Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]);
|
|The last few characters get clipped.
<deletia>

Re:ListBox.TextWidth doesn't seem to get the right value


Quote
Ralph Friedman (TeamB) wrote:
>  You have to make sure that the Canvas' Font is the same as the Listbox's.
>     eg:  with  ListBox1 do Canvas.Font.Assign(Font);

Thanks Ralph - I struggled for hours today to get this right - gave up altogether
-
and scrolled through the newsgroup to console myself.
And there I noticed the answer.

Obviously, the Font of the ListBox and the Font of its Canvas are as similar
as Iceland and Borneo .What a fool I was to confuse the two!

Mark Horridge

Quote
>     for i := 0 to Items.Count - 1 do begin
>       thisWidth := Canvas.TextWidth(Items[i]);
>       if thisWidth > maxWidth then
>         maxWidth := thisWidth;
>     end;

>     Width := maxWidth
>              + (GetSystemMetrics(SM_CXBORDER) * 2)
>              + GetSystemMetrics(SM_CXVSCROLL)
>              + (Canvas.TextWidth('Mi') div 2)
>              ;
>   end;
> end;

> --
> Regards
> Ralph (TeamB)
> Herrsching, Germany
> (TeamB cannot respond to questions received via email)

> Michael D. Spence < <@panix.com>> wrote in message
> <6skb7l$fq...@forums.borland.com>...
> | I want to make the width of a listbox the same as that of its longest
> |string.  Scanning through the items, I find that the longest  is the i-th
> |element, then do this:
> |
> |Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]);
> |
> |The last few characters get clipped.
> <deletia>

--
Mark Horridge
Centre of Policy Studies,
Clayton Campus, Monash University,
AUSTRALIA VIC 3168
email mark.horri...@buseco.monash.edu.au

Re:ListBox.TextWidth doesn't seem to get the right value


Quote
Mark Horridge wrote in message <35EE6C6A.4B541...@buseco.monash.edu.au>...
>Ralph Friedman (TeamB) wrote:
>>  You have to make sure that the Canvas' Font is the same as the
Listbox's.
>>     eg:  with  ListBox1 do Canvas.Font.Assign(Font);

...clipped...

Quote

>Obviously, the Font of the ListBox and the Font of its Canvas are as
similar
>as Iceland and Borneo .What a fool I was to confuse the two!

I had noticed that and had made them the same to no avail.  The border stuff
is what I was really looking for.

BUT:  I wrote a program last night that let me change the font and that
displayed the results of the call to TextWidth.  A lower case "a" is always
6, regardless of Font.Size.  I'm using Delphi 2 and am beginning to think
that maybe the help file is wrong when it says that ListBox.Canvas.TextWidth
returns pixels and ListBox.Width is a pixels dimension.

Anyway, thanks everybody.

Quote

>Mark Horridge

>>     for i := 0 to Items.Count - 1 do begin
>>       thisWidth := Canvas.TextWidth(Items[i]);
>>       if thisWidth > maxWidth then
>>         maxWidth := thisWidth;
>>     end;

>>     Width := maxWidth
>>              + (GetSystemMetrics(SM_CXBORDER) * 2)
>>              + GetSystemMetrics(SM_CXVSCROLL)
>>              + (Canvas.TextWidth('Mi') div 2)
>>              ;
>>   end;
>> end;

>> --
>> Regards
>> Ralph (TeamB)
>> Herrsching, Germany
>> (TeamB cannot respond to questions received via email)

>> Michael D. Spence < <@panix.com>> wrote in message
>> <6skb7l$fq...@forums.borland.com>...
>> | I want to make the width of a listbox the same as that of its longest
>> |string.  Scanning through the items, I find that the longest  is the
i-th
>> |element, then do this:
>> |
>> |Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]);
>> |
>> |The last few characters get clipped.
>> <deletia>

>--
>Mark Horridge
>Centre of Policy Studies,
>Clayton Campus, Monash University,
>AUSTRALIA VIC 3168
>email mark.horri...@buseco.monash.edu.au

Re:ListBox.TextWidth doesn't seem to get the right value


Michael D. Spence < <@panix.com>> wrote in message
<6smb8k$ig...@forums.borland.com>...

Quote

>Mark Horridge wrote in message <35EE6C6A.4B541...@buseco.monash.edu.au>...
>>Ralph Friedman (TeamB) wrote:
>>>  You have to make sure that the Canvas' Font is the same as the
>Listbox's.
>>>     eg:  with  ListBox1 do Canvas.Font.Assign(Font);

>...clipped...

>>Obviously, the Font of the ListBox and the Font of its Canvas are as
>similar
>>as Iceland and Borneo .What a fool I was to confuse the two!

>I had noticed that and had made them the same to no avail.  The border
stuff
>is what I was really looking for.

>BUT:  I wrote a program last night that let me change the font and that
>displayed the results of the call to TextWidth.  A lower case "a" is always
>6, regardless of Font.Size.  I'm using Delphi 2 and am beginning to think
>that maybe the help file is wrong when it says that

ListBox.Canvas.TextWidth

Quote
>returns pixels and ListBox.Width is a pixels dimension.

They are both in pixels.  But Canvas.Font.Size isn't changed when Font.Size
gets changed.  You have to keep them in sync yourself.  Not sure why I
thought it'd be different...

Quote
>Anyway, thanks everybody.

And thanks again.

- Show quoted text -

Quote

>>Mark Horridge

>>>     for i := 0 to Items.Count - 1 do begin
>>>       thisWidth := Canvas.TextWidth(Items[i]);
>>>       if thisWidth > maxWidth then
>>>         maxWidth := thisWidth;
>>>     end;

>>>     Width := maxWidth
>>>              + (GetSystemMetrics(SM_CXBORDER) * 2)
>>>              + GetSystemMetrics(SM_CXVSCROLL)
>>>              + (Canvas.TextWidth('Mi') div 2)
>>>              ;
>>>   end;
>>> end;

>>> --
>>> Regards
>>> Ralph (TeamB)
>>> Herrsching, Germany
>>> (TeamB cannot respond to questions received via email)

>>> Michael D. Spence < <@panix.com>> wrote in message
>>> <6skb7l$fq...@forums.borland.com>...
>>> | I want to make the width of a listbox the same as that of its longest
>>> |string.  Scanning through the items, I find that the longest  is the
>i-th
>>> |element, then do this:
>>> |
>>> |Listbox.Width := Listbox.Canvas.TextWidth(Listbox.Items [i]);
>>> |
>>> |The last few characters get clipped.
>>> <deletia>

>>--
>>Mark Horridge
>>Centre of Policy Studies,
>>Clayton Campus, Monash University,
>>AUSTRALIA VIC 3168
>>email mark.horri...@buseco.monash.edu.au

Other Threads