Getting top-level window by widget - c++

I'm hooking the QPainter::drawText() function of a Qt5 application on Windows.
My goal is to identify the native handle of the top-level-window to which the text is painted. First, I'm getting the associated widget.
QWidget *widget = static_cast<QWidget *>(painter->device());
So it should be possible to find the corresponding top-level window/widget.
But it's harder than I thought. This is what I tried so far:
while (widget->parentWidget())
widget = widget->parentWidget();
HWND hwnd = (HWND) widget->winId();
No success. The top-parent is never the desired window.
QApplication::topLevelWidgets()
Showed me that one single window contains several top-level-widgets (including the one I'm looking for).
I also tried QApplication::topLevelAt(widget->mapToGlobal(QPoint()))
In some cases this actually works, but not reliably.
Depending on text and window position I'm getting a AccessViolationException,
so this is not an option.
By testing widget->testAttribute(Qt::WA_NativeWindow)
I found out that most of the widgets are non-native Alien Widgets.
This is how I get the (what I call) top-level window.
WinAPI.EnumChildWindows(
WinAPI.GetDesktopWindow(),
new EnumWindowsProc(this.EnumWindowsCallback), 0);
Then I check the window titles to find the handles I'm interested in.
I'm not able to find a relation from any (low-level) widget to the (top-level) widget that holds the window title.

For the QWidget that acts as a top level window, call QWidget::window().
For the nearest parent with a native handle, call QWidget::nativeParentWidget().
Calling winId() forces the widget to acquire a native window handle if it does not have one, which isn't your goal. A top level window will always have a native id, so (HWND)window()->winId() is fine. Note that this is usually the same as calling QWidget::effectiveWinId().

It's done! I found a solution for my problem.
Each windows has it's own thread.
int threadId = WinApi.GetWindowThreadProcessId(wndHandle, IntPtr.Zero)
With it I use EnumThreadWindows
to get a list of all window-handles created by this thread.
Finally I check wheather widget->effectiveWinId() is in the list.
So I can map each widget to its corresponding window!

Related

Make focused modeless dialog topmost

So I have my main dialog that calls modeless dialogs through this function (this is the legacy code on the project):
void MyClass::ShowDialog(CDialog* dialog)
{
if (!IsWindow(dialog->m_hWnd))
{
return;
}
int nCmdshow1 = dialog->IsWindowVisible() ? SW_HIDE : SW_SHOW;
dialog->ShowWindow( nCmdshow1 );
}
Problem: all sub dialogs stay on top of my main dialog.
Desired behavior: whichever's focused (they are all modeless), be it the main dialog, or sub dialogs, I want it to be the topmost dialog. Thank you!
Note: I already tried on my main dialog's OnInitDialog() these but didn't work:
1. SetWindowPos(&this->wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
2.SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
EDIT
Also, sub dialogs are created this way:
m_subDlg1->Create( SubDlg1::IDD, this );
As long as there is an owner relation between two windows. the owner of a window can never be on top of the owned window.
Windows in an owner, parent, child relation always behave the same. The owned/child window is always on top of the parent/owner.
If you want to break this, you have to break the owner/child relation. Let all dialog windows have no owner... than they may float freely.
But: I will expect the you program doesn't behave better. Even worse. User might search windows that are deep below covered under other windows. And they will never get in front, when your program gets active.
See the description about parent/child/owned windows here. Also this article might be helpful.
Edit: The problem is that internally the MFC sets the main window as an owner if no parent is given. Only the call to BOOL Wnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd, HINSTANCE hInst) allows to leave pParentWnd NULL.
So you may create the window as normal, but use SetParent(NULL) after it was created. Again the MFC ASSERTs this. SO you may use the API function and the handle of your dialog.

Native Handle of QMdiSubWindow

I'm trying to get the HWND of a QMdiSubWindow which I added to a QMdiArea.
I used the following code to get the handle:
Dialog* subWindow = new Dialog(this);
QMdiSubWindow* sw = ui->mdiArea->addSubWindow(subWindow);
(HWND) hwnd = id->winId();
To test if it worked I used the following code:
SetWindowText(hwnd, "Hello, World!");
Nothing happens. If I run the following code:
SetWindowText((HWND) this->winId(), "Hello, World!");
It works correctly for the main window. The code is placed in the constructor of the main window. The type of the subwindow class is QDialog.
Any ideas how to get it working?
You probably have à correct HWND but it may actually not be the one you are looking for (one visible window could actually be made of a few nested ones: you may believe you picked up the right one when you actually wish to pick up its child or parent).
I suggest that you use Microsoft spy tool, use the finder tool to select the mdi widget you are interested in (directly on your displayed GUI), spy tool will give you its HWND. Then you can check Qt reports you the same id.

Get window title on new window

I'm writing a keylogger type application, and I have pretty much everything done, my problem is getting the window title, I don't want to write the window title every time they press a key, I can get the window title, like I know how to, but how would I only write it to the log when its a new window?
You could maintain an internal list of all windows (with window handles as identifiers to keep memory usage low), and when a new one appears, then you can extract it.
The Win32 API (which I assume you're using) has the function:
EnumChildWindows
which can be used for this task. Call
GetDesktopWindow
to supply as the input window handle, and you'll get every window created under this desktop session.
I'm not sure if this would still work via RDP (and Windows Vista+ have the secure desktop as well as the normal clients), but it depends how vital this functionality is for you.
Store the previous window title and if the current window title is different than the previous window title, print the new window title and set the previous window title to the current window title.
This fails if there's multiple windows with the same name, but it may work for your needs.
Anytime a keypress is detected, call GetForegroundWindow to get the handle to the currently focused window. Store this value as a variable in your program and when it changes, call GetWindowText to get the title of the window and log this title.

Setting parent for a QMessageBox

i can't understand what's the benefit of setting parent for a QMessageBox, for instance in the following code:
void mainWindow::showMessage(QString msg) {
QMesageBox::information(this, "title", msg); //'this' is parent
}
can somebody help me ?
Probably a few things. First of all QMessageBox inherits from QDialog. Since QDialog has a concept of a parent, QMessageBox should too for consistency.
Specifically, the documentation says:
parent is passed to the QDialog constructor.
At the very least, a new dialog is often displayed centered in top of its parent.
However, there is more!
According to the documentation it can effect actually functionality. For example:
On Mac OS X, if you want your message box to appear as a Qt::Sheet of
its parent, set the message box's window modality to Qt::WindowModal
or use open(). Otherwise, the message box will be a standard dialog.
Also, there is a concept of both "Window Modality" and "Application Modality", where the former only prevents input in the parent window, the latter prevents input for the whole application. This obviously requires the concept of a parent to be known.
Finally, for certain static functions such as ::about(...), the first place it looks for an icon to use is parent->icon().
So, if you want to get nice platform specific behavior and have your code be cross platform, you are better off passing a sane parent to it.
The parent-child hierarchy of dialogs defines the window stacking behavior in the various platforms. If you pass dialog P as parent of dialog C, C will appear above P on all (desktop) platforms. If you pass 0, the window stacking will differ and usually not behave as wanted. The worst such issues I've seen on OS X, where some message boxes showed up behind the main window, which was disabled as the message boxes being modal, without any way to get to the message box (neither shortcuts nor moving windows via mouse helped).
In short, my suggestion: always pass a sensible parent.
The other answers are probably better, but my own little reason is that it puts the message box at the centre of the parent instead of the centre of the screen...
Don't forget to mention that QMessageBox will inherit of the palette and the style-sheets of its parent. Believe me when you use custom complex style-sheets you don't want you message to pop like they doesn't belong to your application ...
It is also useful for memory management if you don't use static functions, but actually create an instance of QMessageBox. When the parent is deleted your instance will be deleted too.

MFC: 'Gluing' two windows/dialogs together

I'm trying to set something up so my main dialog has one or more child dialogs, and these are glued/docked to the outside of the main dialog - when the main dialog is minimised, the children are too, when main dialog moves, children move with it.
I'd tried setting child dialogs as having main dialog CWnd as parent, with CHILD style. But then they get clipped by the parent's boundary. If I set them as POPUP, they can be outside but then don't move with the parent.
I'm looking at putting an OnMove handler on the parent dialog, but is there something built-in? And, should child dialogs still be children of the main dialog... I assume they should?
This is VS2005 (I think VS2008 has some related functionality so I mention this).
You need to implement the movement manually when they are popups, and yes they should be popups otherwise they will be clipped out.
I'm new to SO. Not sure if I can refer to an external article.
I guess this is what you are looking for.
I started to write this class because
I'm often in need to popup additional
dialogs around the main one. Often
these dialogs can give some trouble to
the user; for example, he must
move/close them one by one... A
solution that could give the
application a more solid aspect and
that could make the management of the
various windows easier could be, to
dock all dialogs side by side (like
Winamp does, for example).
As Roel says, your extra dialogs will need to be popups. I'm interested: what kind of UI is this? Is it WinAmp-style, where the windows snap to eachother?
Or are you doing some kind of expanding dialog? If it's an expanding dialog (with a More>> button on it, e.g.), then you can put all of the controls on the same dialog and play with the window rect when showing/hiding the extras.