Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

как получить выделенный текст из активного окна?   Найти похожие ветки 

 
Павел   (2009-12-03 15:47) [0]

Приветствую.
Есть приложение (моё). Допустим, оно свёрнуто в трей и дожидается нажатия горячей клавиши. Есть окно какого-то другого приложения. Пользователь выделяет текст в этом окне и нажимает горячую клавишу, после чего моё приложение должно получить выделенный текст.
Вот, собственно, и вопрос: как получить этот текст?
Подскажите, в какую сторону думать :)


 
Игорь Шевченко ©   (2009-12-03 15:51) [1]

две тонны баксов хочешь ? ;)

способ один - посылать окну WM_COPY, читать из Clipboard то, что туда скопировалось.
способ два - посылать окну назатия клавиш Ctrl+C, читать из Clipboard то, что туда поместилось
способ три - присоединять поток активного окна к себе, читать из активного текст любым нравящимся способом.

Найдешь работающее решение - выложи сюда


 
Павел   (2009-12-03 16:47) [2]

при чем тут две тыщи?


 
Leonid Troyanovsky ©   (2009-12-03 17:51) [3]


> Игорь Шевченко ©   (03.12.09 15:51) [1]

> Найдешь работающее решение - выложи сюда

Я когда-то похожим пользовался.
Ну, конечно, это только для EDIT, а, скажем, RICHEDIT не пройдет,
бо "новые" контролы не маршаллят всякие EM_GETSEL.

В ярлыке делал горячую клавишу, f.e., ctrl-alt-z,
функция м.б. любой (я перекодировку делал).


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.


--
Regards, LVT.


 
Leonid Troyanovsky ©   (2009-12-03 18:02) [4]


> Павел   (03.12.09 15:47)  

> Вот, собственно, и вопрос: как получить этот текст?

Из произвольного контрола не получить.
OCR только.

--
Regards, LVT.


 
Павел   (2009-12-03 18:13) [5]

Может быть, действительно работать с буфером обмена?
Ведь если текст можно выделить, то и скопировать, как правило можно... :)
Уточню: мне нужен лишь голый текст, безо всякого форматирования. Буфер обмена для этих целей мне кажется наиболее подходящим пока.


 
DVM ©   (2009-12-03 18:46) [6]


> Из произвольного контрола не получить.

Если произвольный контрол использует DrawText или TextOut, то не все так безнадежно, мне кажется. Но все равно непросто.


 
Игорь Шевченко ©   (2009-12-03 19:58) [7]

Павел   (03.12.09 16:47) [2]


> при чем тут две тыщи?


Предлагали за подобную задачу


 
Игорь Шевченко ©   (2009-12-03 20:00) [8]

Leonid Troyanovsky ©   (03.12.09 17:51) [3]

Надо для любого окна, в котором можно выделить текст (например, на странице, открытой в произвольном браузере).

Я сделал в свое время для Edit/Richedit, через OpenOffice не прорвался, ну и через произвольный браузер тоже :)


 
Павел   (2009-12-04 13:31) [9]

Вот есть такой вот вариантик, и даже работает:

Procedure TRuForm.WMHotkey( Var msg: TWMHotkey );
var happ: HWND;
 Begin
  if msg.HotKey=2 then
   begin

sleep(300);

keybd_event(VK_CONTROL,0,0,0);
keybd_event ($43, 0, 0, 0 ); //Send the C key (43 is "C")
keybd_event ($43, 0, KEYEVENTF_KEYUP, 0);
keybd_event (VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);// "Left Control Up

sleep(300);
ClipBoard:=TClipBoard.Create;
ShowMessage(ClipBoard.AsText);
ClipBoard.Destroy;

  end;
 End;


Очень странно, что без двух вызовов sleep не работает, буфер пуст.
Такое чувство, что буфер формируется далеко не быстро (считайте сами: 300+300=600 миллисекунд)
Кто-нибудь поделится мыслями, отчего так?


 
clickmaker ©   (2009-12-04 13:33) [10]

> Очень странно, что без двух вызовов sleep не работает, буфер
> пуст.

буфер-то заполняется в другом потоке и даже в другом процессе.
Вполне вероятно, что твой поток успевает проскочить до ClipBoard.AsText


 
Игорь Шевченко ©   (2009-12-04 16:05) [11]


> Кто-нибудь поделится мыслями, отчего так?


SendMessageTimeout (чужое_окно, WM_NULL, ...) не поможет засинхронизироваться ? (Сам не пробовал, на уровне предположений)


 
Павел   (2009-12-06 19:27) [12]

Я не понимаю, как оно может тут помочь? :)


 
Игорь Шевченко ©   (2009-12-06 20:27) [13]

Павел   (06.12.09 19:27) [12]

Ну вроде как ты ждешь, пока другое окно не среагирует на твое сообщение. То есть, подразумевается, что на комбинацию клавиш "запихнуть в клипбоард" оно к тому времени уже среагировало


 
Павел   (2009-12-07 00:50) [14]

Игорь, поясните, пожалуйста, на примере, как тут можно применить SendMessageTimeout. Я реально не понимаю :)

Если что, хэндл чужого окна у меня есть.


 
Игорь Шевченко ©   (2009-12-07 02:03) [15]


> Игорь, поясните, пожалуйста, на примере, как тут можно применить
> SendMessageTimeout.


Не помогает (я все-таки попробовал). А Sleep помогает


 
Eraser ©   (2009-12-07 18:12) [16]

можно подвязать синхронизация на clipboard change notifications. и для защиты добавить выход, если событие не пришло в течение, допустим, 3 секунд.



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.051 c
15-1343545365
megavoid (other pc)
2012-07-29 11:02
2013.03.22
Синхронизация и гонки потоков


15-1344231937
картман
2012-08-06 09:45
2013.03.22
извините, пожалуйста, забыл


15-1329835501
Pavia
2012-02-21 18:45
2013.03.22
Максимально выделить память


1-1298972588
rxQ
2011-03-01 12:43
2013.03.22
Положение объекта в rxRichEdit


2-1339141857
Александр_2012
2012-06-08 11:50
2013.03.22
Об управлении монитором