1

I have a program that takes an image (about 50px on 50px), does something with the image and uploads it. At the moment the user still needs to take a screenshot, open paint, crop out the desired part and copy-past it to my program.

I want to make this easier/faster for the user by letting him drag some kind of crosshair to the desired point on the screen and release it. My program then takes a small screenshot of that area (already know how to do that) and does something with that screenshot.

The question is, how can I do this? How can I have a draggable crosshair that the user can drag to a point outside the form and release it, to specify a screen coordinate for the program to use?

user886079
  • 864
  • 2
  • 11
  • 18
  • 1
    Is this for WinForms or WPF? – RogerN Jul 03 '13 at 18:22
  • winforms, but I could switch over to wpf if it's really necessary. – user886079 Jul 03 '13 at 18:23
  • 1
    I'm writing in the comments because this is not the answer you were expecting, but just a suggestion for an alternative. Why don't you have a control that can have an image of any size in it, but with a 50px x 50px viewport over it? Then the user could drag the viewport around. You take a screenshot of whatever is in the viewport. I think it's easier than getting what's being displayed in the monitor as a whole. – Geeky Guy Jul 03 '13 at 18:23
  • Just make a screenshot of the entire screen and display it in a maximized borderless window. – Hans Passant Jul 03 '13 at 18:49

2 Answers2

1

You'll need to do all of the following:

  1. Use the MouseDown / MouseMove / MouseUp events to track when and where the crosshair is being dragged
  2. Set the Capture property of the control to True while the crosshair is being dragged so that you continue to receive MouseMove events after the mouse leaves your form
  3. Draw the crosshair directly to the desktop window (and invalidate the desktop window to erase it) by getting the appropriate window handle and creating a graphics object for it directly. The desktop window handle is always 0.

Drawing to the desktop is pretty easy:

using (var g = Graphics.FromHwnd(IntPtr.Zero))
{
    g.DrawLine(SystemPens.WindowText, 0, 0, 200, 200);
}

To erase what you draw, you'll need to use Platform Invoke to call InvalidateRect for the appropriate location.

RogerN
  • 3,761
  • 11
  • 18
  • It worked. Well the part with the mouse-down, move and up ,and the capture thing. I was able to draw on the screen and erase it but everything started to flicker and it just didn't look like I wanted. I just left it out for now... – user886079 Jul 03 '13 at 22:43
0

Here's a quick and dirty example of allowing the user to left click and drag on the a PictureBox and get the image underneath the cursor. It doesn't update well when the user moves quickly, though:

public partial class Form1 : Form
{

    public Form1()
    {
        InitializeComponent();
        pictureBox1.Cursor = Cursors.Cross;
    }

    private Bitmap bmp = null;
    private Graphics G = null;

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (bmp == null)
            {
                bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
                G = Graphics.FromImage(bmp);
            }
        }
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (bmp != null && G != null)
            {
                Rectangle rc = new Rectangle(Cursor.Position, new Size(1, 1));
                rc.Inflate(pictureBox1.Width / 2, pictureBox1.Height / 2);
                G.CopyFromScreen(rc.Location, new Point(0, 0), rc.Size);
                pictureBox1.Image = bmp;
            }    
        }
    }

}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40