views:

879

answers:

6

In my c# .Net application, I've been trying to be able to retrieve the currently selected text in the currently focused window. (Note that it can be any window open in windows, such as word, or safari).

I'm able to retrieve the handle to the currently focused control. (Using a couple of interop calls to user32.dll, and kernel32.dll).

However, I've been unable to consistently be able to get back the selected text.

I've tried using SENDMESSAGE and GET_TEXT. However this only seems to work for some applications (works for simple applications like wordpad, doesn't work for more complex applications like firefox, or word).

I've tried using SENDMESSAGE and WM_COPY. However, again this only seems to work on some controls. (I would think that WM_COPY, would cause the exact same behaviour as manually pressing CTRL-C, but it doesn't).

I've tried using SENDMESSAGE and WM_KEYUP+WM_KEYDOWN to manually stimulate a copy command. BUt this doesn't constantly work either. (Perhaps of an overlap with the actual hotkey pressed by a user to invoke my applications).

Any ideas on consistently being able to retrieve the currently selected text ? (on any application).

+1  A: 

I don't believe that it is possible, the currently focused may not contain any selected text. (It may not even contain any text at all). Or the current selection could be an icon, or an image.

Perhaps requiring the user to copy the selected text to the clipboard first may be a solution.

Craig T
I am a sexy shoeless god of war!
Joel Coehoorn
In my case, I can assume that it's alway text selected.
vicjugador
@Joel: What the hell?
P Daddy
+1  A: 

I've possibly misunderstood the question, but could you just send Ctrl+c? If you know the window is always foremost and the text to be copied is selected?

SendKeys.SendWait("^c");

Once copied to the clipboard, it's not tricky to programatically retrieve the contents (you could even check it's actually text at that point).

Matthew Brindley
I tried this along with SENDMESSAGE KEYUP/KEYDOWN. It doesn't always work either. I think its an overlap of the keys. (i.e. user pressed down on some key combination to activate my program say ctrl-shift-p, ctrl-c is invoked by program, and keys up on ctrl-shift-p, and ctrlc isn't understood).
vicjugador
A: 

I think creating clipboard monitor is a good option. I suggest you to look at Klipper (KDE clipboard module), it copied everything you select in the clipboard list, either content is file, folder or some text.

More details can be found here.

Sharique
A: 

Hm... you find it to be easy? How come?

The best alternative to SendKeys.SendWait("^c"); I found was this one:

http://www.c-sharpcorner.com/Forums/ShowMessages.aspx?ThreadID=46203

However, it only works for a few apps, like notepad. For web browsers, it just crashes.

Anyone got anything better?

A: 

Try the GetWindowText() API on controls for which the other methods do not work.

SDX2000
+1  A: 

I managed to get text for wordpad/notepad and anything that supports UI automation.

The code below may work for you in some cases. I'm going to get a start on using Reflector to see how windows does it for textboxes in the TextBoxBase.SelectedText property.

public static string SelectedText
{
    get
    {
        AutomationElement focusedElement = AutomationElement.FocusedElement;

        object currentPattern = null;

        if (focusedElement.TryGetCurrentPattern(TextPattern.Pattern, out currentPattern))
        {
            TextPattern textPattern = (TextPattern)currentPattern;
            TextPatternRange[] textPatternRanges = textPattern.GetSelection();
            if (textPatternRanges.Length > 0)
            {
                string textSelection = textPatternRanges[0].GetText(-1);
                return textSelection;
            }
        }
        return string.Empty;
    }
    set
    {
        AutomationElement focusedElement = AutomationElement.FocusedElement;
        IntPtr windowHandle = new IntPtr(focusedElement.Current.NativeWindowHandle);
        NativeMethods.SendMessage(windowHandle, NativeMethods.EM_REPLACESEL, true, value);
    }
}
AndrewVos
Nice idea, although on my machine (Win 7) .. it doesn't work on .Net 3.5 WPF apps .. the windowHandle returned is always zero.
vicjugador