Question

I have a main form and a status form similar to the question asked here. However, my status window's FormStyle is fsStayOnTop, which causes some odd behavior when I try and minimize the main form when the status window is showing.

When I minimize the main form, both forms are hidden as expected, but when the status form is done completing its tasks when it is minimized, the main form automatically restores itself and its minimize button no longer works (but maximize/restore/close all still work). The only way to get the minimize function to work again is to restart the application. If I set the FormStyle to anything else, everything works fine, but my application requires the status form to stay on top when it is visible.

Is there a reason why the main form automatically restores like this? Is there a way to fix this?

procedure ButtonClick(sender:TObject);
begin
  //Gather some data

  ShowStatusWindow; // sets status window to visible, does its work, 
                    // then sets invisible. (Usually visible for about 10 seconds)

  //Gather more data

  Windows.SendMessage(self.Handle, WM_SETREDRAW, 0, 0); //Freeze the main form for 
                                                        //flickerless drawing
  // Handle everything that would cause a redraw
  Windows.SendMessage(self.Handle, WM_SETREDRAW, 1, 0);  // thaw form
  RedrawWindow(self.Handle, 0, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
end;
Was it helpful?

Solution

The only explanation I can come up with, is your application's MainFormOnTaskbar is set to false.

If this is the case, when your application is minimized, the main form is not actually minimized but hidden according to VCL's minimization mechanism. When you send a WM_SETREDRAW message with 'wParam' set to True, you're forcing the hidden (not minimized) main form's window to be shown.

At this stage the application is still minimized according to the VCL since it has never been restored. When you click the minimize button of the main form, VCL calls TApplication.Minimize and sees that the application window is already minimized and so returns without further action, hence the main form is not minimized.

Here's a simple sample that would duplicate the problem. Set MainFormOnTaskbar to false in project source. Run the application and then click the button:

procedure TForm1.Button2Click(Sender: TObject);
begin
  Application.Minimize;
  SendMessage(Handle, WM_SETREDRAW, 1, 0);
  // ShowWindow(Handle, SW_SHOWNORMAL); // this will also do the same
end;

You won't be able to minimize the form after that.


To solve, you can check if the main form is visible f.i. before disabling drawing:

  if IsWindowVisible(Handle) then begin
    Windows.SendMessage(self.Handle, WM_SETREDRAW, 0, 0);
    ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top