views:

2410

answers:

6

I struggle to show a second form above the main form without losing focus.

I have tried ShowWindow(second.handle, SW_SHOWNOACTIVATE), but the mainform loses focus. If I set Visible := false on the second window, the call to ShowWindow does not activate the second form, but the windows is empty when shown...

Does anyone have a good recipe for this?

UPDATE: What I'm trying to do, is showing a notify-window at a given event. It's crucial that the main form does not lose focus at any time.

A: 

You can show the window (non modal) and reset the focus to the mainwindow.

procedure TMainForm.ButtonClick(Sender: TObject);
begin
  OtherForm.Show;
  SetFocus;
end;

Tested on 2006.

This does not show the other form on top. But it is very counter intuitive to have a window on top that does not have the focus.

Gamecat
But this would be enough to trigger events and datastorage etc, and I don't want that...
Vegar
this doesnt work under various circumstances, for example if you are working (say editing text) in a child form of the main form and the main form needs to popup a notification. you lose any characters you are in the process of typing plus setting the focus back to the main form does not set the focus back to the original child form you were editing in. This problem haunted me for a long time until I found DR's simple (I should have thought of that) fix.
DeveloperChris
+6  A: 

There has to be something wrong with your code.

I tested this code, it works:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowWindow(Form2.Handle, SW_SHOWNOACTIVATE);
  Form2.Visible := True;
end;

Be careful to use Visible, not Show ! Otherwise it'll override the SW_SHOWNOACTIVATE.

DR
I'm sorry, but it's still activated :-(
Vegar
I modified my answer and tested it :)
DR
Wow, it's amazing :-) The tricks seems to be to let visible be false at designtime, and set it to true after the call to showwindow( ). Thanks!
Vegar
Wonderful. I tried everything to get this to work for me except the setting the Visible flag. It also helped fix the render offscreen and reposition before display problem I had. Up one from me :)
DeveloperChris
A: 

I've used this in the past

SetWindowPos(WindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);

I've not tested this with recent versions of Delphi though...

Marius
A: 

If possible, you should considered using some sort of tool tip window to display the notification information. A tool tip will not steal focus from you main window when it is displayed or when a user clicks on it. A regular form will have a border by default and if the user clicks on that border your main form will loose focus.

Here is some basic code to do this. The tip disappears when free is called; however you would be better off setting a timer than using sleep.

with THintWindow.Create(nil) do
  try
    ActivateHint(MyRect, 'My Notification');
    Sleep(DisplayTime);
  finally
    Free;
  end
Lawrence Barsanti
Maybe this is the easiest way to go, but I would have to customize the hintwindow to show more than just simple text...
Vegar
+1  A: 

Here you are:

  // you have set your 2nd form as non resizable, without border nor title etc...
  Form2.Enabled := False; // prevent the 2nd form to grab focus even when clicked
  SetWindowPos(Form2.Handle, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
  // be sure to hide it automatically when done as it is disabled...
François
A: 

I did this in the past, but I don't have the code because it was propietary in last job (sorry).

If I remember well, what I did was:

  1. From client class A call a procedure (or function) that doesn't belongs to any class (a traditional Pascal method).
  2. From that method, call some method in a class B that doesn't inherit from TForm
  3. From the method in B, create an instance of popup form P, but with no parent or owner; and call a method in the instance.
  4. From the method called in the instance, show itself.

The code (of step 3) could go something like this:

var p: TPopupForm;
begin
  p := TPopupForm.Create(nil);
  p.ShowWindow;
  p.Release;
end;

I'm sorry if this doesn't work, I don't have Delphi too.

eKek0