Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

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

 
Павел   (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 вся ветка

Форум: "WinAPI";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.069 c
15-1335126602
Юрий
2012-04-23 00:30
2013.03.22
С днем рождения ! 23 апреля 2012 понедельник


2-1340780940
aka
2012-06-27 11:09
2013.03.22
Удаления пробелов в строке.


15-1332013809
V_a_d
2012-03-17 23:50
2013.03.22
PopupMenu


2-1330700037
German
2012-03-02 18:53
2013.03.22
МойДатаСет


2-1331669763
Очень злой
2012-03-14 00:16
2013.03.22
Свойство для поля array[0..20] of char





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский