With regard to a thread posted on Friday "How to get selected text", I
need to do something similar. The scenario is:
The user highlights a certain portion of text in an active application
(say notepad, or word or anything really) and clicks on a button in my
app. My app copies the selected text and enters it into an edit control
in my app. My question is:
If I do not know the application or window name or even the type of
control (could be an edit or a memo or whatever) that the text is
highlighted in when the user clicks into my app, how can I pick it up?
Thank you in advance,
Chris O'Brien
Simple answer is, you can NOT!.
You could search for a window that has selected text, but then there
could be many windows that have selected text!.
(What is wrong with copy the selected text then paste into your app?)
--
Charles Hacker
Lecturer in Electronics and Computing
School of Engineering
Griffith University - Gold Coast
Australia
Thanks for your response.
> (What is wrong with copy the selected text then paste into your app?)
>
There is nothing wrong particularly, except that I am replacing an aged app
written by a 3rd party company that DOES in fact perform the functionality I
need.
It is basically a client that forces the telephone to dial a number (via a
CTI server). A user can highlight a number anywhere in any app and click on
the "Go" button in the 'client app'.
The client app then takes the highlighted number and feeds it to the CTI
server. The only part of the process I cannot do is the "getting the
selected text" part initially. It does appear to be possible, I just don't
know how. After talking to users, this is very high on their priority list.
Many thanks,
Chris O'Brien
I wrote little application for simple text formatting.
This app started by pressing a system hot key, f.e. "Ctrl+Alt+Z"
(shortcut properties settings) in focused edit control.
The application may to formate text for Notepad, Netscape & etc,
but not for Word.
--
WBR, LVT.
program prfxline;
uses
Windows,
Messages;
const
buflen = $FFFF;
procedure InsertPrefixToLines(EditHandle: HWND; const prefx: String);
var
i, idx : Longint;
Source : array [0..buflen] of Char;
Dest: array [0..buflen] of Char;
Sel, Len : DWord;
StartSel, EndSel: Word;
begin
Len := SendMessage( EditHandle,
WM_GETTEXT,
SizeOf(Source),
LParam(PChar(@Source[0])));
Sel := SendMessage( EditHandle,
EM_GETSEL,
0,
0);
StartSel := LoWord(Sel);
EndSel := HiWord(Sel);
if (StartSel = 0) and (EndSel = -1) then
EndSel:= Len;
if StartSel = -1 then
Exit;
move(prefx[1], Dest[0], Length(prefx));
idx := Length(prefx);
i:= StartSel;
while i < EndSel do
begin
case Source[i] of
#13:
begin
Dest[idx] := #13;
Dest[idx+1] := #10;
move(prefx[1], Dest[idx+2], Length(prefx));
inc(idx, Length(prefx)+2);
inc(i);
if Source[i] = #10 then
inc(i);
end;
else
begin
Dest[idx] := Source[i];
inc(idx);
inc(i);
end;
end;
end;
SendMessage(EditHandle, EM_REPLACESEL, WParam(True), LParam(PChar(@Dest[0])));
end;
const
prefix: String = ' ';
var
happ: HWND;
tid : DWord;
handles: array [0..0] of THandle;
begin
happ:= GetForegroundWindow;
tid := GetWindowThreadProcessID(happ, nil);
if ParamCount > 0 then
prefix := ParamStr(1);
MsgWaitForMultipleObjects(0, handles, false, 0, QS_POSTMESSAGE);
AttachThreadInput(tid, GetCurrentThreadID, true);
try
InsertPrefixToLines(GetFocus, prefix);
finally
AttachThreadInput(tid, GetCurrentThreadID, false);
end;
end.
The highlighted text is from another application, not inside my own. Yes, you
are right about the GO button, but I am not using the same CTI server or
component for client side development as it has proved very unreliable, so I am
using different CTI software entirely.
I had thought that if I could get the handle of the last window that was active
before the GO button (or equivalent) was clicked, I could then getvthe
highlighted text. A user will always want the number from the window they were
in when they clicked the GO button. If getting the previously active window is
possible, and then getting the highlighted text could be done, the solution is
found.
Not easy, I appreciate, but possible as it is already being done. Any
suggestions are most welcome, and I will update this NG as a solution is found.
Thanks,
Chris
Doug wrote:
--
O'Brien Systems Limited
http://www.obriensystems.com
"Creative Software ~ Applied Simplicity"
> I had thought that if I could get the handle of the last window that was active
> before the GO button (or equivalent) was clicked
Better follow Leonids suggestion and create a system wide shortcut. This
would enable you to react without activating your application, e. g.
without losing the focus on the 'other' application.
If you still want to use a button, you can get the previous application
in most (but not all) cases like that:
My first attempt was to catch the WM_ACTIVATEAPP message which should
deliver the thread ID of the deactivated application. But it always
brings up 0, so it's useless.
Assuming that the active window of the 'other' application is not
topmost. Assuming further that _your_ application window is not topmost.
Start enumerating windows on desktop.
Repeat until you find your window.
Now, repeat until you find a window belonging to some other app.
With some luck, this is the window you are after.
That's what I tried, it works for Delphi, Word and some othe
applications. It doesn't work for Explorer and Netscape, but this should
be fixable.
procedure TForm1.WMActivateApp(var Msg: TWMActivateApp);
var
W: HWND;
PrID: Cardinal;
begin
if Msg.Active then begin
FLastActiveWnd := 0;
W := GetWindow(GetDesktopWindow, GW_CHILD);
while (W <> 0) and (W <> Handle) do
W := GetWindow(W, GW_HWNDNEXT);
while W <> 0 do begin
GetWindowThreadProcessId(W, @PrID);
if PrID <> GetCurrentProcessId then begin
FLastActiveWnd := W; //GetLastActivePopup(W);
break;
end;
W := GetWindow(W, GW_HWNDNEXT);
end;
end;
inherited;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
S: Array[0..255] of Char;
begin
if FLastActiveWnd <> 0 then begin
GetWindowText(FLastActiveWnd, S, 255);
ShowMessage('last active: ' + S);
end else begin
ShowMessage('nothing found');
end;
end;
> , I could then getvthe highlighted text.
If you don't know anything about the window, it's hard to get the text.
The only simple things I can think are (1) to find a way to get the
highlighted text for some popular applications like Notepad, Wordpad,
Word, etc., or (2) to PostMessage a WM_COPY to the focused control. Be
aware that (2) will destroy the clipboard content which I think is a
property of the user.
BTW, how would you get a telephone number written in MS Paint?
BTW2, AFAIK the popular 'Babylon' translator uses onscreen OCR to get
the highlighted text.
However, good luck.
-Michael
Thank you very, very much for your help. I will give it a go and let you know how I
get on.
Best regards,
Chris O'Brien