Tuesday, March 01, 2011

How ScratchPad does copy and paste ... [#wp7dev]

In response to public demand I'm going to explain how I got Scratch Pad (my Windows Phone 7 app which supports cut 'n' paste and a shared clipboard API) to work.

This is the first of 2 posts on the subject. In this post I'm going to explain how I manipulate the text to create cut and paste within the app. In the next I'll show how I created a shared clipboard. And how you can add the functionality to your own apps too!

The cutting, copying and pasting of text within an app is simple really. It basically involves storing a copy of the text in question in a string variable within the code.

private string localClipboard;

To be able to select more than a single word, the code supports a "shift" mode:

private bool shiftSelected;

private int shiftSelectPositionStart;

private int shiftSelectPositionLength;

private void ShiftClick(object sender, EventArgs e)
    shiftSelected = !shiftSelected;

    shiftSelectPositionStart = tb.SelectionStart;
    shiftSelectPositionLength = tb.SelectionLength;

Which can be combined with a SelectionChanged event on the text to capture the larger string. (Being sure to consider if the new selection point is before or after the original/previous selection.)

private void SelectionChanged(object sender, RoutedEventArgs e)
    var currentStart = tb.SelectionStart;
    var currentLength = tb.SelectionLength;

    if (shiftSelected)
        if (shiftSelectPositionStart < currentStart)
            tb.SelectionStart = shiftSelectPositionStart;
            tb.SelectionLength = currentStart - shiftSelectPositionStart + currentLength;
            tb.SelectionStart = currentStart;
            tb.SelectionLength = shiftSelectPositionStart - currentStart + shiftSelectPositionLength;

    shiftSelected = false;
Copying text is easy:
private void CopyClick(object sender, EventArgs e)
    this.localClipboard = tb.SelectedText;
But cutting text is slightly more complicated as we need to replace the original string with the text before and after the selection.
private void CutClick(object sender, EventArgs e)
    this.localClipboard = tb.SelectedText;

    var removeAt = tb.SelectionStart;

    var afterCut = tb.Text.Substring(removeAt + tb.SelectionLength);

    var beforeCut = tb.Text.Substring(0, removeAt);

    tb.Text = beforeCut + afterCut;

    tb.SelectionStart = beforeCut.Length;
Then that just leaves pasting the text back in at a newly selected location.
private void PasteClick(object sender, EventArgs e)
    var insertAt = tb.SelectionStart;

    tb.Text = tb.Text.Substring(0, insertAt) +
              this.localClipboard +
              tb.Text.Substring(insertAt + tb.SelectionLength);

    tb.SelectionStart = insertAt + this.localClipboard.Length;
    tb.SelectionLength = 0;
The above also selects the newly pasted string. Simples! Now, while you digest all that, please head on over to http://www.wp7comp.com/scratch-pad/ and leave some lovely comments - Thanks.


  1. Anonymous1:33 am

    is it possible to get text from Webpage ?

    I would like to make a browser by using C# that is able to get selected text and automatically show the selected text in textbox.
    I also tried using JavaScript to make function that copys and pastes text from webpag.

    finally, I figured out that I cannot do!
    If you have any idea to solve this problem, please let me know.
    I need your wonderful technique.
    I need you. please help me!

    PS. I am using now:
    viusal stdio 2010 express for windows phone
    windows phone SDK7.1

    thank you.


  2. @Samurai
    Assuming that you're just using an embedded browser control in your app then I don't believe it's possible to get any selected text as there are no APIs availabel to provide it.
    If you really must get at the selected text in rendered HTML you'll need to display it yourself but I can't imagine the use case which would justify the amount of work that would be needed to do that across arbitrary sites.


I get a lot of comment spam :( - moderation may take a while.