Obtenha o tamanho total da TCheckbox, incluindo caixa e texto, em Delphi

Jan 15 2021

Quero obter o tamanho total da caixa de seleção TCh, incluindo a caixa e o texto em Delphi. Eu verifico o artigo em Delphi FMX TCheckbox / TRadiobutton Autosize , mas parece que TCheckbox não tem uma propriedade Canvas, então o código não se ajusta a ela.

Atualizar

Deixe-me explicar o motivo pelo qual preciso saber disso. Em algumas das minhas caixas de seleção, preciso colocar um spinedit relacionado à caixa de seleção. Por exemplo, na caixa de seleção "Dividir o arquivo quando seu tamanho for maior que" ### "Bytes", onde ### é a edição giratória.

Uma vez que a caixa de seleção não suporta o tamanho automático, uma maneira é aumentá-la para que acomode todos os textos. Em seguida, coloque a edição de rotação após o último caractere visível.

Isso é bom para um único idioma, no entanto, para oferecer suporte a vários idiomas, alguns idiomas serão muito mais longos do que outros.

Nesse caso, posso escolher:

  1. Calcule o tamanho da parte visível do checkbxo.

ou

  1. Mantenha alguns espaços entre o último caractere visível e a edição de rotação.

o método 2 não é muito bom, pois haverá uma grande distância entre a caixa de seleção e a edição giratória para alguns idiomas.

Atualização 2

Mais um problema, tento fazer o mesmo para um botão, conforme abaixo:

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;

Como o botão não tem caixa, uso o size.cx em vez de adicionar algum valor. Porém, em meu teste, na verdade a largura do texto não está correta, o que faz com que o botão não possa acomodar todo o texto, veja abaixo:

Respostas

2 AndreasRejbrand Jan 15 2021 at 21:20

Aqui estão meus dois centavos.

Para obter o tamanho da caixa de seleção real, acredito que você deve perguntar à API do tema 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;

Da mesma forma, recupera a largura do texto (legenda):

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;

O que permanece desconhecido é o preenchimento entre a caixa de seleção e a legenda. Não sei a maneira certa de obter isso, mas parece que geralmente é igual à largura de um espaço:

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;