How to make a window appear on top of everything (even full screen games!) c++/Qt
Asked Answered
N

2

9

I'm trying to make an application displaying a crosshair at the center of the screen and staying on top of everything else. The aim is to have a crosshair in some FPS games that doesn't provide one. I've succesfully made my window topmost for everything except the games :/

Here is my code : (everything is in the main since im only testing the core functionalitys of my app, I've commented it extensively to try and make my problem more accessible)

QApplication app(argc, argv);

DWORD error;
QWidget window;
QLabel *label = new QLabel(&window);
label->setText("<strong>O<strong>");//I'm using an "O" as a crosshair until I can figure out how to display image transparency.
window.setGeometry(960-label->width()/2,540-label->height()/2,label->width(),label->height());//here I'm making my window appear in the center of my screen
window.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);// here making the window frameless and topMost via qt
window.setAttribute(Qt::WA_TranslucentBackground);//making the window see through
window.setWindowTitle("Crosshair");
window.show();

//in this next part I tried using windows api to make my window appear on top of the game.
HWND handle, myHandle;
myHandle = FindWindow(NULL,TEXT("Crosshair"));//retieving my own application window handle
if(myHandle == 0){cout << "no own handle" << endl;}//it successfully retrieves it

handle = FindWindow(NULL,TEXT("Killing Floor"));//retrieving a game window handle
if(handle == 0){cout << "no KF handle" << endl;}//it successfully retrieves it

if(handle != 0 && myHandle != 0)
{
    if(SetWindowPos(handle,myHandle,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE) == 0){cout << "couldnt set notopmost" << endl;}//here SetWindowPos returns 0 (function failed)
}
          // I've also tried using SetWindowPos to set the game to Not TOPMOST, it didnt work either.
          // here was my code : SetWindowPos(handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

error = GetLastError();// i tried using GetLastError to understand what was happening
cout << error << endl;// but it only returns "5", I've read that you can look in WINNT.H for information about the meanings of error codes
                      // however its a pretty big file and I wasn't able to understand where the relevant part was.


return app.exec();

My guess is that application such as games have a more direct control over the display device. I'm looking for any solution to this problem (not neccesseraly one involving a transparent topmost window). Also on a sidenote if someone could explain to me how to effectively use GetLastError(), and also why are game behaving differently than a common window.

Thanks in advance.

Navicert answered 18/4, 2012 at 13:47 Comment(11)
+1 for a hi-tech solution to drawing a dot on the screen where the ironsights centre :PUnwearied
Oh! I know that one off-by-heart. It's 'ACCESS_DENIED' :( There's some API for getting the actual error message from the GetLastError() number, but I've forgotten it for now.Airfield
I enjoy that this uses the topmost tag. :)Affluence
Hehe! There is a tag for topmost :))Airfield
I am not at home so I cannot check, but does nVidia provide a "laser" sight for non-3D vision gaming? When you play with 3D vision some games mess up the crosshairs (producing doubles) and the solution is disable the game crosshair and enable the nVidia one. Also shame on you for cheating in Killing Floor, un-aimed headshots is something you learn by heart.Gauffer
Call me old school but sounds like you need a water soluble felt tip pen? Ink on the screen is always topmostHeterotrophic
@JamesAllan - my app controls a laser that burns its image onto your retina. My app is topmost! Felt-tip - bah!Airfield
Anything wrong with transparent child window? I've done that before and it worked well.Threw
@MikeKwan I tried it using the setParent function of windows api, however i wasnt able to make it work , can you expand on how you achieved it?Navicert
You should find out how Steam does this. I bet Qt won't work this way.Fahy
did you over come this ? since it past 1 year and no solution is accepted ... i want to do this to show an alert like Xfire's new messageSybaris
R
1

From the SetWindowPos() documentation:

A window can be made a topmost window either by setting the hWndInsertAfter parameter to HWND_TOPMOST and ensuring that the SWP_NOZORDER flag is not set, or by setting a window's position in the Z order so that it is above any existing topmost windows. When a non-topmost window is made topmost, its owned windows are also made topmost. Its owners, however, are not changed.

Also from the same page:

To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.

However, I guess the link is for Windows Vista and above.

Royalroyalist answered 18/4, 2012 at 13:56 Comment(0)
K
1

I found that the c++ library DirectDrawOverlayLib should be able to do this. To quote the website:

An unmanaged C++ library to create, manage and draw to DirectDraw overlays. A C++/CLI wrapper for .NET clients is included.

DirectDraw overlays are special DirectDraw surfaces that are shown over everything else, including full-screen games and applications. They can be used to implement programs like XFire that display information during fullscreen game operation.

Kwashiorkor answered 7/9, 2012 at 9:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.