2

i am trying to grab the selected text from the open form on a users machine. Currently i have tried using GetFocus which is defined as

    '[DllImport("user32.dll")]
    static extern int GetFocus();'

In the api it says - Retrieves the handle to the window that has the keyboard focus, if the window is attached to the calling thread's message queue. Which explains why my app can grab the selected text from a window thats part of my app, but not one thats external, like a pdf for example.

What alternative win32 method is available for me to use that would fit this purpose?

Thanks.

edit: this is the attempt at the moment

[DllImport("user32.dll")] static extern int GetFocus();

[DllImport("user32.dll")]
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId);

[DllImport("user32.dll")]
static extern int GetForegroundWindow();

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);


// second overload of SendMessage

[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);

const int WM_SETTEXT = 12;
const int WM_GETTEXT = 13;

private static string PerformCopy()
{
    try
    {
        //Wait 5 seconds to give us a chance to give focus to some edit window,
        //notepad for example
        System.Threading.Thread.Sleep(1000);
        StringBuilder builder = new StringBuilder(500);

        int foregroundWindowHandle = GetForegroundWindow();
        uint remoteThreadId = GetWindowThreadProcessId(foregroundWindowHandle, 0);
        uint currentThreadId = GetCurrentThreadId();

        //AttachTrheadInput is needed so we can get the handle of a focused window in another app
        AttachThreadInput(remoteThreadId, currentThreadId, true);
        //Get the handle of a focused window


        int focused = GetFocus();




        //Now detach since we got the focused handle
        AttachThreadInput(remoteThreadId, currentThreadId, false);

        //Get the text from the active window into the stringbuilder
        SendMessage(focused, WM_GETTEXT, builder.Capacity, builder);

        return builder.ToString();
    }
    catch (System.Exception oException)
    {
        throw oException;
    }
}
rik
  • 1,279
  • 4
  • 20
  • 29
  • You can't do this in full generality. Even if you can get hold of the window handle for the control with input focus (which is hard enough anyway), that window might be a custom window that doesn't respond to the standard windows messages for retrieving selection. For example Word uses its own custom control. What problem are you trying to solve? – David Heffernan Jul 01 '11 at 13:51
  • The user would currently manually enter the search term in the app window in the task tray. Ideally, where possible we wanted to try and simulate this process so that if they were reading our internal pdf scientific reports they could highlight a particular internal data item and search it with our system without manually copying and pasting. – rik Jul 01 '11 at 13:55
  • I don't think you have much chance of succeeding with your current approach. I'm pretty sure there's no single general purpose API for getting hold of the current selection. I believe this because each application can implement text selection in its own way. You could consider a clipboard listener. – David Heffernan Jul 01 '11 at 13:59
  • it doesnt have to work with all systems, i can accept showing a message box if it isnt possible :) – rik Jul 01 '11 at 14:00
  • I expect you won't get anywhere with either Word or Acrobat. What's left? – David Heffernan Jul 01 '11 at 14:01
  • ok! dam it! i will try and automate the control c then? is that the best move? – rik Jul 01 '11 at 14:03

3 Answers3

0

Check GetForegroundWindow.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Dan
  • 1,927
  • 2
  • 24
  • 35
0

I don't think you have much chance of succeeding with your current approach. I'm pretty sure there's no single general purpose API for getting hold of the current selection. I believe this because each application can implement text selection in its own way.

As an alternative solution you should consider using a clipboard listener. Listen for changes to the clipboard contents and whenever text is added you can suck it out of the clipboard and put it in your app's window.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

I think this is a job for UI Automation (the API screen readers use). Here's a post that get's the selected text in C#.

Community
  • 1
  • 1
agent-j
  • 27,335
  • 5
  • 52
  • 79