Hi,
As part of research for a project I'm working on, I need to be able to locate hidden windows on my screen.
Ideally I would do something like draw a colored recangle on the sreen at the location where each hidden window is.
I've done some research and I know that DrawRectangle is available. As a pure guess, I created the code below.
Code:
public void drawRectangle(int x, int y, int width, int height )
{
// get desktop window
IntPtr desktopHwnd = GetDesktopWindow();
// Create a new pen.
Pen skyBluePen = new Pen(Brushes.DeepSkyBlue);
// Set the pen's width.
skyBluePen.Width = 8.0F;
// Set the LineJoin property.
skyBluePen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
Graphics.FromHwnd(desktopHwnd).DrawRectangle(skyBluePen, x, y, width, height);
skyBluePen.Dispose();
}
But when I call the function with valid coordinates, it does not draw a rectangle.
It should create a graphics object for the entire screen - it's not documented in GDI+, but it something that originates in the old Windows GDI, where you would pass (C++) NULL to GetDC() to get the device context of the entire screen.
TheGreatCthulhu, thanks.
I tried your suggestion but it did not work. Let me know if I did something wrong.
Code:
public void tempDrawRectUsingGraphicsObject(int x, int y, int width, int height)
{
Console.WriteLine("In tempDrawRectUsingGraphicsObject");
// get desktop window
//IntPtr desktopHwnd = GetDesktopWindow();
// Create a new pen.
Pen pen = new Pen(Brushes.Red);
// Set the pen's width.
pen.Width = 8.0F;
// Set the LineJoin property.
pen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
Graphics gr = Graphics.FromHwnd(IntPtr.Zero); //IntPtr.Zero
Font font = new Font("Arial",10);
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
gr.DrawString("Test string", font, myBrush, new PointF(x, y));
gr.DrawRectangle(pen, x, y, width, height);
}
I also tried drawing the rectangle with win API calls:
Code:
public void tempDrawRectUsingWinAPI(int x, int y, int width, int height)
{
Console.WriteLine("In tempDrawRectUsingWinAPI");
IntPtr desktopHwnd = GetDesktopWindow();
Graphics gr = Graphics.FromHwnd(desktopHwnd);
IntPtr hdc = gr.GetHdc();
uint uintColor = Convert.ToUInt32(ColorTranslator.ToOle(Color.FromArgb(255, 0, 0)));
IntPtr gdiPen = CreatePen(0, 5, uintColor);
SelectObject(hdc, gdiPen);
Rectangle(hdc, x, y, x + width, y + height);
}
I think it **is** possible to accomplish what I want, but I'm out of ideas.
Anything you can think of is appeciated.
Strange... One of 3 things is probably happening: either your location/size input parameters aren't right, or there is some interference with the regular windows drawing routine, where your rectangles are overwritten when the screen redraws itself (or portions of itself), or your draw method never get's called.
I attached a small sample application that draws semitransparent rectangles on random screen locations. Note that when you hover your mouse over some parts of the window (like minimize/maximize buttons), a part of the screen get's redrawn. You can even induce the invalidation of the entire screen area.
The gist of the sample is simple, the code below:
Code:
private void m_btnDraw_Click(object sender, EventArgs e)
{
var g = Graphics.FromHwnd(IntPtr.Zero);
int screenWidth = Screen.GetWorkingArea(this).Width;
int screenHeight = Screen.GetWorkingArea(this).Height;
int boxSize = 100;
Brush brsh = new SolidBrush(Color.FromArgb(128, m_rnd.Next(256), m_rnd.Next(256), m_rnd.Next(256)));
g.FillRectangle(brsh,
m_rnd.Next(screenWidth - boxSize),
m_rnd.Next(screenHeight - boxSize),
boxSize,
boxSize
);
brsh.Dispose();
g.Dispose();
}
Thanks very much for working on this for me. For some strange reason rectangles do not get drawn when I run your application.
I had to make one change. I changed this:
Code:
var g = Graphics.FromHwnd(IntPtr.Zero);
to this:
Code:
Graphics g = Graphics.FromHwnd(IntPtr.Zero);
The app would not compile with "var" -- but it seems this change would not cause to the app to fail to draw the rectangles.
I've created a workaround -- instead of rectangles, I'm drawing semitransparent borderless windows with a red rectangle drawn inside. (Imitation rectangles.)
Hi Evets, is there any particular reason you need to draw the rectangle on the screen?
What I did to highlight part of my GUI is just create a blank form with no borderstyle, a light blue background and set its opacity to 50% or so to make it transparent. That way I can define it's size and location, hide it, move it, close it, whatever you can do to a form. I might not allow you to click on the window it is highlighting, but you'd get the result.
In case you do need to click on it, you could always overwrite the OnPaint method and draw the form as a frame, perhaps with less transparency to make it stand out more.
I wanted to draw a rectangle because that's what I saw in another app (WinSpector Spy).
With all the issues I ran into, though, I ended up doing exactly what you suggested -- a semi-transparent window with no border. I overrided the OnPaint method to draw a red rectangle within the window. Of course all this I encapsulated into a class so I could easily instantiate and position the windows. Also this solution is slightly better than a rectangle because I can write text into the window that will help me with research/debugging.
I still want to figure out how to draw the rectangle, but just as a matter of interest (a challenge that's hard to let go of.)
Bookmarks