Uzyskaj całkowity rozmiar TCheckbox, w tym ramkę i tekst, w Delphi

Jan 15 2021

Chcę uzyskać całkowity rozmiar TCheckbox, w tym pudełko i tekst w Delphi. Sprawdzam artykuł w Delphi FMX TCheckbox / TRadiobutton Autosize , ale wygląda na to, że TCheckbox nie ma właściwości Canvas, więc kod do niego nie pasuje.

Aktualizacja

Pozwól, że wyjaśnię powód, dla którego muszę to wiedzieć. W niektórych moich polach wyboru muszę umieścić spinedit związany z polem wyboru. Na przykład w polu wyboru „Podziel plik, gdy jego rozmiar jest większy niż„ ### ”Bajty”, gdzie ### jest obrotową edycją.

Ponieważ pole wyboru nie obsługuje automatycznego rozmiaru, jednym ze sposobów jest powiększenie pola wyboru tak, aby mieściło się w nim wszystkie teksty. Następnie umieść edycję wirowania po ostatnim widocznym znaku.

Jest to dobre w przypadku jednego języka, jednak aby obsługiwać wiele języków, niektóre języki będą znacznie dłuższe niż inne.

W takim przypadku mam do wyboru:

  1. Oblicz rozmiar widocznej części checkbxo.

lub

  1. Zachowaj odstępy między ostatnim widocznym znakiem a edycją obrotu.

metoda 2 nie jest zbyt dobra, ponieważ w niektórych językach będzie duża odległość między polem wyboru a edycją spinową.

Zaktualizuj 2

Jeszcze jedno, próbuję zrobić to samo dla przycisku, jak poniżej:

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;

Ponieważ przycisk nie ma żadnego pola, więc używam pliku size.cx zamiast dodawać jakąś wartość. Jednak w moim teście faktycznie szerokość tekstu jest nieprawidłowa, co powoduje, że przycisk nie może pomieścić całego tekstu, patrz poniżej:

Odpowiedzi

2 AndreasRejbrand Jan 15 2021 at 21:20

Oto moje dwa centy.

Aby uzyskać rozmiar rzeczywistego pola wyboru, uważam, że powinieneś zapytać API motywu 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;

Podobnie pobiera szerokość tekstu (podpis):

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;

Nieznane pozostaje wypełnienie między polem wyboru a podpisem. Nie wiem, jak to uzyskać, ale wydaje się, że najczęściej jest to to samo, co szerokość przestrzeni:

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;