Recent

Author Topic: How to show form w/out focusing it?  (Read 1062 times)

AlexTP

  • Hero Member
  • *****
  • Posts: 2384
    • UVviewsoft
How to show form w/out focusing it?
« on: September 04, 2022, 05:48:23 pm »
I need to do TForm.Show but w/out focusing the form (my app needs the form acting like a tooltip). How can I do it? Do i need to wait some delay (eg 100ms), and force focus on the main form?

(Form will be TopMost.)

AlexTP

  • Hero Member
  • *****
  • Posts: 2384
    • UVviewsoft
Re: How to show form w/out focusing it?
« Reply #1 on: September 04, 2022, 08:03:31 pm »
Additional question: how IDE shows its editor tooltips w/o focusing them? Is it enough that tooltip's form don't have focusable controls? So IDE tooltips are not focused.

BrunoK

  • Sr. Member
  • ****
  • Posts: 452
  • Retired programmer
Re: How to show form w/out focusing it?
« Reply #2 on: September 04, 2022, 08:18:06 pm »
Maybe something like in the attached test project ?

AlexTP

  • Hero Member
  • *****
  • Posts: 2384
    • UVviewsoft
Re: How to show form w/out focusing it?
« Reply #3 on: September 04, 2022, 08:23:19 pm »
Nope, this project shows focusable form (it gets the focus on showing), while I need to show the form w/o focusing.

zeljko

  • Hero Member
  • *****
  • Posts: 1594
    • http://wiki.lazarus.freepascal.org/User:Zeljan
Re: How to show form w/out focusing it?
« Reply #4 on: September 04, 2022, 09:19:20 pm »
Qt/Qt5 have QWidget_setAttribute(Qt_WA_ShowWithoutActivating, True);, don't know for others.

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: How to show form w/out focusing it?
« Reply #5 on: September 26, 2022, 03:52:37 pm »
Remember, which form had focus, then show your form, then show that prior form to make it have the focus back

zamtmn

  • Hero Member
  • *****
  • Posts: 594
Re: How to show form w/out focusing it?
« Reply #6 on: September 26, 2022, 04:04:27 pm »
Remember, which form had focus, then show your form, then show that prior form to make it have the focus back
It doesn't work well. Main form title has time to blink due to the loss of focus. I need such forms for toolbars and, for example, TMyComboBox implementations

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: How to show form w/out focusing it?
« Reply #7 on: September 26, 2022, 05:03:19 pm »
At least on Windows/Native there is precious little you can do

the best would be, in LCL terms,
Code: Pascal  [Select][+][-]
  1.     NewForm.PopupMode := pmAuto;
  2.     NewForm.Visible := True;
  3.     OldForm.SetFocus;
  4.  

Still flickers with caption, but not for long.

Code: Pascal  [Select][+][-]
  1.     NewForm.PopupParent := OldForm;
  2.     NewForm.WindowState := wsMinimized;
  3.     NewForm.Visible := True;
  4.     NewForm.WindowState := wsNormal;
  5.     OldForm.SetFocus;
  6.  

This makes new form smoothly slide up, and this animation steald user attentioon, so he does not see the flicker :-)

To get it flicker-less LCL (with all the toolkits) has to be refactored so that showing and activating (getting focus) would be decoupled and TWSWinControlClass(WidgetSetClass).ShowHide(Self); either would have some flags, which of the two functions to skip.
Or should only do non-activating showing and to have an extra explicit call to SetFocus requires. Which, maybe, would cause new form flickering instead.

This probably also makes docking libraries in LCL problematic...


At least on Windows/Native the process of showing goes down to

Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomForm.ShowHide(const AWinControl: TWinControl);
  2. const
  3.   WindowStateToFlags: array[TWindowState] of DWord = (
  4.  { wsNormal     } SW_SHOWNORMAL, // to restore from minimzed/maximized we need to use SW_SHOWNORMAL instead of SW_SHOW
  5.  { wsMinimized  } SW_SHOWMINIMIZED,
  6.  { wsMaximized  } SW_SHOWMAXIMIZED,
  7.  { wsFullScreen } SW_SHOWMAXIMIZED  // win32 has no fullscreen window state
  8.   );
  9. var
  10.   Flags: DWord;
  11. begin
  12.   if AWinControl.HandleObjectShouldBeVisible then
  13.   begin
  14.     Flags := WindowStateToFlags[TCustomForm(AWinControl).WindowState];
  15.     Windows.ShowWindow(AWinControl.Handle, Flags);
  16.  

it gets called from

