Forum > General
FormShow with QueueAsyncCall() different behaviour
Moritz:
Hello :)
I recently upgraded to Lazarus 3.4, from 2.2.6 and noticed some (maybe) weird behaviour.
I was using Application.QueueAsyncCall() to execute some code (loading data) after FormShow().
The following code is a simplification of what I want to do. The form includes some random controls.
--- 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 TMainForm.AfterShow(Ptr: IntPtr);begin Sleep(4000); // loading dataend; procedure TMainForm.FormShow(Sender: TObject);begin Application.QueueAsyncCall(@AfterShow, 0);end;
The code is compiled using the exact same settings and config (except the versions)
Lazarus 2.2.6: The form shows up with all it's controls (FormShow finishes), then it just stays busy for 4 seconds ("loading data").
Lazarus 3.4: The form shows up, but is white for 4 seconds ("loading data"), then after that it shows the content ("FormShow finishes).
In the never version it does not seem to be async at all. I was looking through the changelog of the never version, but could not find anything
specific which could be the reason for this difference. I'm also not entirely sure what is the root cause here (Forms, QueueAsyncCall, "@", ...).
To be absolutely sure, I reinstalled both Lazarus versions. I also tested version 3.0RC1, where it was the same as in 3.4.
System: Windows 10 (2004)
Thaddy:
--- 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 TMainForm.FormShow(Sender: TObject);begin Application.ProcessMessages;// to finish waiting paint updates Application.QueueAsyncCall(@AfterShow, 0);end;You can also try Tform.begin/endupdate.
Moritz:
This does not work sadly. The form still stays white for 4 seconds (during the entire "async" call) until it actually shows it's controls... :(
Unless I find out why this has changed, I have to stick to Lazarus 2.2.6 for a bit longer I guess, at least for this project...
bpranoto:
Try this
--- 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.FormShow(Sender: TObject);begin Application.QueueAsyncCall(@Self.AfterShow,0); Application.ProcessMessages;end;
BrunoK:
Possible solution demo :
--- 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";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class(TForm) Label1: TLabel; Memo1: TMemo; procedure FormShow(Sender: TObject); private FOldOnIdle: TIdleEvent; procedure AfterShow(Sender: TObject; var Done: Boolean); public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.AfterShow(Sender: TObject; var Done: Boolean);var Start: Qword;begin Application.OnIdle := FOldOnIdle; // Restore catched OnIdle. Label1.Caption:=Format('Sleep(4000)', [GetTickCount64-Start]); Application.ProcessMessages; Start:=GetTickCount64; Sleep(4000); // loading data Memo1.Lines.Add(Format('Waited %d ticks', [GetTickCount64-Start])); Memo1.ScrollBy(0, Memo1.Lines.Count); Label1.Caption:=Format('Slept(%d)', [GetTickCount64-Start]); Done := True;end; procedure TForm1.FormShow(Sender: TObject);begin FOldOnIdle := Application.OnIdle; // Save current OnIdle. Application.OnIdle:=@AfterShow;end; end.
Navigation
[0] Message Index
[#] Next page