Ottieni la dimensione totale della TCheckbox, inclusi box e testo, in Delphi

Jan 15 2021

Voglio ottenere la dimensione totale della TCheckbox, inclusa la casella e il testo in Delphi. Controllo l'articolo su Delphi FMX TCheckbox / TRadiobutton Autosize , ma sembra che TCheckbox non abbia una proprietà Canvas quindi il codice non si adatta.

Aggiornare

Lascia che ti spieghi il motivo per cui ho bisogno di saperlo. In alcune delle mie caselle di controllo, devo inserire uno spinedit relativo alla casella di controllo. Ad esempio, nella casella di controllo "Dividi il file quando la dimensione è maggiore di" ### "Byte", dove ### è la modifica di rotazione.

Poiché la casella di controllo non supporta il ridimensionamento automatico, un modo è ingrandire la casella di controllo in modo che si adatti a tutti i testi. Quindi metti la modifica di rotazione dopo l'ultimo carattere visibile.

Questo va bene per una singola lingua, tuttavia, per supportare il multi-langauge, alcune lingue saranno molto più lunghe di altre.

In tal caso, posso scegliere:

  1. Calcola la dimensione della parte visibile checkbxo.

o

  1. Mantieni alcuni spazi tra l'ultimo carattere visibile e la modifica dello spin.

il metodo 2 non è molto buono poiché ci sarà un'enorme distanza tra la casella di controllo e la modifica dello spin per alcune lingue.

Aggiorna 2

Un altro problema, provo a fare la stessa cosa per un pulsante, come di seguito:

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;

Poiché il pulsante non ha alcuna casella, utilizzo size.cx invece di aggiungere un valore. Tuttavia, nel mio test, in realtà la larghezza del testo non è corretta, il che impedisce al pulsante di adattarsi all'intero testo, vedi sotto:

Risposte

2 AndreasRejbrand Jan 15 2021 at 21:20

Ecco i miei due centesimi.

Per ottenere la dimensione della casella di controllo effettiva, credo che dovresti chiedere all'API del 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;

Allo stesso modo, questo recupera la larghezza del testo (didascalia):

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;

Ciò che rimane sconosciuto è il riempimento tra la casella di controllo e la didascalia. Non conosco il modo giusto per ottenerlo, ma sembra che il più delle volte sia uguale alla larghezza di uno spazio:

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;