2

I need some help with trying to get the position of the notepad window. I'm pretty sure I need to use the GetWindowRect function, which is below, but I do not know how to use it. I've put what is below in to a win form project, but myRect.X, myRect.Y, etc. did not have anything in them. I though they should've at least had the x, y, width, height, of the winform I was working in. But it always displayed 0. honestly I just don't understand how to use this. Ive looked around for a 5ish hours now. but haven't learned anything.

[DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

     [StructLayout(LayoutKind.Sequential)]
     public struct RECT
     {
         public int Left;        // x position of upper-left corner
         public int Top;         // y position of upper-left corner
         public int Right;       // x position of lower-right corner
         public int Bottom;      // y position of lower-right corner
     }

     Rectangle myRect = new Rectangle();

     private void button1_Click(object sender, System.EventArgs e)
     {
         RECT rct;

         if(!GetWindowRect(new HandleRef(this, this.Handle), out rct ))
         {
             MessageBox.Show("ERROR");
             return;
         }
         MessageBox.Show( rct.ToString() );

         myRect.X = rct.Left;
         myRect.Y = rct.Top;
         myRect.Width = rct.Right - rct.Left + 1;
         myRect.Height = rct.Bottom - rct.Top + 1;
     }

I’ve also tried the code below, but still the most I got out of this is DrawingBasicShapes.Form1+Rect located in the NotepadRect.

Then there is true in the GetWindowRect(ptr, ref NotepadRect). I used MessageBox.Show(Convert.ToString(NotepadRect)); to get what was inside.. Same for the other, I’m thinking that was wrong. But I do not know how to show what’s in it.

I was expecting numbers or something to be in here but I guess not. I’m sorry if this is a novice question, or if the answer is clear to you. But I normally do not work with dll import. So I am slowly learning how to use it...

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);

[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

public struct Rect
{
  public int Left { get; set; }
  public int Top { get; set; }
  public int Right { get; set; }
  public int Bottom { get; set; }
}

Process[] processes = Process.GetProcessesByName("notepad");
Process lol = processes[0];
IntPtr ptr = lol.MainWindowHandle;
Rect NotepadRect = new Rect();
GetWindowRect(ptr, ref NotepadRect);
Fortyrunner
  • 12,702
  • 4
  • 31
  • 54
hurnhu
  • 888
  • 2
  • 11
  • 30

2 Answers2

1

If all you are putting in your messagebox is the Rect object itself, that's exactly what output you're going to get.

Output your messagebox as follows:

MessageBox.Show( string.Format("Left: {0}\r\nTop: {1}\r\nRight: {2}\r\nBottom: {3}", NotepadRect.Left, NotepadRect.Top, NotepadRect.Right, NotepadRect.Bottom));
dodexahedron
  • 4,584
  • 1
  • 25
  • 37
  • thanks, now if i wanted to store the right side in to a point could i just do. Point startPoint = new Point(NotepadRect.right); ? – hurnhu Apr 18 '14 at 04:54
  • Not exactly. A point needs two coordinates (x,y), since you're in 2D space. But you have the right idea, yes. – dodexahedron Apr 18 '14 at 05:15
  • so lets we are in a windows form, and i wanted to draw a line from one point to another, using NotepadRect. would i just do Point startPoint = new Point(NotepadRect.right, NotepadRect.top); Point endPoint = new Point(800,400); would i be able to draw a line using these two points? – hurnhu Apr 18 '14 at 05:29
  • Yes, those would both be valid points, and the Graphics.DrawLine() function takes a Pen, and two points. So, to draw a line with a Graphics object called g, you'd call g.DrawLine(Pens.Black, startPoint,endPoint); – dodexahedron Apr 18 '14 at 05:40
0

The Rect struct does not override ToString. Therefore converting it to string will only yield the full type name. Nothing else.

Try

string s = String.Format("left = {0}, top = {1}, right = {2}, bottom = {3}",
    NotepadRect.Left, NotepadRect.Top, NotepadRect.Right, NotepadRect.Bottom);
MessageBox.Show(s);

Alternatively you could override ToString in Rect:

public struct Rect
{
    public int Left { get; set; }
    public int Top { get; set; }
    public int Right { get; set; }
    public int Bottom { get; set; }

    public override string ToString()
    {
        return String.Format("left = {0}, top = {1}, right = {2}, bottom = {3}",
            Left, Top, Right, Bottom);
    }
}

Then MessageBox.Show(NotepadRect) will work as expected.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Yes, you can safely override the ToString method and it will still work as expected. – dodexahedron Apr 17 '14 at 21:43
  • 3
    In fact, for a rather nicely done version of the RECT struct, see http://www.pinvoke.net/default.aspx/Structures/rect.html. That one even has implicit conversions to .Net Rectangles defined and such, which might make life in WinForms easier. – dodexahedron Apr 17 '14 at 21:45
  • 3
    As a general rule, your structs will work fine with PInvoke so long as the member fields match and the appropriate LayoutKind is declared, even if you've added custom functions and such. You only really run into trouble when you start adding member fields of your own. Functions and, by extension, properties are fine, so long as they have explicit implementations (meaning don't use auto-properties). – dodexahedron Apr 17 '14 at 21:48