7

Situation: A border-less QDialog stays successfully on top of other applications.

The problem is when clicking on this always-on-top application window, the following occurs:

  • The clicked always-on-top application gets activated
  • The clicked always-on-top application window steals the focus of previous active/focused app

Is there a possibility that when clicking on this always-on-top inactive and unfocused application window,

  • the current application does not loose activation and focus
  • while user being still able to interact with the always-on-top application (hitting buttons or drop-down menus, dragging the window)?

I'm working with Qt but there's no problem about using native Windows API.

I tried the following Qt windowFlag:

  • Qt::WindowDoesNotAcceptFocus but it does not work: the always-on-top application is activated, focused.
  • Qt::WindowTransparentForInput, the always-on-top application is really transparent to clicks: not activated and not focused in but buttons are unfortunately not triggered when hit.
Derek
  • 3,295
  • 3
  • 24
  • 31

2 Answers2

7

It is possible to make a window unactivable and unfocusable when clicking on it by using Windows flags (#include <qt_windows.h>). The following has to be used after the window is created and shown:

HWND winHandle = (HWND)winId();
ShowWindow(winHandle, SW_HIDE);
SetWindowLong(winHandle, GWL_EXSTYLE, GetWindowLong(winHandle, GWL_EXSTYLE)
    | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
ShowWindow(winHandle, SW_SHOW);
Derek
  • 3,295
  • 3
  • 24
  • 31
  • Hm, how do you do this in Qt anyway? Override `winEvents`? – swdev Jul 04 '14 at 09:58
  • 1
    You can override `showEvent()`. For its implementation, first call the parent method then the above code. – Derek Jul 05 '14 at 12:27
  • Not successful :) I have already success in porting the code to PyQt using PyWin libraries, overriding `showEvent()`, but when I click control on this suppose-to-be-nonactive-window, my main window become inactive. Any idea? – swdev Jul 06 '14 at 07:32
  • 1
    What about overriding `showEvent()` in the other window too? – Derek Jul 07 '14 at 08:18
  • My case is a floating QFrame containing buttons that need to be clicked. Haven't success using the above WS_EX_NOACTIVATE. Right now, I subclass pushbutton and trapping MouseButtonPress, MouseButtonRelease and MouseButtonDblClick in eventFilter. In there, I activate the main window. It's almost perfect. Sometime still a quick flashing title bar occured. But, yeah, that's the best I can do right now :) – swdev Jul 07 '14 at 22:38
  • 1
    Does the window active when you click on its background (not on one of its button). I remember that I had to override showEvent() of menu/dropdown list of the window. – Derek Jul 08 '14 at 11:25
  • My background is transparent. So, users must click the button in this case. I have also override `showEvent()` of the buttons subclass and try to set WS_EX_NOACTIVATE there. But still the focus shifted from main window – swdev Jul 08 '14 at 13:26
  • Try a new Qt simple project with one default window (no special effects, no transparent background, no buttons ...). See if it clicking the window does not activate the application, then trial/error different options (adding buttons, transparency, multiple windows ...). – Derek Jul 09 '14 at 09:06
1

I don't know about QDialog, I'm using just a QWidget for similar purpose (displaying a Windows 8 style notification).

Try setting:

dialog->setFocusPolicy(Qt::NoFocus);
dialog->setAttribute(Qt::WA_ShowWithoutActivating); 

maybe you'll have to set focus policy on all children.

headsvk
  • 2,726
  • 1
  • 19
  • 23
  • Thanks headsvk but it is overridden by the always on top flag: `dialog->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);` It seems that this flag is conflicting with the `Qt::WA_ShowWithoutActivating` attribute. – Derek Sep 09 '13 at 14:11
  • In fact it doesn't work at all on Windows (even without the WindowStaysOnTopHint), while on Mac there is the conflict. I tested with a MainWindow, then a QDialog and finally with a QWidget. – Derek Sep 09 '13 at 14:37
  • I'm also using `Qt::WindowStaysOnTopHint`. So I tried adding a button to my popup and when I click on it, it doesn't steal focus from my active window. How do the flags conflict? – headsvk Sep 09 '13 at 14:53
  • The conflict was on Mac (sorry for the confusion). But let's go back on Windows. The application still activates and get focus in. I've created a sample Qt GUI project then added the following code in MainWindow constructor: http://pastebin.com/tKB2NSHz – Derek Sep 11 '13 at 15:24
  • ok it doesn't work for me, my popup isn't stealing focus on show so I thought it also doesn't on click (I don't click on it, I close it on mouse enter), sorry – headsvk Sep 11 '13 at 16:07
  • however if the window which needs to stay activated is yours, you can use a simple workaround by activating it when the user clicks on the dialog – headsvk Sep 11 '13 at 16:09
  • Unfortunately it is not the case. Typically, my Qt app (to be left unactivated and unfocused) lies on top of PowerPoint. – Derek Sep 11 '13 at 19:48