views:

69

answers:

2

Hello All

I was using an Adobe product (If I remember correctly, it was a PDF Creator) the other day, and they have this cool feature where you can literally click anywhere inside the window and just start typing. And the text will appear as you type, whereever you clicked.

Can somebody please point me in the right direction where I can learn how to implement something like this?

Thank you

Edit:


Steps to Click & Type:

  1. Capture MouseDown and store location where user clicked.
  2. Handle KeyDown event to see what key was pressed.
  3. Foreach key that is pressed, create a label and place it next to the last-typed character.

@Qua, in the last step, am I right in thinking that? If so, how would I account for the length of an individual character, so I know where to place the next one? I think I would need to somehow measure the type and size of the font in the label and adjust positioning accordingly...?

+1  A: 

Lets say that you wanted to implement this feature on a usercontrol that you were making. At first you would need to handle the mouse down event to register where the user clicked, and after this you should be able to handle the key down event to register which keys the user pressed.

To draw the actual text at the target location you have several options. You could use GDI+ to render the strings on the control or you could insert labels which would benefit you due to the amount of functionality that the labels come with.

Here's a prototype example of how it could be implemented using GDI:

private Point? lastSelected;
private Dictionary<Point, string> renderedText = new Dictionary<Point, string>();

private Point LastSelected
{
    get
    {
        return (Point)lastSelected;
    }
}
private void Form1_Load(object sender, EventArgs e)
{
    this.MouseDown += Form1_MouseDown;
    this.KeyDown += Form1_KeyDown;
    this.Paint += Form1_Paint;
}

void Form1_Paint(object sender, PaintEventArgs e)
{
    foreach (KeyValuePair<Point, string> pair in renderedText)
{
        e.Graphics.DrawString(pair.Value, new Font("Arial", 12), Brushes.Black, 

pair.Key);
    }
   }

   void Form1_KeyDown(object sender, KeyEventArgs e)
   {
    if (lastSelected != null)
    {
        if (!renderedText.ContainsKey(LastSelected))
        {
            renderedText.Add(LastSelected, "");
        }
        renderedText[LastSelected] = renderedText[LastSelected] + e.KeyCode;
        this.Invalidate();
        }
    }

void Form1_MouseDown(object sender, MouseEventArgs e)
{
    lastSelected = e.Location;
}

Reply to comment:

The above code captures the location of the mouse when the user clicks on the form and saves it in the lastSelected variable. At each subsequent key press on the form the key pressed is appended to the string representing that location. Furthermore the strings are being rendered on the screen at the captured location in the paint. The strings are rendered using GDI+, which means that you don't need to worry about the length of the individual characters.

Note that for a real application storing the locations and strings via a hashtabel (dictionary in C#) is not a great idea. You should rather create a custom class or structure that will hold the information such as location, text ect. This will allow you to further improve the functionality by adding options for stuff like bolding, italic, font sizes and so on.

Qua
Oh this is awesome, I'm about to update my question, can you please take a look at it and tell me if I'm right in what I'm saying? I'd type it here, but it'll be too long and messy as a comment
lucifer
Edited to respond to your question.
Qua
Thank you very much for your help :) I am now trying to reduce the flickering, it's really bad flickering, like it's trying to jump out of the screen or something and attack me. But very much appreciated :-D
lucifer
At run-time : once the strings are rendered via GDI+, they are, of course, just a buch of "burned pixels" : not editable, you can't move them arond as "objects." Seems like a highly implausible scenario.
BillW
+2  A: 

You could simply draw a new TextBox on your Windows Form when the user clicks. The MouseClick event will expose all the properties you need to draw the textbox right where they click.

private void Form1_MouseClick(object sender, MouseEventArgs e)
{
    TextBox txtBox = new TextBox();
    txtBox.Location = new Point(e.X, e.Y);
    this.Controls.Add(txtBox);
    txtBox.Focus();
}

You could make the TextBox transparent or what not if you wanted to mask the fact that they're typing a normal TextBox.

Steve Danner
Thank you for this
lucifer
Note that TextBoxes do not have an Auto-Size property : at run-time how does the end user get a TextBox large enough (or small enough) to contain only the text the user typed. This requires creating an auto-resizing TextBox control which is doable, but not trivial.
BillW