Code: Pascal  [Select][+][-]
  1. procedure TWinControl.CMShowingChanged(var Message: TLMessage);
  2. begin
  3.   {$IFDEF VerboseShowing}
  4.   DebugLn(['TWinControl.CMShowingChanged ',DbgSName(Self),' HandleAllocated=',HandleAllocated,' ',dbgs(ComponentState)]);
  5.   {$ENDIF}
  6.   if HandleAllocated and ([csDestroying,csLoading]*ComponentState=[]) then
  7.     DoSendShowHideToInterface
  8.   else
  9.     Exclude(FWinControlFlags, wcfHandleVisible);
  10. end;
  11.  
  12. ....
  13.  
  14. procedure TWinControl.DoSendShowHideToInterface;
  15. ...
  16.     TWSWinControlClass(WidgetSetClass).ShowHide(Self);
  17.  

Microsoft: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow

Falgs you need are either SW_SHOWNOACTIVATE or SW_SHOWNA

But TWin32WSCustomForm.ShowHide - does not have any,

Despite right above there is

Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomForm.SetShowInTaskbar(const AForm: TCustomForm;
  2.   const AValue: TShowInTaskbar);
  3.  
  4. .....
  5.  
  6.   // now we need to restore window visibility with saving focus
  7.   if Visible then
  8.     if Active then
  9.       ShowWindow(AForm.Handle, SW_SHOW)
  10.     else
  11.       ShowWindow(AForm.Handle, SW_SHOWNA);
  12. end;
  13.  

you can not work-arount it bypassing LCL like

Code: Pascal  [Select][+][-]
  1.    
  2.    NeewForm.PopupMode := pmAuto;
  3.    Windows.ShowWindow( NewForm.Handle, SW_SHOWNA );
  4.  

Doing so you would get dead empty window then as LCL only puts behavior and widgets to the window during its first-time showing and activation.



On Delphi/VCL/Windows it is not possible normally too, but there is a hack (not working in LCL)

https://stackoverflow.com/questions/700698/delphi-show-window-without-activation
https://stackoverflow.com/questions/20548321/how-can-i-make-a-form-visible-and-maximize-it-to-fill-a-secondary-monitor-withou
« Last Edit: September 26, 2022, 05:21:54 pm by Arioch »

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: How to show form w/out focusing it?
« Reply #8 on: September 26, 2022, 05:28:47 pm »
On windows this works.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   Form2.Show;
  4.   Self.SetFocus;
  5. end;
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: How to show form w/out focusing it?
« Reply #9 on: September 26, 2022, 05:31:39 pm »
That's what i told above.

Remember, which form had focus, then show your form, then show that prior form to make it have the focus back

But this indeed makes Form1 flicker the captionbar. Not sure how much a problem that is. But the Delphi discusisons imply that is indeed.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: How to show form w/out focusing it?
« Reply #10 on: September 26, 2022, 05:36:08 pm »
In my small test (one form with a button and one empty form, both created via lpr) no flicker, no taskbar change, no nothing.
It does exact do what the OP was asking for, anyway, good luck.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: How to show form w/out focusing it?
« Reply #11 on: September 26, 2022, 05:47:29 pm »
In my small test (one form with a button and one empty form, both created via lpr) no flicker, no taskbar change, no nothing.
It does exact do what the OP was asking for, anyway, good luck.

Maybe you have windows animaitons turned off, or maybe something else.

I was checking on a live project (forms from DFM, created on demand, not very complex but having grid and paintbox) on Windows 7 default theme and visuals - and the flicker is noticeable.

If i turn Aero off - the animations are much shorter and the flicker gets much faster and really hard to notice. It is annoying, but you rarely sure if you saw it or not.

If i additionally go System Properties - performance - visuals and turn all the visual effects off, then without animations the flicker becomes unnoticeable indeed. It is complete before human eyes can notice it. But few run Windows with bare bones visuals today...

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: How to show form w/out focusing it?
« Reply #12 on: September 26, 2022, 05:56:33 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   s : string;
  4.   FHintRect: TRect;
  5.   FHintWin: THintWindow;
  6. begin
  7.    FHintWin := THintWindow.Create(Self);
  8.    try
  9.      s := 'This is a test!'+sLineBreak+'Line #2';
  10.      FHintRect := FHintWin.CalcHintRect(200, s, nil);
  11.      FHintWin.ActivateHint(FHintRect, s);
  12.      FHintWin.Refresh;
  13.    finally
  14.      // FHintWin.ReleaseHandle;
  15.    end;
  16. end;
Than the only thing that i do know of, is a hintwindow, it can not be focused and just display by default text.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

 

TinyPortal © 2005-2018