Meine aktuelle Lösung ist die folgende, für alle die, die es interessiert.
Mein Einsatzzweck ist eine multilinguale Software, wo ich die Edits und ComboBoxen nicht am Ende eines Satzes (CheckBox) haben sollte sondern grammatikalisch korrekt mittendrin.
So war es vorher:
Delphi-Quellcode:
LabelX.Caption := 'Das hier ist ein ganz langer Satz mit gefühlt....................völlig nutzlosen Zeichen!'; // statt den Punkten natürlich Leerzeichen
Edit1.Left := 123;
So ist es jetzt:
Delphi-Quellcode:
LabelX.Caption := 'Das hier ist ein ganz langer Satz mit gefühlt ' + calcSpacesNeeded(Edit1) + ' völlig nutzlosen Zeichen!';
setControlToPosition(Edit1, LabelX);
Delphi-Quellcode:
function getTextWidth(const aString: string; aForm: TForm): Integer;
var
iRes: Integer;
// Canvas: TCanvas;
begin
iRes := 0;
if aString <> '' then
begin
// Canvas := TCanvas.Create;
// try
// Canvas.Handle := GetDC(0);
// try
// Canvas.Font := aForm.Font;
iRes := aForm.Canvas.TextWidth(aString); // nur diese Zeile wird benötigt, da aForm schon ein Canvas hat
// finally
// ReleaseDC(0, Canvas.Handle);
// end;
// finally
// Canvas.Free;
// end;
end;
Result := iRes;
end;
function calcSpacesNeeded(aControl: TControl): string;
var
i, iTmpWidth, iSpaceWidth: Integer;
sTmp: string;
begin
iSpaceWidth := getTextWidth(' ', TForm(GetParentForm(aControl)));
sTmp := '';
iTmpWidth := aControl.Width div iSpaceWidth;
for i := 0 to iTmpWidth do
begin
sTmp := sTmp + ' ';
end;
if aControl.ClassType = TEdit then
sTmp := sTmp + ' ' // 6
else if aControl.ClassType = TComboBox then
sTmp := sTmp + ' ' // 4
else
sTmp := sTmp + ' '; // 2
Result := sTmp;
end;
procedure setControlToPosition(aControlToSet, aControlSource: TControl);
var
iSpacePosition, iCaptionWidth, iTmp: Integer;
sCaption, sTmp: string;
begin
if aControlSource.ClassType = TEdit then
sCaption := (aControlSource as TEdit).Text
else if (aControlSource.ClassType = TCheckBox) or (aControlSource.ClassType = TRadioButton) then
sCaption := (aControlSource as TCheckBox).Caption
else if (aControlSource.ClassType = TLabel) then
sCaption := (aControlSource as TLabel).Caption;
iSpacePosition := PosEx(' ', sCaption, 1) + 2;
if iSpacePosition > 0 then
begin
sTmp := Copy(sCaption, 1, iSpacePosition);
iCaptionWidth := getTextWidth(sTmp, TForm(GetParentForm(aControlToSet)));
iTmp := aControlToSet.Width;
if aControlSource.ClassType = TLabel then
iTmp := aControlToSet.Width div 2;
if aControlToSet.ClassType = TEdit then
iTmp := iTmp + 2
else if aControlToSet.ClassType = TComboBox then
iTmp := iTmp - 4
else
iTmp := iTmp - 6;
aControlToSet.Left := iCaptionWidth + iTmp;
end;
end;
Das Resultat ist, dass Edit1 immer korrekt bei jeglicher DPI genau da im darunterliegenden Text-Control angezeigt wird, wo die Leerzeichen sind.