BidiUtils.pas 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. unit BidiUtils;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2024 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Bidi utility functions
  8. }
  9. interface
  10. uses
  11. Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
  12. procedure FlipControls(const AParentCtl: TWinControl);
  13. procedure FlipRect(var Rect: TRect; const ParentRect: TRect; const UseRightToLeft: Boolean);
  14. function IsParentFlipped(const AControl: TControl): Boolean;
  15. function IsParentRightToLeft(const AControl: TControl): Boolean;
  16. function SetBiDiStyles(const AControl: TControl; var AParams: TCreateParams): Boolean;
  17. var
  18. { These two callbacks should be set by the caller. Inno Setup: set by the Setup.SetupForm unit: }
  19. IsParentFlippedFunc: function(AControl: TControl): Boolean;
  20. IsParentRightToLeftFunc: function(AControl: TControl): Boolean;
  21. implementation
  22. procedure FlipRect(var Rect: TRect; const ParentRect: TRect; const UseRightToLeft: Boolean);
  23. var
  24. W: Integer;
  25. begin
  26. if UseRightToLeft then begin
  27. W := Rect.Right - Rect.Left;
  28. Rect.Left := ParentRect.Right - (Rect.Left - ParentRect.Left) - W;
  29. Rect.Right := Rect.Left + W;
  30. end;
  31. end;
  32. function IsParentFlipped(const AControl: TControl): Boolean;
  33. begin
  34. if Assigned(IsParentFlippedFunc) then
  35. Result := IsParentFlippedFunc(AControl)
  36. else
  37. Result := False;
  38. end;
  39. function IsParentRightToLeft(const AControl: TControl): Boolean;
  40. begin
  41. if Assigned(IsParentRightToLeftFunc) then
  42. Result := IsParentRightToLeftFunc(AControl)
  43. else
  44. Result := False;
  45. end;
  46. function SetBiDiStyles(const AControl: TControl; var AParams: TCreateParams): Boolean;
  47. begin
  48. Result := IsParentRightToLeft(AControl);
  49. if Result then
  50. AParams.ExStyle := AParams.ExStyle or (WS_EX_RTLREADING or WS_EX_LEFTSCROLLBAR or WS_EX_RIGHT);
  51. end;
  52. type
  53. TControlAccess = class(TControl);
  54. procedure FlipControls(const AParentCtl: TWinControl);
  55. var
  56. ParentWidth, I: Integer;
  57. Ctl: TControl;
  58. begin
  59. if AParentCtl.ControlCount = 0 then
  60. Exit;
  61. AParentCtl.DisableAlign;
  62. try
  63. ParentWidth := AParentCtl.ClientWidth;
  64. for I := 0 to AParentCtl.ControlCount-1 do begin
  65. Ctl := AParentCtl.Controls[I];
  66. if (akLeft in Ctl.Anchors) and not (akRight in Ctl.Anchors) then
  67. Ctl.Anchors := Ctl.Anchors - [akLeft] + [akRight]
  68. else if not (akLeft in Ctl.Anchors) and (akRight in Ctl.Anchors) then begin
  69. { Before we can set Anchors to [akLeft, akTop] (which has a special
  70. 'no anchors' meaning to VCL), we first need to update the Explicit*
  71. properties so the control doesn't get moved back to an old position. }
  72. if Ctl.Anchors = [akTop, akRight] then
  73. TControlAccess(Ctl).UpdateExplicitBounds;
  74. Ctl.Anchors := Ctl.Anchors - [akRight] + [akLeft];
  75. end;
  76. Ctl.Left := ParentWidth - Ctl.Width - Ctl.Left;
  77. end;
  78. finally
  79. AParentCtl.EnableAlign;
  80. end;
  81. for I := 0 to AParentCtl.ControlCount-1 do
  82. if AParentCtl.Controls[I] is TWinControl then
  83. FlipControls(TWinControl(AParentCtl.Controls[I]));
  84. end;
  85. end.