Lazarus

Free Pascal => Beginners => Topic started by: Hi im Pascal on January 01, 2019, 02:35:30 am

Title: [Solved] Toggle Fullscreen mode
Post by: Hi im Pascal on January 01, 2019, 02:35:30 am
Hello,

I'm trying to implement fullscreen on F11. Unfortunately, after setting WindowStyle to wsFullScreen, when I read WindowStyle the next time it still contains wsNormal. After reading it a second time then it reads wsFullscreen. I tried Update and SetFocus and so on after setting wsFullScreen, it didn't help.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ToggleFullscreenActionExecute(Sender: TObject);
  2. begin
  3.   if WindowState = wsFullScreen then begin
  4.     WindowState := wsNormal;
  5.     ToggleFullscreenAction.Caption := 'Fullscreen';
  6.   end
  7.   else begin
  8.     WindowState := wsFullScreen;
  9.     ToggleFullscreenAction.Caption := 'Exit Fullscreen';
  10.   end;
  11. end;

I press F11 -> application goes fullscreen -> I press F11 second time -> application stays fullscreen -> I press F11 third time -> application goes back to normal.

Any ideas what is going wrong?
Title: Re: Toggle Fullscreen mode
Post by: lucamar on January 01, 2019, 02:52:30 am
It shouldn't be needed and I'm not sure it will help but add:
  Application.ProcessMessages;
at the end of the procedure and see if it helps. If it does, something may be wrong in the WindowsState setter.
Title: Re: Toggle Fullscreen mode
Post by: Hi im Pascal on January 01, 2019, 03:01:55 am
It shouldn't be needed and I'm not sure it will help but add:
  Application.ProcessMessages;
at the end of the procedure and see if it helps. If it does, something may be wrong in the WindowsState setter.

Hi,

didn't help. Can someone reproduce my error? Start an empty project, slap a button on the form and put this code in it:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   if WindowState = wsFullScreen then begin
  4.     BorderStyle := bsSizeable;
  5.     WindowState := wsNormal;
  6.   end
  7.   else begin
  8.     BorderStyle := bsNone;
  9.     WindowState := wsFullScreen;
  10.   end;
  11. end;

Same thing windows and Manjaro Linux (Gnome Desktop).
Title: Re: Toggle Fullscreen mode
Post by: engkin on January 01, 2019, 03:25:41 am
I see the problem here (Win32). It cycles between wsNormal, wsMaximized and wsFullScreen. I temporarily can overcome the problem with:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   if WindowState in [wsFullScreen,wsMaximized] then begin
  4.     WindowState := wsNormal;
  5.     BorderStyle := bsSizeable;
  6.   end
  7.   else begin
  8.     WindowState := wsFullScreen;
  9.     BorderStyle := bsNone;
  10.   end;
  11. end;

still I see other problems.
Title: Re: Toggle Fullscreen mode
Post by: jamie on January 01, 2019, 03:28:10 am
There is no "wsFullScreen" mode in widows, its a made up thing in Lazarus..

Even the SetWindow API in the widget diverts to a Maximize state when it detects wsFullScreen
constant.
 so if you read it, chances the state may actually be at Maximize and not FullScreen..

Maybe you want to test for both...

 If WindowsState in [wsMaximize, wsFullScreen] then.....


Damn! I got beat to it this time! LOL
Title: Re: Toggle Fullscreen mode
Post by: Hi im Pascal on January 01, 2019, 03:30:23 am
OK yeah I noticed I have to set borderStyle to bsNone as well. This version is better for windows (remembers window dimensions and position):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.     if WindowState in [wsFullScreen,wsMaximized] then begin
  4.     BorderStyle := bsSizeable;
  5.     WindowState := wsNormal;
  6.     Width := lastWidth;
  7.     Height := lastHeight;
  8.     Left := lastLeft;
  9.     Top := lastTop;
  10.   end
  11.   else begin
  12.     lastWidth := Width;
  13.     lastHeight := Height;
  14.     lastLeft := Left;
  15.     lastTop := Top;
  16.     BorderStyle := bsNone;
  17.     WindowState := wsFullScreen;
  18.   end;
  19. end;

Gonna test it on Linux again now.
Edit:
To make it work on my Manjaro + GNOME:
Code: Pascal  [Select][+][-]
  1.   if isFullscreen then begin
  2.     isFullscreen := false;
  3.     WindowState := wsNormal;
  4.     WindowState := wsFullScreen;
  5.     WindowState := wsNormal;
  6.     ToggleFullscreenAction.Caption := 'Fullscreen';
  7.   end
  8.   else begin
  9.     ToggleFullscreenAction.Caption := 'Exit Fullscreen';
  10.     WindowState := wsFullScreen;
  11.     isFullscreen := true;
  12.   end;
