views:

59

answers:

1

Note:

  • Using Windows Forms
  • preferably C# .NET

Question:

  • Best method for implementing a drag-over-window tool, similar (or identical) to that featured in process explorer, to obtain the process ID corresponding to the selected Window
+1  A: 

I think the easiest way is to put a control on your form that acts as a starting point; you press a mouse button there, and then you move it over the screen while the button is pressed, and pick up the process ID of whatever you are pointing at. I my example I have used a panel (called _aim).

First we set up the mouse events:

private void Panel_MouseDown(object sender, MouseEventArgs e)
{
     // make all mouse events being raised in the _aim panel
     // regardless of whether the mouse is within the control's
     // bounds or not
    _aim.Capture = true;
}

private void Panel_MouseMove(object sender, MouseEventArgs e)
{
    if (_aim.Capture)
    {   
        // get the process id only if we have mouse capture 
        uint processId = GetProcessIdFromPoint(
            _aim.PointToScreen(e.Location)).ToString();
        // do something with processId (store it for remembering the 
        // last processId seen, to be used as MouseUp for instance)
    }
}
private void Panel_MouseUp(object sender, MouseEventArgs e)
{
    if (_aim.Capture)
    {
        // release capture if we have it
        _aim.Capture = false;
        // perhaps do something more (fetch info about last seen
        // process id, if we stored it during MouseMove, for instance)
    }
}

The GetProcessIdFromPoint method looks like this:

private uint GetProcessIdFromPoint(Point point)
{
    uint procId;
    WinApi.GetWindowThreadProcessId(WinApi.WindowFromPoint(point), out procId);
    return procId;
}

And finally the windows API things (from pinvoke.net):

public static class WinApi
{
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        public static implicit operator System.Drawing.Point(POINT p)
        {
            return new System.Drawing.Point(p.X, p.Y);
        }

        public static implicit operator POINT(System.Drawing.Point p)
        {
            return new POINT(p.X, p.Y);
        }
    }

    [DllImport("user32.dll")]
    public static extern IntPtr WindowFromPoint(POINT Point);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
}
Fredrik Mörk