β Overlay on other Windows from WPF
Hello π
Is it possible from WPF to make a overlay over another window.
I wanna show some information over another window on the computer from my WPF application, and was wondering if its possible, and if so how?
Thanks
192 Replies
I know about Win32 but not everything about WPF capabilities. But yeah you could make your WPF window a top-most window. Then you could get the handle of the window you want to overlay and get its position on the screen to reposition your window above it. Some issues might be; getting WPF to be transparent and finding the right window.
a way to get the window handle: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindoww
a way to find where it is: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect
a way to position and top-most your wpf app: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos
hope this helps <:PES_ThumbsUp:513327253728264192>
Will this also work for x64 ?
yes win32 is 64 bit on 64bit machines
ok
they updated it from 16 bit to 32 but didnt rename it from 32 to 64 <:PES_SadShrug:646092743378206760>
WPF uses it under the hood too
Okay π
But, what if I don't know the class name of the window
you dont need it, its optional
idk how familiar you are with interop?
Can't I use like a process or smth
I don't know anything about this topic
I just wanna make a simple overlay for a game
the problem is overlays arent simple
:/
while they shouldnt have to be <:PES_Think:639363477458255874>
I found a nuget package, which is for .net, but it seems to be for cheats injected into a process, and then it draws on that window, but I just wanna find the window in the current processes
i think that nuget package then hooks into the swapchain of the game process to inject extra drawing
yes your own window above the game should be simpler
its called GameOverlay.NET, and I searched on some guides or smth for it, and got straight to unknown cheats, so yea im guessing
i think i have a project you might be able to build on
what does your overlay need to have of functionality? just display text and shapes?
idk, it would nice to deisng it a little but primary just text
yea text and shapes should be fine
in this project i built upon a different one which allows you to easely draw text and shapes on a window. i made it so your own window is fully transparent
https://github.com/QubitTooLate/Win2DSample/tree/main
GitHub
GitHub - QubitTooLate/Win2DSample: A simple and minimal Win2D sampl...
A simple and minimal Win2D sample in an unpackaged Win32 app - GitHub - QubitTooLate/Win2DSample: A simple and minimal Win2D sample in an unpackaged Win32 app
its not WPF but thats maybe an advantage
you just have to add this functionality and then draw whatever
it should already be top most
bcuz this code is quite low-level compared to WPF not every method will be as easy to understand
I'm just gonna try with the first things you send, with a WPF Window and see if I can maybe get it to work
i wish i could just change the render pipeline of WPF a little <:PES_Cry:493359762432327691>
hehe
what do I need to do to use the FindWindowW functions?
do I need a DllImport or using something?
DllImport but in newer C# .NET it seems to recommend LibraryImport which is pretty much the same
what dll do i need to import?
winuser.dll?
user32
idk I dont think i understand
it says on the docs
the return type is HWND, but when I try to make the type HWND it says it doesn't exist
yes, .NET doesnt know what HWND is but its an IntPtr
ah ok
like this for example
but, do I then make the function called FindowW or
okay
i get their inaccessible due to their protection level...
if you give it an entrypoint it imports that function and then you can name it whatever you like
make it public?
its the LibraryImport
not the function
put the functions in a class like this
aight
which version of .NET are you on?
6
.0
core
then i think you still have to use DllImport
like that
then you dont need
partial
Okay
And now I can call the User32.FindWindow to call the FindWindowW
yes
what type is lpRect in .Net?
you would have to make a rect structure and have a pointer or reference to it in the method
im asking bing chat to give me the code so i dont have to write it all myself but i know if the code is correct or not
ah ok
so i can make it a ref in the function def and then just pass a new Rect
with a ref to it
you have to initialise the rect in advance and then ref it
Yeye
bing chat is being annoying, why doesnt it just give me code
for this one
SetWindowPos function (winuser.h) - Win32 apps
Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order.
I would want it to be HWND_TOPMOST, but what do I pass in the function
do I just pass -1?
yep
Do I need that custom Struct Rect, or can I use the one from System.Windows
im writing the code myself bcuz the AI doesnt want to do it
like this but add the accessability modifiers
some methods are a hell to dll import, but there are generators to do it for you, but you dont need many so you dont really need them to be generated for you yet
idk what is accessability modifiers
public, private, internal etc
just make it all public
It wants me to do LayoutKind.Sequential, is that ok?
yes
ok
Well I have a User32.cs now with the three functions and no errors, so thats a start atleast
otherwise the memory of the fields can be in a different order than you wrote it
can you show it for me to check?
Since the FindWindowW, has the first parameter as optional, do I jsut pass a null value to it?
yes
ok
you have to change the return type of getwindowrect and setwindowpos
it has to be like this
oh yea, i changed it to bool now sorry
for both?
add the publics like here
yes like in the docs
I dont understand
the return needs the marshalas bcuz a bool in C is 32bit and in c# only 8
what is something.Bool
something is an enum i forgot the name of
so what do I write instead
of something
what does it tell you to write?
nothing
it just says error with something
UnmanagedType
okay
so this is
better ?
yes looks good
hold on
you made the second HWND an int instead of intptr
in the last function
yes because isnt -1 an int?
yes but it wants more bits than an int
or it still needs to be a intpointer?
Okay
intptr is 64 bit on 64 bit and int is always 32
sometimes it might work if you use the wrong types, until it doesnt or crashes everything
ok lol
good to know
i dont understand
it says on the docs
that FindWindowW can return null, but when I check if the return of the function is null, it says it can never be null
And if I try to make it nullable, then I can't use it for any of the other functions...
dont look at the return value of it, its not really useful
wdym
oh wiat
how would I know if I have found the window then
lmao
my bad
yes you do need the returned value
I thought i had a way
but now it says I cant use a unassigned variable...
no dont make it nullable that changes the type
null is just 0, so you have to check if the IntPtr is 0
Okay
How do I get around the Unassigned variable thing
IntPtr FoundWindow = default;
oh, ok, didn't know that existed
bcuz IntPtr is a struct, and if you make a struct nullable, it actually becomes a different type. which we cant have bcuz then the bytes wont align anymore
null is just a fancy 0
I still dont quite understand
If I run the code im doing rn, from a new WPF window, will that window then get drawed? or do I need to tell it somewhere which window to draw
i dont understand what you mean
IntPtr?
is actually Nullable<IntPtr>
which is different than IntPtr
you draw on your own WPF window but your WPF window is going to be above the game if everything goes rightim not sure i understand
im just gonna write the code and try it
you need to have the window title exactly right to find the window
Okay, I have created the following now
So this code, if I understand, will draw the Window (OverLay) on top of the window title I input?
yes but why did you make your own window hidden? and you cant really have a while loop there bcuz its going to get stuck in it
Because, I don't wanna draw the overlay imediatly on startup, only when the window to draw on is found
okay
so when you have found it, break the loop and show the window
This better?
yes
Im going thru Mainwindow.overlay since I instance the class from there
Okay Im gonna try to build and run it
drawoverlay doesnt have to be static
oh ok
probably form before, when I tried to use DllImport it said it had to be static, just forgot to remove
idk what is a good window to test on
notepad should be good but the problem is the title of notepad can not always be clear
if you look in the taskbar and hover your mouse over an app icon of an open window you can see its title
ye
hm
it doesn't draw it on top
it just draws the overlay as a new window
or well
it draws it in the correct location
but its drawn behind
its not top most?
no
oh yeah you put notepad top most above your window instead of the opposite
oh
how do I do it the other way around lol
I get the window for the overlay?
you can get that like this or simular
IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
but i dont want the mainwindow
I need the Overlay Window
then use the overlay window as argument
eh how
its not showing with Intellisense
so for the setwindowposition you need your own handle
im guessing
this
WindowInteropHandler(this)?
yes
and just quick question, im not totally sure of the rect thing
how would I turn that into the top left corner of the window i wanna do the overlay on
is it just left; top;
Retrieves the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
it doesnt give you the size of the window
it gives you the rectangle on screen where the window is
okay
and how would I turn that into coordinates for the overlay?
should be the same
if I have the x,y and for cornerns
isnt it just x,y for top corner
rect.Left, rect.Top
width = right - left
Okay, now it draws it on top
but if I focus the application, it dissapears
how do I make the overlay stay and follow
close and open notepad again
and then re-run your app
huh
i dont understand
well i think before you made the notepad window top most as well on accident
im not using notepad anymore
im using Epic Games Launcher rn
oh ok
it was just easier to type
but let me check its fully closed
well if the window you are trying to get above isnt top most and yours doesnt stay above it then yours isnt top most either
hm, idk I just always want to have the overlay on top of the window
i dont care about other things getting in front, as long as its on top of the actual window i want
yes, im not sure why its not top most bcuz ur passing in -1
but right now, when I jsut focus epic games launcher, it just hides behind it
and if I focus something else, it hides behind that aswell
ooh i forgot about the flags
read the docs about the flags of setwindowpos closely
and the remarks maybe
eh i dont understand it really
there is many
maybe this one
SWP_SHOWWINDOW - Displays the window
well it was already showing so not really
idk then
hmm maybe not a flag
so your overlay window is not showing above the epic games launcher?
right when I launch it, it shows
but as soon as I focus the launcher, it just goes behind like any other application would
like when you focus something behind someting else on windows, it just goes beheind
i found this in the remarks
they couldve written that better
i dont totally understand it
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.
show me your code again
ah you didnt pass in a width and height into to setwindowposition, maybe thats an issue?
I did before, and it was the same issue
im clueless
let me search my own code
looks fine to
I also just tried to do it on the MainWindow of just the application it self, to check it wasnt something weird with epic games launcher
but still
it just hides behind when I focus the other window
you did change the int to an intptr right?
Yes
okay
<:PES_Think:639363477458255874>
it gets shown
but as soon as I click anywhere on the window under, it just goes behind
ok so what if you look into the wpf window properties maybe there is a setting to set it as topmost
probably. that should solve it
eh
how?
these?
like when you change properties of a label
no
in the editor
ah
I can do TopMost = true
on the window
try that
ok
yes
now it works
...
solved
but, now it draws over eveything else lol
is that meant to happen
yes, its all or nothing sadly
:/
wish you could do something like
WindowIWannaDrawOverZ+1
yeah that would be nice but unfortunatly not
okay
well
still
also
How would I make it follow the window its drawed on around?
I can make like a tick or smth, i havent tried that before
you need a timer to have something happen repeatedly
i think thats also a wpf thing in the editor?
im going to sleep soon, you will probably also have to make your window click-trough if its not yet
Im just gonna try something, but thanks so fucking much
I would have never figured this out without you
took me a while to figure it all out myself a while ago
just a quick final question
getting to know internals and modifying linux?
mastering and customizing windows?
how can I make the Handle to the overlaywindow outside of the DrawOverlay()?
I can't use this outside of the method
make it a field in your overlay class
also your drawoverlay method is doing too much right now, to make the code more readable you should divide it in multiple functions which each do only one thing
add some DRY (dont repeat yourself) and SRP (single responsability principle) to your code
okay
is it a bad idea to get the WindowSize of the window under a lot of times
30 times a second should be enough for sure and fine
only as much as nescessary
I will look into it tommorow, sleep well, and thanks for the help
good night
this is gonna be harder
a simple topmost window probably wont work on fullscreen games
one way i know that is used to to hook into the graphics api and draw
that means you need to implement that for every graphics api that a game may use
or find an implementation/lib
or you can try a topmost window and see if it works
i just really dont wanna fiddle with injection, as the game has an anti cheat, and I donβt wanna get bannedβ¦
So I've tried to create a timer, but it doesn't update the WindowPos for some odd reason.
I have the following as a Timer.Elapsed event:
But, this doesn't update the position of the overlay for some reason, however the text get changed to the right thing, it updates like it should to the new rect coordinates. but the windowposition of the overlay never changes
this wont trigger it
you wouldnt be modifying any of the games files
fraps is open source iirc you can check at how they did it
if their implementation still works
I fixed it with this.Left and this.Top
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.