-2

I'm writing this code to select some lines of text from another application ( process ) but the problem is that i can't handel to this application and get the selected text the text selected perfectly but can't copy this text , is there any way to simulate Ctrl+C command in delphi ? THis is my code

    SetCursorPos(300, 300);
  mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
  SetCursorPos(300, 350);
  mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
  if not AttachThreadInput(GetCurrentThreadId,
    GetWindowThreadProcessId(GetForegroundWindow), true) then
    RaiseLastOSError;
  try

    SendMessage(GetFocus, WM_GETTEXT, 0, 0);
    lookup_word := clipboard.astext;
    CurvyEdit1.Text := lookup_word;
  finally
    AttachThreadInput(GetCurrentThreadId,
      GetWindowThreadProcessId(GetForegroundWindow), false);
  end;
Oussaki
  • 1,449
  • 2
  • 21
  • 30
  • WM_gettext should copy text to clipboard? Why do u think so? For clipboard other message is used. – Prog1020 Jul 11 '13 at 22:10
  • I don't know but let focus in the first problem that always an exception raised if not AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true) then RaiseLastOSError; – Oussaki Jul 11 '13 at 22:28
  • Your question doesn't ask about `AttachThreadInput` or an exception. It asks about `WM_GETTEXT` or simulating `Ctrl+C`. If you have a separate question about `AttachThreadInput`, post it as a separate question. – Ken White Jul 11 '13 at 22:40
  • @ken white and if you see my question is not just asking about WM_GETTEXT it also about simulation Ctrl+C using code ^^ . – Oussaki Jul 11 '13 at 22:41
  • And that's exactly what I said. It's not asking about `AttachThreadInput` (which is also what I said). Your comment to Alextp said "let focus in the first problem that always an exception raised if not AttachThreadInput`, which is **NOT** what your question asks. Don't change the question after you've received answers to it. – Ken White Jul 11 '13 at 22:43
  • 2
    You have **at least** four problems here: (1) You're calling AttachThreadInput to [link your thread's message queue to who-knows-where](http://blogs.msdn.com/b/oldnewthing/archive/2013/06/19/10426841.aspx). (2) You're passing a null pointer to `wm_GetText`. (3) You're sending `wm_GetText` with the inexplicable expectation that it has anything to do with copying things to the clipboard. (4) You're attempting to use the clipboard for inter-process communication. What do you *want* to do? – Rob Kennedy Jul 11 '13 at 22:54

3 Answers3

5

WM_GETTEXT retrieves the actual text directly, it does not put the text on the clipboard. WM_COPY does that instead. When using WM_GETTEXT, you must provide a character buffer for the text to be copied into. You are not doing that.

So either use WM_GETTEXT correctly:

var
  lookup_word: string;
  Wnd: HWND;
  Len: Integer;

lookup_word := '';

Wnd := GetFocus;
if Wnd <> 0 then
begin
  Len := SendMessage(Wnd, WM_GETTEXTLENGTH, 0, 0);
  if Len > 0 then
  begin
    SetLength(lookup_word, Len);
    Len := SendMessage(Wnd, WM_GETTEXT, Len+1, LPARAM(PChar(lookup_word)));
    SetLength(lookup_word, Len);
  end;
end;
CurvyEdit1.Text := lookup_word;

Or else use WM_COPY instead:

SendMessage(GetFocus, WM_COPY, 0, 0);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Okay thanks, but it not working fine when i want to copy from another application like note pad . i mean ( WM_COPY ) – Oussaki Jul 11 '13 at 22:50
  • 4
    `Wm_Copy` causes the *selected* text to be copied to the clipboard. Oussaki, you appear to be attempting to move the mouse. Does that actually cause the text in Notepad to be selected? If not, then stop focusing on copying and get selection to work first. Better yet, stop trying to use the clipboard for something it's not intended for. (Instead, send `wm_GetText` to directly get the text and leave the clipboard alone. The clipboard is meant to be populated exclusively by the user, never automatically by a program.) – Rob Kennedy Jul 11 '13 at 23:00
  • If you want to copy just a selection of text without using the clipboard, use the `WM_GETTEXT` message to retrieve the entire text first, then use the `EM_GETSEL` message to know which portion of the text was selected so you can copy that portion out of the buffer. This is exactly what the `TCustomEdit.SelText` property getter does internally, for instance. – Remy Lebeau Jul 11 '13 at 23:15
1

Try sending a WM_COPY message to the target window (edit control) handle.

1

It works fine. You've indicated you're working with Notepad in your other related question - this will retrieve all text from a running instance of Notepad (the first it finds!) and put it into a TMemo on a Delphi form. Tested in Delphi 2007 on Windown 7 64-bit.

procedure TForm1.Button3Click(Sender: TObject);
var
  NpWnd, NpEdit: HWnd;
  Buffer: String;
  BufLen: Integer;
begin
  Memo1.Clear;
  NpWnd := FindWindow('Notepad', nil);
  if NpWnd <> 0 then
  begin
    NpEdit := FindWindowEx(NpWnd, 0, 'Edit', nil);
    if NpEdit <> 0 then
    begin
      BufLen := SendMessage(NpEdit, WM_GETTEXTLENGTH, 0, 0);
      SetLength(Buffer, BufLen + 1);
      SendMessage(NpEdit, WM_GETTEXT, BufLen + 1, LParam(PChar(Buffer)));
      Memo1.Lines.Text := Buffer;
    end;
  end;
end;
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • **FIX**: The second `SendMessage()` call should be: `SendMessage(NpEdit, WM_GETTEXT, BufLen + 1, LParam(PChar(Buffer)));` –  Feb 24 '21 at 06:02