Obtenez la taille totale de la TCheckbox, y compris la zone et le texte, dans Delphi

Jan 15 2021

Je veux obtenir la taille totale de la TCheckbox, y compris la boîte et le texte dans Delphi. Je vérifie l'article sur Delphi FMX TCheckbox / TRadiobutton Autosize , mais il semble que TCheckbox n'a pas de propriété Canvas donc le code ne lui convient pas.

Mettre à jour

Laissez-moi vous expliquer la raison pour laquelle j'ai besoin de savoir cela. Dans certaines de mes cases à cocher, je dois mettre un spinedit lié à la case à cocher. Par exemple, dans la case à cocher "Fractionner le fichier lorsque sa taille est supérieure à" ### "Octets", où ### est l'édition par rotation.

Puisque la case à cocher ne prend pas en charge la taille automatique, une façon est d'agrandir la case à cocher pour qu'elle contienne tous les textes. Ensuite, placez l'édition par rotation après le dernier caractère visible.

C'est bien pour une seule langue, cependant, pour prendre en charge plusieurs langues, certaines langues seront très plus longues que les autres.

Dans un tel cas, je peux choisir:

  1. Calculez la taille de la partie visible checkbxo.

ou alors

  1. Gardez quelques espaces entre le dernier caractère visible et l'édition par rotation.

la méthode 2 n'est pas très bonne car il y aura une distance énorme entre la case à cocher et l'édition par rotation pour certaines langues.

Mise à jour 2

Encore un problème, j'essaye de faire la même chose pour un bouton, comme ci-dessous:

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;

Comme le bouton n'a pas de boîte, j'utilise donc size.cx au lieu d'ajouter de la valeur. Cependant, dans mon test, la largeur du texte n'est pas correcte, ce qui fait que le bouton ne peut pas accueillir tout le texte, voir ci-dessous:

Réponses

2 AndreasRejbrand Jan 15 2021 at 21:20

Voici mes deux cents.

Pour obtenir la taille de la case à cocher réelle, je pense que vous devriez demander à l'API du thème Win32 ( 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;

De même, cela récupère la largeur du texte (légende):

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;

Ce qui reste inconnu, c'est le remplissage entre la case à cocher et la légende. Je ne connais pas la bonne façon d'obtenir cela, mais il semble que ce soit le plus souvent la même que la largeur d'un espace:

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;