Click to See Complete Forum and Search --> : Drawing On Top Of Another Application
Homogenn
February 27th, 2008, 08:57 AM
I just created an application to see if I were able to draw a string on top of another application (a game). Essentially it's going to be a parser that will show how much damage you do per second, by reading a log file.
What I'm currently doing is having a timer redraw it every so often, but problem is it flickers a lot. I remember when I created a screensaver I had to enable double buffering, to prevent it from flickering, but since I don't really have the same control over the application, I'm kinda stumped as to what to do. Here's the code I use to find window and draw on it:
Graphics eqGraphic;
Font font;
SolidBrush brush;
private void Form1_Load(object sender, EventArgs e)
{
Process[] ps = Process.GetProcesses();
Process eqProcess = null;
foreach (Process p in ps)
{
if (p.MainWindowTitle == "EQW beta 2.35a")
{
eqProcess = p;
break;
}
}
//listBox1.Items.Add(eqProcess.MainWindowHandle);
IntPtr ptr = eqProcess.MainWindowHandle;
eqGraphic = Graphics.FromHwnd(ptr);
font = new Font("Arial", 16);
brush = new SolidBrush(Color.Black);
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
eqGraphic.DrawString("HELLO", font, brush, new PointF(100, 100));
}
jon.borchardt
February 27th, 2008, 05:16 PM
Im not sure this is not working for you, but at very least, I would get the graphics reference from within the timer and release it when done...
private void timer1_Tick(object sender, EventArgs e)
{
using(Graphics eqGraphic = Graphics.FromHwnd(ptr))
{
eqGraphic.DrawString("HELLO", font, brush, new PointF(100, 100));
}
}
I would guess this is not working for you because you dont have the right pointer to create the graphics object, can you make it work first with a known graphics object... like inside a picturebox?
Homogenn
February 28th, 2008, 12:39 AM
Im not sure this is not working for you, but at very least, I would get the graphics reference from within the timer and release it when done...
private void timer1_Tick(object sender, EventArgs e)
{
using(Graphics eqGraphic = Graphics.FromHwnd(ptr))
{
eqGraphic.DrawString("HELLO", font, brush, new PointF(100, 100));
}
}
I would guess this is not working for you because you dont have the right pointer to create the graphics object, can you make it work first with a known graphics object... like inside a picturebox?
Well, I released the graphic object in the FormClosing event instead, I don't know what's more efficient.
The problem isn't that it doesn't paint it in the window (it does), but that it instantly disappears, thus if I increase the interval number for the timer, the text instantly disappears and reappears at a decreased interval.
I don't know if this is a question for a GDI forum instead, perhaps?
JonnyPoet
February 28th, 2008, 03:03 PM
I would guess that if its a graphics application the graphics is redrawn by the program iitself, in which you are trying to draw. I dont know ifit is possible to hook into the message chain of this application and reading out paint events. But if possible then I would try to draw synchron just after eacg paint event is done. ( Never tried such things so maybe only an idea )
Homogenn
February 29th, 2008, 09:13 AM
I would guess that if its a graphics application the graphics is redrawn by the program iitself, in which you are trying to draw. I dont know ifit is possible to hook into the message chain of this application and reading out paint events. But if possible then I would try to draw synchron just after eacg paint event is done. ( Never tried such things so maybe only an idea )
I couldn't find any way to do this, but I'd be interested if anyone knew.
What I did find out was that the timer was too slow, and instead I created a thread, made it run a function, and just Thread.Sleep(5) and it wouldn't flicker at all (or rather it would write faster than EQ would update).
So this is a very hack solution, which isn't a very good solution (a terrible one to say the least), so if anyone comes up with another way of doing it, I'd be very interested in it.
DeepT
February 29th, 2008, 09:39 AM
If this is a game that uses DirectX then it most likely doesn't use the WM_PAINT method to drive it's rendering. One of the first things they tell you is to make your own timer or loop to call the render function instead of using WM_PAINT.
So if you are trying to key off WM_PAINT then you are not in synch with the application's render function.
The best way to do this is simply to create your own 'window' on the render device and make your own polygon in 2D space and place it on the highest (or lowest) Z level possible. Draw your information on that.
There might be a hook or callback you can get when a device calls the method to Clear or BeginDraw methods (I forgot their exact names) so you know when to re-draw your polygon.
Homogenn
March 1st, 2008, 07:30 AM
If this is a game that uses DirectX then it most likely doesn't use the WM_PAINT method to drive it's rendering. One of the first things they tell you is to make your own timer or loop to call the render function instead of using WM_PAINT.
So if you are trying to key off WM_PAINT then you are not in synch with the application's render function.
The best way to do this is simply to create your own 'window' on the render device and make your own polygon in 2D space and place it on the highest (or lowest) Z level possible. Draw your information on that.
There might be a hook or callback you can get when a device calls the method to Clear or BeginDraw methods (I forgot their exact names) so you know when to re-draw your polygon.
I was looking for exactly something like this, but is that possible in GDI?
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.