Recent

Author Topic: BidiMode versus Caption, Icon and SystemMenu of Form  (Read 10035 times)

LazProgger

  • Full Member
  • ***
  • Posts: 106
BidiMode versus Caption, Icon and SystemMenu of Form
« on: April 13, 2021, 09:44:28 pm »
I want to create an application that supports right to left mode (RTL) on Windows.

When setting the BidiMode of the Form...

Code: Pascal  [Select][+][-]
  1. Form1.BiDiMode := bdRightToLeft;

...the font caption appears on the right (correct) but the icon of the form as well as the system menu of the form are not switching (incorrect).

I have searched the forum and found the following code:

Code: Pascal  [Select][+][-]
  1. const
  2.   RightToLeftLayout = $400000;
  3.   NoInheritLayout = $00100000;  
  4.  
  5. procedure LTRCtrl(ACtrl: TObject);
  6. begin
  7.   if ACtrl is TWinControl then
  8.     with ACtrl as TWinControl do begin
  9.       SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE)
  10.                     and RightToLeftLayout and NoInheritLayout);
  11.   end;
  12. end;

With LTRCtrl(Form1), the icon of the form and the system menu are switching (correct) but the caption remains at the left (incorrect) - so just the other way around.

Then I tried to call both after each other but it seems as if one is revoking the other - the icon and system menu was correct with this but the caption remains left (side effect: the text of labels appeared mirrored).

Does someone know how to implement this correctly?
« Last Edit: April 13, 2021, 09:49:11 pm by LazProgger »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #1 on: July 10, 2021, 05:20:21 am »
The code you posted seems wrong to me. Try this instead:
Code: Pascal  [Select][+][-]
  1. uses
  2.  Windows...
  3.  
  4. procedure SetWinControlBiDi(Control: TWinControl; RTL:Boolean=True);
  5. const
  6.  WSEXRight=WS_EX_RTLREADING or {WS_EX_RIGHT or} WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT;
  7.  WSEXLeft=WS_EX_LEFT or WS_EX_NOINHERITLAYOUT;
  8. var
  9.  ExStyle: Longint;
  10. begin
  11.  ExStyle := GetWindowLong(Control.Handle, GWL_EXSTYLE);
  12.  if RTL then
  13.    ExStyle := ExStyle and not (WSEXLeft or WS_EX_RIGHT) or WSEXRight
  14.  else
  15.    ExStyle := ExStyle and not WSEXRight or WSEXLeft;
  16.  
  17.  SetWindowLong(Control.Handle, GWL_EXSTYLE, ExStyle);
  18.  Control.Invalidate;
  19. end;

Your problem seems to be related to WS_EX_RIGHT. When included the caption stays to the left.
When you use BidiMode:=bdRightToLeft  it gets add:
Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSWinControl.SetBiDiMode(const AWinControl : TWinControl;
  2.   UseRightToLeftAlign, UseRightToLeftReading, UseRightToLeftScrollBar : Boolean
  3.   );
  4. ...
  5.     FlagsEx := FlagsEx or WS_EX_RIGHT;
  6. ...
  7. end;

If you need to use BidiMode, call SetWinControlBiDi *after* changing BidiMode, as in:
Code: Pascal  [Select][+][-]
  1.   TForm1 = class(TForm)
  2. ...
  3.   public
  4.     RTL:Boolean;
  5.   end;
  6. ...
  7. procedure TForm1.Button1Click(Sender:TObject);
  8. begin
  9.  RTL:=not RTL;
  10.  if RTL then
  11.    BiDiMode:=bdRightToLeft
  12.  else
  13.    BiDiMode:=bdLeftToRight;
  14.  SetWinControlBiDi(Self,RTL);
  15. end;

When using the code above, you'll notice the origin is shift to top-right corner. To see what I mean, try:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormPaint(Sender:TObject);
  2. begin
  3.   Canvas.Line(0,0,100,200);
  4. end;

LazProgger

  • Full Member
  • ***
  • Posts: 106
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #2 on: July 10, 2021, 05:52:46 pm »
Thank you very much!

The good news is that with your code it was the first time I could make the form caption, the form icon and the system menu of the form behave in the right way.

However, now there are problems for example with the menu and other controls. The menu remains left for all states (when only setting BiDiMode to bdRightToLeft the menu switches its side correctly - when omitting setting the BiDiMode from your code, the main menu works but other controls are not switching any more or they are mirrored in a strange way).

Just a quick note of my first observations, I will test further.
« Last Edit: July 13, 2021, 03:43:11 pm by LazProgger »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #3 on: July 11, 2021, 06:20:02 am »
I just tried adding TMainMenu, seemed to work right if you:
keep its BidiMode as bdLeftToRight
change its ParentBidiMode to False

BUT there is a Bidi example project in Lazarus\examples\bidi\ folder. Have you tried it? It seems to work fine.

LazProgger

  • Full Member
  • ***
  • Posts: 106
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #4 on: July 13, 2021, 04:23:59 pm »
Yes, that's right for the MainMenu, but it is not only the MainMenu. Also the rest of the form behaves not in the way intended. For example, the text on Labels becomes mirrored, regardless of the BidiMode.

It would be great to have a way to only change the title bar of the form and leave the rest of the form like it is, because the rest of the form can easily be adjusted using BidiMode and the controls are caring of themselves correctly. When changing the mirroring only for fixing the title bar, it results in more problems than it solves.

Maybe this is even a thing that could be integrated into the Windows widgetset in general. At the moment, setting BidiMode of the form is changing the alignment of the form caption only (see first attachment), but the form caption should normally be at the side of the icon (see last attachment).

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #5 on: July 13, 2021, 07:12:35 pm »
Did you try the example mentioned in my previous post? It is included in your Lazarus installation.

LazProgger

  • Full Member
  • ***
  • Posts: 106
Re: BidiMode versus Caption, Icon and SystemMenu of Form
« Reply #6 on: July 13, 2021, 08:17:41 pm »
Did you try the example mentioned in my previous post? It is included in your Lazarus installation.

Yes, I have tried it. It is the same there: The icon is always left, the system menu is always right in the title bar, regardless of the BidiMode.

 

TinyPortal © 2005-2018