C
C#β€’16mo ago
Ossie

❔ 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
Jester
Jesterβ€’16mo ago
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>
Ossie
OssieOPβ€’16mo ago
Will this also work for x64 ?
Jester
Jesterβ€’16mo ago
yes win32 is 64 bit on 64bit machines
Ossie
OssieOPβ€’16mo ago
ok
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
Okay πŸ™‚ But, what if I don't know the class name of the window
Jester
Jesterβ€’16mo ago
you dont need it, its optional idk how familiar you are with interop?
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
the problem is overlays arent simple LULLLLLL
Ossie
OssieOPβ€’16mo ago
:/
Jester
Jesterβ€’16mo ago
while they shouldnt have to be <:PES_Think:639363477458255874>
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
its called GameOverlay.NET, and I searched on some guides or smth for it, and got straight to unknown cheats, so yea im guessing
Jester
Jesterβ€’16mo ago
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?
Ossie
OssieOPβ€’16mo ago
idk, it would nice to deisng it a little but primary just text yea text and shapes should be fine
Jester
Jesterβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
i wish i could just change the render pipeline of WPF a little <:PES_Cry:493359762432327691>
Ossie
OssieOPβ€’16mo ago
hehe what do I need to do to use the FindWindowW functions? do I need a DllImport or using something?
Jester
Jesterβ€’16mo ago
DllImport but in newer C# .NET it seems to recommend LibraryImport which is pretty much the same
Ossie
OssieOPβ€’16mo ago
what dll do i need to import? winuser.dll?
Jester
Jesterβ€’16mo ago
user32
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
yes, .NET doesnt know what HWND is but its an IntPtr
Ossie
OssieOPβ€’16mo ago
ah ok
Jester
Jesterβ€’16mo ago
like this for example
[LibraryImport("user32.dll", EntryPoint = "FindWindowW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal static partial IntPtr FindWindow(string lpClassName, string lpWindowName);
[LibraryImport("user32.dll", EntryPoint = "FindWindowW", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal static partial IntPtr FindWindow(string lpClassName, string lpWindowName);
Ossie
OssieOPβ€’16mo ago
but, do I then make the function called FindowW or okay i get their inaccessible due to their protection level...
Jester
Jesterβ€’16mo ago
if you give it an entrypoint it imports that function and then you can name it whatever you like make it public?
Ossie
OssieOPβ€’16mo ago
its the LibraryImport not the function
Jester
Jesterβ€’16mo ago
put the functions in a class like this
public static partial class User32
{
...
}
public static partial class User32
{
...
}
Ossie
OssieOPβ€’16mo ago
aight
Jester
Jesterβ€’16mo ago
which version of .NET are you on?
Ossie
OssieOPβ€’16mo ago
6 .0 core
Jester
Jesterβ€’16mo ago
then i think you still have to use DllImport
[DllImport("user32.dll", EntryPoint = "FindWindowW", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindowW", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
like that then you dont need partial
Ossie
OssieOPβ€’16mo ago
Okay And now I can call the User32.FindWindow to call the FindWindowW
Jester
Jesterβ€’16mo ago
yes
Ossie
OssieOPβ€’16mo ago
what type is lpRect in .Net?
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
you have to initialise the rect in advance and then ref it
Ossie
OssieOPβ€’16mo ago
Yeye
Jester
Jesterβ€’16mo ago
bing chat is being annoying, why doesnt it just give me code
Ossie
OssieOPβ€’16mo ago
Rect r = new Rect();
GetWindowRect(hwnd, ref r);
Rect r = new Rect();
GetWindowRect(hwnd, ref r);
Jester
Jesterβ€’16mo ago
[DllImport("user32")]
[return: MarshalAs(something.Bool)]
public static extern bool GetWindowRect(IntPtr handle, ref Rect rect);
[DllImport("user32")]
[return: MarshalAs(something.Bool)]
public static extern bool GetWindowRect(IntPtr handle, ref Rect rect);
Ossie
OssieOPβ€’16mo ago
for this one
Ossie
OssieOPβ€’16mo ago
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.
Ossie
OssieOPβ€’16mo ago
I would want it to be HWND_TOPMOST, but what do I pass in the function do I just pass -1?
Jester
Jesterβ€’16mo ago
[StructLayout(Sequential)]
public struct Rect {
public int Left;
public int Top;
public int Right;
public int Bottom; }
[StructLayout(Sequential)]
public struct Rect {
public int Left;
public int Top;
public int Right;
public int Bottom; }
yep
Ossie
OssieOPβ€’16mo ago
Do I need that custom Struct Rect, or can I use the one from System.Windows
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
idk what is accessability modifiers
Jester
Jesterβ€’16mo ago
public, private, internal etc just make it all public
Ossie
OssieOPβ€’16mo ago
It wants me to do LayoutKind.Sequential, is that ok?
Jester
Jesterβ€’16mo ago
yes
Ossie
OssieOPβ€’16mo ago
ok Well I have a User32.cs now with the three functions and no errors, so thats a start atleast
Jester
Jesterβ€’16mo ago
otherwise the memory of the fields can be in a different order than you wrote it can you show it for me to check?
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
Since the FindWindowW, has the first parameter as optional, do I jsut pass a null value to it?
Jester
Jesterβ€’16mo ago
yes
Ossie
OssieOPβ€’16mo ago
ok
Jester
Jesterβ€’16mo ago
you have to change the return type of getwindowrect and setwindowpos it has to be like this
Ossie
OssieOPβ€’16mo ago
oh yea, i changed it to bool now sorry for both?
Jester
Jesterβ€’16mo ago
add the publics like here yes like in the docs
Ossie
OssieOPβ€’16mo ago
I dont understand
Jester
Jesterβ€’16mo ago
the return needs the marshalas bcuz a bool in C is 32bit and in c# only 8
Ossie
OssieOPβ€’16mo ago
what is something.Bool
Jester
Jesterβ€’16mo ago
something is an enum i forgot the name of
Ossie
OssieOPβ€’16mo ago
so what do I write instead of something
Jester
Jesterβ€’16mo ago
what does it tell you to write?
Ossie
OssieOPβ€’16mo ago
nothing it just says error with something
Jester
Jesterβ€’16mo ago
UnmanagedType
Ossie
OssieOPβ€’16mo ago
okay so this is
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
better ?
Jester
Jesterβ€’16mo ago
yes looks good hold on you made the second HWND an int instead of intptr in the last function
Ossie
OssieOPβ€’16mo ago
yes because isnt -1 an int?
Jester
Jesterβ€’16mo ago
yes but it wants more bits than an int
Ossie
OssieOPβ€’16mo ago
or it still needs to be a intpointer? Okay
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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...
Jester
Jesterβ€’16mo ago
dont look at the return value of it, its not really useful
Ossie
OssieOPβ€’16mo ago
wdym
Jester
Jesterβ€’16mo ago
oh wiat
Ossie
OssieOPβ€’16mo ago
how would I know if I have found the window then
Jester
Jesterβ€’16mo ago
lmao my bad yes you do need the returned value
Ossie
OssieOPβ€’16mo ago
I thought i had a way but now it says I cant use a unassigned variable...
Ossie
OssieOPβ€’16mo ago
Jester
Jesterβ€’16mo ago
no dont make it nullable that changes the type null is just 0, so you have to check if the IntPtr is 0
Ossie
OssieOPβ€’16mo ago
Okay How do I get around the Unassigned variable thing
Jester
Jesterβ€’16mo ago
IntPtr FoundWindow = default;
Ossie
OssieOPβ€’16mo ago
oh, ok, didn't know that existed
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
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 right
Ossie
OssieOPβ€’16mo ago
im not sure i understand im just gonna write the code and try it
Jester
Jesterβ€’16mo ago
you need to have the window title exactly right to find the window
Ossie
OssieOPβ€’16mo ago
Okay, I have created the following now
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
So this code, if I understand, will draw the Window (OverLay) on top of the window title I input?
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
Because, I don't wanna draw the overlay imediatly on startup, only when the window to draw on is found
Jester
Jesterβ€’16mo ago
okay so when you have found it, break the loop and show the window
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
This better?
Jester
Jesterβ€’16mo ago
yes
Ossie
OssieOPβ€’16mo ago
Im going thru Mainwindow.overlay since I instance the class from there Okay Im gonna try to build and run it
Jester
Jesterβ€’16mo ago
drawoverlay doesnt have to be static
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
its not top most?
Ossie
OssieOPβ€’16mo ago
no
Jester
Jesterβ€’16mo ago
oh yeah you put notepad top most above your window instead of the opposite
Ossie
OssieOPβ€’16mo ago
oh how do I do it the other way around lol I get the window for the overlay?
Jester
Jesterβ€’16mo ago
you can get that like this or simular IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
Ossie
OssieOPβ€’16mo ago
but i dont want the mainwindow I need the Overlay Window
Jester
Jesterβ€’16mo ago
then use the overlay window as argument
Ossie
OssieOPβ€’16mo ago
eh how its not showing with Intellisense
Jester
Jesterβ€’16mo ago
so for the setwindowposition you need your own handle im guessing this
Ossie
OssieOPβ€’16mo ago
WindowInteropHandler(this)?
Jester
Jesterβ€’16mo ago
yes
Ossie
OssieOPβ€’16mo ago
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;
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
okay and how would I turn that into coordinates for the overlay?
Jester
Jesterβ€’16mo ago
should be the same
Ossie
OssieOPβ€’16mo ago
if I have the x,y and for cornerns isnt it just x,y for top corner rect.Left, rect.Top
Jester
Jesterβ€’16mo ago
width = right - left
Ossie
OssieOPβ€’16mo ago
Okay, now it draws it on top but if I focus the application, it dissapears how do I make the overlay stay and follow
Jester
Jesterβ€’16mo ago
close and open notepad again and then re-run your app
Ossie
OssieOPβ€’16mo ago
huh i dont understand
Jester
Jesterβ€’16mo ago
well i think before you made the notepad window top most as well on accident
Ossie
OssieOPβ€’16mo ago
im not using notepad anymore im using Epic Games Launcher rn
Jester
Jesterβ€’16mo ago
oh ok
Ossie
OssieOPβ€’16mo ago
it was just easier to type but let me check its fully closed
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
yes, im not sure why its not top most bcuz ur passing in -1
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
ooh i forgot about the flags read the docs about the flags of setwindowpos closely and the remarks maybe
Ossie
OssieOPβ€’16mo ago
eh i dont understand it really there is many maybe this one SWP_SHOWWINDOW - Displays the window
Jester
Jesterβ€’16mo ago
well it was already showing so not really
Ossie
OssieOPβ€’16mo ago
idk then
Jester
Jesterβ€’16mo ago
hmm maybe not a flag so your overlay window is not showing above the epic games launcher?
Ossie
OssieOPβ€’16mo ago
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
If neither the SWP_NOACTIVATE nor SWP_NOZORDER flag is specified (that is, when the application requests that a window be simultaneously activated and its position in the Z order changed), the value specified in hWndInsertAfter is used only in the following circumstances.

Neither the HWND_TOPMOST nor HWND_NOTOPMOST flag is specified in hWndInsertAfter.
The window identified by hWnd is not the active window.
If neither the SWP_NOACTIVATE nor SWP_NOZORDER flag is specified (that is, when the application requests that a window be simultaneously activated and its position in the Z order changed), the value specified in hWndInsertAfter is used only in the following circumstances.

Neither the HWND_TOPMOST nor HWND_NOTOPMOST flag is specified in hWndInsertAfter.
The window identified by hWnd is not the active window.
Jester
Jesterβ€’16mo ago
they couldve written that better
Ossie
OssieOPβ€’16mo ago
i dont totally understand it
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
Jester
Jesterβ€’16mo ago
ah you didnt pass in a width and height into to setwindowposition, maybe thats an issue?
Ossie
OssieOPβ€’16mo ago
I did before, and it was the same issue
Jester
Jesterβ€’16mo ago
im clueless let me search my own code looks fine to Huh
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
you did change the int to an intptr right?
Ossie
OssieOPβ€’16mo ago
Yes
Ossie
OssieOPβ€’16mo ago
Jester
Jesterβ€’16mo ago
okay <:PES_Think:639363477458255874>
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
it gets shown but as soon as I click anywhere on the window under, it just goes behind
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
eh how?
Ossie
OssieOPβ€’16mo ago
Ossie
OssieOPβ€’16mo ago
these?
Jester
Jesterβ€’16mo ago
like when you change properties of a label no in the editor
Ossie
OssieOPβ€’16mo ago
ah I can do TopMost = true on the window
Jester
Jesterβ€’16mo ago
try that
Ossie
OssieOPβ€’16mo ago
ok yes now it works ...
Jester
Jesterβ€’16mo ago
thumbsupsmiley solved
Ossie
OssieOPβ€’16mo ago
but, now it draws over eveything else lol is that meant to happen
Jester
Jesterβ€’16mo ago
yes, its all or nothing sadly
Ossie
OssieOPβ€’16mo ago
:/ wish you could do something like WindowIWannaDrawOverZ+1
Jester
Jesterβ€’16mo ago
yeah that would be nice but unfortunatly not
Ossie
OssieOPβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
Im just gonna try something, but thanks so fucking much I would have never figured this out without you
Jester
Jesterβ€’16mo ago
sunglas took me a while to figure it all out myself a while ago
Ossie
OssieOPβ€’16mo ago
just a quick final question
Jester
Jesterβ€’16mo ago
getting to know internals and modifying linux? howieno mastering and customizing windows? howieyes
Ossie
OssieOPβ€’16mo ago
how can I make the Handle to the overlaywindow outside of the DrawOverlay()? I can't use this outside of the method
Jester
Jesterβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
okay is it a bad idea to get the WindowSize of the window under a lot of times
Jester
Jesterβ€’16mo ago
30 times a second should be enough for sure and fine only as much as nescessary
Ossie
OssieOPβ€’16mo ago
I will look into it tommorow, sleep well, and thanks for the help
Jester
Jesterβ€’16mo ago
good night
sibber
sibberβ€’16mo ago
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
Ossie
OssieOPβ€’16mo ago
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:
private void UpdateWindowPos(object sender, EventArgs e)
{
if (Found)
{
this.Dispatcher.Invoke((Action)(() =>
{
Classes.User32.Rect rect = GetRect();
DrawText.Text = rect.Left.ToString() + " " + rect.Top.ToString();
Classes.User32.SetWindowPosition(OverlayWindowHandle, (IntPtr)(-1), rect.Left, rect.Top, 10, 10, 0);
}));
}
}
private void UpdateWindowPos(object sender, EventArgs e)
{
if (Found)
{
this.Dispatcher.Invoke((Action)(() =>
{
Classes.User32.Rect rect = GetRect();
DrawText.Text = rect.Left.ToString() + " " + rect.Top.ToString();
Classes.User32.SetWindowPosition(OverlayWindowHandle, (IntPtr)(-1), rect.Left, rect.Top, 10, 10, 0);
}));
}
}
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
Ossie
OssieOPβ€’16mo ago
sibber
sibberβ€’16mo ago
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
Jester
Jesterβ€’16mo ago
Huh
Ossie
OssieOPβ€’16mo ago
I fixed it with this.Left and this.Top
Accord
Accordβ€’16mo ago
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.
Want results from more Discord servers?
Add your server