Forum > Win32/64

BidiMode versus Caption, Icon and SystemMenu of Form

(1/2) > >>

LazProgger:
I want to create an application that supports right to left mode (RTL) on Windows.

When setting the BidiMode of the Form...


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---const  RightToLeftLayout = $400000;  NoInheritLayout = $00100000;   procedure LTRCtrl(ACtrl: TObject);begin  if ACtrl is TWinControl then    with ACtrl as TWinControl do begin      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE)                     and RightToLeftLayout and NoInheritLayout);  end;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?

engkin:
The code you posted seems wrong to me. Try this instead:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---uses Windows... procedure SetWinControlBiDi(Control: TWinControl; RTL:Boolean=True);const WSEXRight=WS_EX_RTLREADING or {WS_EX_RIGHT or} WS_EX_LAYOUTRTL or WS_EX_NOINHERITLAYOUT; WSEXLeft=WS_EX_LEFT or WS_EX_NOINHERITLAYOUT;var ExStyle: Longint;begin ExStyle := GetWindowLong(Control.Handle, GWL_EXSTYLE); if RTL then   ExStyle := ExStyle and not (WSEXLeft or WS_EX_RIGHT) or WSEXRight else   ExStyle := ExStyle and not WSEXRight or WSEXLeft;  SetWindowLong(Control.Handle, GWL_EXSTYLE, ExStyle); Control.Invalidate;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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---class procedure TWin32WSWinControl.SetBiDiMode(const AWinControl : TWinControl;  UseRightToLeftAlign, UseRightToLeftReading, UseRightToLeftScrollBar : Boolean  );...    FlagsEx := FlagsEx or WS_EX_RIGHT;...end;
If you need to use BidiMode, call SetWinControlBiDi *after* changing BidiMode, as in:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  TForm1 = class(TForm)...  public    RTL:Boolean;  end;...procedure TForm1.Button1Click(Sender:TObject);begin RTL:=not RTL; if RTL then   BiDiMode:=bdRightToLeft else   BiDiMode:=bdLeftToRight; SetWinControlBiDi(Self,RTL);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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.FormPaint(Sender:TObject);begin  Canvas.Line(0,0,100,200);end;

LazProgger:
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.

engkin:
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:
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).

Navigation

[0] Message Index

[#] Next page

Go to full version