Search code examples
delphiribbonvcldelphi-10-seattle

Why does BringWindowToTop combined with the VCL Ribbon not work correctly?


I have the following (simplified) procedure to bring a desired window atop all other normal windows:

function focusWindow(): boolean;
var
  h: Hwnd;
begin
  result := true;
  h := findwindow('Notepad', 'Unbenannt - Editor');
  if h <> 0 then
    BringWindowToTop(h);
end;

I use this in the following example application:

starting situation

On the top, you can see my example application. There is an explorer window behind and an empty notepad in the background. As seen in the code above, I would like to move the notepad window to the front.

If I call my function from the button event handler

procedure TForm4.btnFocusClick(Sender: TObject);
begin
  focusWindow();
end;

everything works as expected. The empty notepad window moves up to the front, behind that is the example application and the explorer is behind the other two windows.

But if I use a vcl ribbon control with an action assigned to a command button, it works only partly.

procedure TForm4.actDemoExecute(Sender: TObject);
begin
  focusWindow();
end;

The notepad window moves up leaving the explorer window in the back. But then the procedure stops -- the notepad window keeps hidden behind my own application. What is happening here?

final situation


Solution

  • I've had contexts where the call to bring something to the top fires and then something (perhaps the mouseUp on certain controls, but I'm not sure) refocuses the control with the button and puts in front. In these cases where I need a quick workaround, adding a timer that fires in 10 or 20 ms with the bringToFront call seems to work. The button starts the timer, finishes it's own processing, and then the timer executes bringToFront and turns itself off; this makes the BringToFront happen after the interaction with the button. I don't find this very elegant, but it has worked for me more than once.