Reputation: 21
To demonstrate the problem I created a simple application that consists of 4 blank forms. One of them (Form1) is the main and shows automatically. Showing other forms I put in the code project:
…
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.CreateForm(TForm3, Form3);
Application.CreateForm(TForm4, Form4);
Form2.Show;
Form3.Show;
Form4.Show;
Application.Run;
end.
On the second form (or any other) Form2 I put a button that, when clicked, synchronously executes long (>5 seconds) SQL query (any, I open the stored procedure). Is it synchronous, that is, the app hangs for at least 10 seconds. At this time triggers the windows ghosting. Windows creates Windows Ghost for all Windows stale apps that you can minimize, move and close. After executing a query, the application resumes processing messages and everything returns to its original state.
It must be so, but for me it is not. In fact, after defrosting program Z-order of the Windows is changed, the order of the Windows mixed. Moreover, the top (or bottom) can get out of any window, I have not noticed any pattern. It seems that Windows does not correctly restore the Z-order when cancelling the ghosting.
This behavior is also found in Delphi 2007. Note that under the Delphi debugger mode ghosting is disabled and you will not see this behavior. Run the application without debugger to see this behaviour. After disabling mode ghosting with DisableProcessWindowsGhosting - everything works correctly.
But I don't want to completely disable this mode, the program often hangs for more than 5 seconds, and this mode is useful: the user is still nicer to look at Windows that somehow redrawn than not redrawn at all. To rewrite half the program code for asynchronous execution of queries is very long and time-consuming task, I'm afraid we don't have enough resources, although it is undoubtedly the right approach.
MainFormOnTaskBar property has nothing to do with my question, there is no such property in delphi 7.
Does this effect anyone else besides me? If not – where did I go wrong? How to force Windows to properly reconstruct the sequence of Windows?
Upvotes: 1
Views: 1191
Reputation: 1216
Disable the windows ghosting "feature" completely and it will fix the z-order issue (and other annoyances of this feature).
The Windows API function to call is named DisableProcessWindowsGhosting, in user32.dll: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-disableprocesswindowsghosting
Allen Bauer, former Delphi architect, described why this z-order issue happens. The page is not available anymore, but WayBackMachine comes to the rescue:
This function is not imported in Winapi.Windows.pas (at least not up to Delphi 10.2), so you need to do it yourself. Declare a procedure that imports user32.dll's DisableProcessWindowsGhosting function dynamically and call it before your application starts, like this:
procedure DisableProcessWindowsGhosting;
var
DisableProcessWindowsGhostingProc: procedure;
begin
DisableProcessWindowsGhostingProc := GetProcAddress(GetModuleHandle('user32.dll'), 'DisableProcessWindowsGhosting');
if Assigned(DisableProcessWindowsGhostingProc) then
DisableProcessWindowsGhostingProc;
end;
begin
// Disable windows ghosting feature (XP and newer)
DisableProcessWindowsGhosting;
Application.Initialize;
...
end.
Upvotes: 1
Reputation: 613163
There is exactly one way to avoid your application becoming unresponsive. Don't block the main thread.
You are asking how to block the main thread, and keep the application responsive. The only way for an application to remain responsive is for it to process its message queue in a timely fashion. You simply cannot have it both ways. You can't both process messages and not process messages.
Probably the z-order gets changed because your application is not able to process the various clicks you make while the application is not processing messages. And then processes them when the application starts processing messages again.
Conclusion: if you want your application to remain responsive, arrange for the long running tasks to run asynchronously with respect to the main thread.
Upvotes: 1