isFullscreen is a member variable for Form1. I can't check for wsFullScreen or wsMaximized, because it reads as wsNormal the first time around after setting it to fullScreen.

Complete Windows 10 and Manjaro Linux GNOME compatible code (I hope):
Code: Pascal  [Select][+][-]
  1.   if isFullscreen then begin
  2.     isFullscreen := false;
  3.     WindowState := wsNormal;
  4.     WindowState := wsFullScreen;
  5.     WindowState := wsNormal;
  6. {$IFDEF WINDOWS}
  7.     BorderStyle := bsSizeable;
  8. {$ENDIF}
  9.     ToggleFullscreenAction.Caption := 'Fullscreen';
  10.     Width := lastWidth;
  11.     Height := lastHeight;
  12.     Left := lastLeft;
  13.     Top := lastTop;
  14.   end
  15.   else begin
  16.     lastWidth := Width;
  17.     lastHeight := Height;
  18.     lastLeft := Left;
  19.     lastTop := Top;
  20.     ToggleFullscreenAction.Caption := 'Exit Fullscreen';
  21. {$IFDEF WINDOWS}
  22.     BorderStyle := bsNone;
  23. {$ENDIF}
  24.     WindowState := wsFullScreen;
  25.     isFullscreen := true;
  26.   end;

wsFullScreen seems to be buggy with GNOME on my Linux machine, as well as BorderStyle in Kombination with wsFullScreen.
Title: Re: Toggle Fullscreen mode
Post by: User137 on January 01, 2019, 11:00:32 am
This looks good on Windows 10:
Code: Pascal  [Select][+][-]
  1. var FullScreen: boolean;
  2.  
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. begin
  5.   if FullScreen then begin
  6.     WindowState := wsNormal;
  7.     BorderStyle := bsSizeable;
  8.   end else begin
  9.     BorderStyle := bsNone;
  10.     WindowState:=wsMaximized; // Or WindowState:=wsFullscreen;
  11.   end;
  12.   FullScreen:=not FullScreen;
  13. end;

The order of lines do matter, other way around it loses the original window size and remains maximized:
Code: Pascal  [Select][+][-]
  1.     WindowState := wsNormal;
  2.     BorderStyle := bsSizeable;
Title: Re: Toggle Fullscreen mode
Post by: Hi im Pascal on January 01, 2019, 01:06:55 pm
When I started, I was expecting something like
Code: [Select]
Form1.Fullscreen := True given my experience with Lazarus so far ^^ Maybe a worthy addition to the LCL?
Title: Re: Toggle Fullscreen mode
Post by: lucamar on January 01, 2019, 01:09:06 pm
This version is better for windows (remembers window dimensions and position):

You don't need to "remember" them yourself: TCustomForm aready keeps properties for this. Look for RestoredLeft, RestoredTop, RestoredWidth and RestoredHeight.
Title: Re: Toggle Fullscreen mode
Post by: Hi im Pascal on January 01, 2019, 05:07:20 pm
@lucamar Ah cool, that's good to know, thanks!

I did realize that indeed the window dimensions are correctly preserved if you change the order like User137 suggested. I wasn't sure how to toggle in Pascal, but your method is cleaner than writing isFullscreen in two separate places as well. So this is my current state for the record:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.ToggleFullscreen;
  2. begin
  3.   if isFullscreen then begin
  4.     // go to normal -> fullscreen -> normal/restored so it works in GNOME for me
  5.     WindowState := wsNormal;
  6.     WindowState := wsFullScreen;
  7.     WindowState := RestoredWindowState;
  8.     BorderStyle := RestoredBorderStyle;
  9.   end
  10.   else begin
  11.     RestoredBorderStyle := BorderStyle;
  12.     RestoredWindowState := WindowState;
  13.   {$IFDEF WINDOWS}
  14.     BorderStyle := bsNone;
  15.   {$ENDIF}
  16.     WindowState := wsFullScreen;
  17.   end;
  18.   isFullscreen := not isFullscreen;
  19. end;

Thanks again for your help and suggestions.

P.S.: There is another improvement: When the window is maximized, and you go into fullscreen, it is restored as wsNormal instead of being wsMaximized again. Additionally, probably it's a good idea to store the BorderStyle, too. I edited my code appropriately.

There is also this: http://wiki.freepascal.org/Application_full_screen_mode. You need 'uses LCLIntf' for ShowWindow function.

P.P.S.: After further testing, I have come to the conclusion that even using RestoredLeft and RestoredTop, the result is for me not satisfactory: If you really want to window to always end up in the position it was before, store your own Left/Top. (For example if you use poDesktopCenter etc. the window won't go back to the side, if you had it all the way on the side)
TinyPortal © 2005-2018