alancc
alancc

Reputation: 811

Get the total size of the TCheckbox, including box and text, in Delphi

I want to get the total size of the TCheckbox, including the box and the text in Delphi. I check the article at Delphi FMX TCheckbox/TRadiobutton Autosize, but it seems that TCheckbox does not have a Canvas property so the code does not fit for it.

Update

Let me explain the reason why I need to know that. In some of my checkboxes, I need to put a spinedit related to the checkbox. For example, in checkbox "Split the file when it size larger than" ### "Bytes", where ### is the spin edit.

Since checkbox does not support auto-size, one way is to enlarge the checkbox so that it accomondate all the texts. Then put the spin edit after the last visible character.

This is fine for single language, however, to support multi-langauge, some language will be very longer than the others.

In such a case, I can choose:

  1. Calculate the size of the checkbxo visible part.

or

  1. Keep some spaces between the last visible character and the spin edit.

method 2 is not very good as there will be huge distance between the checkbox and the spin edit for some languages.

Update 2

One more issue, I try to do the same thing for a button, as below:

var
  bmp: TBitmap;
  size: TSize;
  width: Integer;
begin
  Checkbox1.Caption := Edit3.Text;
  Button3.Caption := Edit3.Text;

  bmp := TBitmap.Create;
  try
    bmp.SetSize(CheckBox1.Width, CheckBox1.Height);
    bmp.Canvas.Font := CheckBox1.Font;
    size := bmp.Canvas.TextExtent(CheckBox1.Caption);
    Width := bmp.Canvas.TextWidth(Checkbox1.Caption);
    CheckBox1.Width := size.cx + 20;
    button3.Width := size.cx;
    SpinEdit1.Left := Checkbox1.Left + Checkbox1.Width + 5;
  finally
    bmp.Free;
  end;
end;

As the button does not have any box, so I use the size.cx instead of adding some value. However, in my test, actually the text width is not correct, which makes the button cannot accomondate the whole text, see below:

enter image description here

Upvotes: 0

Views: 1257

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109003

Here's my two cents.

To get the size of the actual checkbox, I believe you should ask the Win32 theme API (uses UxTheme):

var
  h: HTHEME;
  S: TSize;
begin

  h := OpenThemeData(Handle, 'BUTTON');
  try

    if Succeeded(GetThemePartSize(h, Canvas.Handle, BP_CHECKBOX,
      CBS_UNCHECKEDNORMAL, nil, TS_DRAW, S))
    then
      ShowMessage('Check box width: ' + S.cx.ToString);

  finally
    CloseThemeData(h);
  end;

Similarly, this retrieves the width of the text (caption):

var
  h: HTHEME;
  R: TRect;
begin

  h := OpenThemeData(Handle, 'BUTTON');
  try

    if Succeeded(GetThemeTextExtent(h, Canvas.Handle, BP_CHECKBOX,
      CBS_UNCHECKEDNORMAL, PChar(CheckBox1.Caption),
      Length(CheckBox1.Caption), 0, nil, R))
    then
      ShowMessage('Caption width: ' + R.Width.ToString);

  finally
    CloseThemeData(h);
  end;

What remains unknown is the padding between the check box and the caption. I don't know the right way to obtain this, but it seems like it is most often the same as the width of a space:

var
  h: HTHEME;
  S: TSize;
  R: TRect;
begin

  h := OpenThemeData(Handle, 'BUTTON');
  try

    if Succeeded(GetThemePartSize(h, Canvas.Handle, BP_CHECKBOX,
      CBS_UNCHECKEDNORMAL, nil, TS_DRAW, S))
    then
      ShowMessage('Check box width: ' + S.cx.ToString);

    if Succeeded(GetThemeTextExtent(h, Canvas.Handle, BP_CHECKBOX,
      CBS_UNCHECKEDNORMAL, PChar(#32+CheckBox1.Caption),
      1+Length(CheckBox1.Caption), 0, nil, R))
    then
      ShowMessage('Caption width including padding: ' + R.Width.ToString);

  finally
    CloseThemeData(h);
  end;

Upvotes: 5

Related Questions