|
Вопрос # 1 805/ вопрос открыт / |
|
Всем привет!
Наверняка многие пользуются Lingvo - довольно популярный словарь-переводчик. Так вот, в нём есть такая удивительная возможность: если зажать Ctrl и навести курсор на какой-либо текст, то появится окошко с переводом. Вопрос в следующем: как он это делает? Он читает текст практически отовсюду: из любого окна, любого элемента окна, заголовка окна - да откуда угодно. Как это реализовано? Как сделать нечто подобное? Кроме как распознавания скриншота части экрана ничего в голову не приходит. Но это очень сложный вариант и вряд ли там сделано именно так. Может у кого-то есть идеи?
 |
Вопрос задал: Sunshine (статус: Посетитель)
Вопрос отправлен: 7 августа 2008, 10:17
Состояние вопроса: открыт, ответов: 0.
|
Мини-форум вопроса
Всего сообщений: 7; последнее сообщение — 28 октября 2008, 18:28; участников в обсуждении: 3.
|
Вадим К (статус: Академик), 7 августа 2008, 11:25 [#1]:
там используются хуки. а в тако случае длл для хука находиться внутри каждого запущенного процесса. А если находишся внутри процесса, то это заметно упрощает задачу - теперь стают доступны многие функции (ваша длл стаёт как бы частью каждой программы).
После этого задача своиться к простым действиям
- узнать, что за окно под курсором,
- с помощью GetText или аналогов узять текст (для некоторых окон могут быть варианты. кнопка - это ведь в понимании Windows тоже окно).
- по координатам рассчитать какое именно слово выделил пользователь. В некоторых случаях это можно сделать только узнав размер шрифта и сделав ручную прорисовку в памяти. это самая сложная часть с всего этого (ну кроме собственно перевода)
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Sunshine (статус: Посетитель), 7 августа 2008, 12:03 [#2]:
А хуки на что именно?
Порядок запуска ведь не важен - можно сначала запустить браузер, потом Lingvo и всё равно будет работать. Как можно dll подцепить к работающей программе? Да и вообще я не совсем понял об этом "нахождении внутри процесса" - это уже получается внедрение в чужую память. Можно поподробнее?
|
|
Вадим К (статус: Академик), 7 августа 2008, 12:16 [#3]:
именно через хук и можно подцепить.
да, в результате длл будет находиться в каждом процессе. она может обращаться к памяти процесса. Но тут и проблема - на самом деле получается, что одновременно код длл исполняется в каждом процессе. И для того, что бы обмениваться данными между ними, надо уже использовать специальные средства.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Sunshine (статус: Посетитель), 7 августа 2008, 19:42 [#4]:
Как я понимаю, воплотить это самостоятельно практически нереально?
|
|
Вадим К (статус: Академик), 7 августа 2008, 23:50 [#5]:
всё реально. Просто взять текст с текущего элемента (окна, если корректней) просто. Сделаю маленький презентик. попробуйте следующий код.
type
// *********************************************************************//
// Interface: IAccessible
// Flags: (4432) Hidden Dual OleAutomation Dispatchable
// GUID: {618736E0-3C3D-11CF-810C-00AA00389B71}
// *********************************************************************//
IAccessible = interface(IDispatch)
['{618736E0-3C3D-11CF-810C-00AA00389B71}']
function Get_accParent: IDispatch; safecall;
function Get_accChildCount: Integer; safecall;
function Get_accChild(varChild: OleVariant): IDispatch; safecall;
function Get_accName(varChild: OleVariant): WideString; safecall;
function Get_accValue(varChild: OleVariant): WideString; safecall;
function Get_accDescription(varChild: OleVariant): WideString; safecall;
function Get_accRole(varChild: OleVariant): OleVariant; safecall;
function Get_accState(varChild: OleVariant): OleVariant; safecall;
function Get_accHelp(varChild: OleVariant): WideString; safecall;
function Get_accHelpTopic(out pszHelpFile: WideString; varChild: OleVariant): Integer; safecall;
function Get_accKeyboardShortcut(varChild: OleVariant): WideString; safecall;
function Get_accFocus: OleVariant; safecall;
function Get_accSelection: OleVariant; safecall;
function Get_accDefaultAction(varChild: OleVariant): WideString; safecall;
procedure accSelect(flagsSelect: Integer; varChild: OleVariant); safecall;
procedure accLocation(out pxLeft: Integer; out pyTop: Integer; out pcxWidth: Integer;
out pcyHeight: Integer; varChild: OleVariant); safecall;
function accNavigate(navDir: Integer; varStart: OleVariant): OleVariant; safecall;
function accHitTest(xLeft: Integer; yTop: Integer): OleVariant; safecall;
procedure accDoDefaultAction(varChild: OleVariant); safecall;
procedure Set_accName(varChild: OleVariant; const pszName: WideString); safecall;
procedure Set_accValue(varChild: OleVariant; const pszValue: WideString); safecall;
property accParent: IDispatch read Get_accParent;
property accChildCount: Integer read Get_accChildCount;
property accChild[varChild: OleVariant]: IDispatch read Get_accChild;
property accName[varChild: OleVariant]: WideString read Get_accName write Set_accName;
property accValue[varChild: OleVariant]: WideString read Get_accValue write Set_accValue;
property accDescription[varChild: OleVariant]: WideString read Get_accDescription;
property accRole[varChild: OleVariant]: OleVariant read Get_accRole;
property accState[varChild: OleVariant]: OleVariant read Get_accState;
property accHelp[varChild: OleVariant]: WideString read Get_accHelp;
property accHelpTopic[out pszHelpFile: WideString; varChild: OleVariant]: Integer read Get_accHelpTopic;
property accKeyboardShortcut[varChild: OleVariant]: WideString read Get_accKeyboardShortcut;
property accFocus: OleVariant read Get_accFocus;
property accSelection: OleVariant read Get_accSelection;
property accDefaultAction[varChild: OleVariant]: WideString read Get_accDefaultAction;
end;
function AccessibleObjectFromPoint(Pt: TPoint; var Acc: IAccessible; var Child: Variant): HRESULT;
stdcall; external 'OleAcc.dll' name 'AccessibleObjectFromPoint';
var
OldPoint: TPoint;
procedure TForm1.Timer1Timer(Sender: TObject);
var
P: TPoint;
A: IAccessible;
V: Variant;
begin
if GetCursorPos(P) and ((P.X <> OldPoint.X) or (P.Y <> OldPoint.Y)) then
begin
OldPoint := P;
if Succeeded(AccessibleObjectFromPoint(P, A, V)) then begin
Memo1.Lines.Text := A.accName[V];
Caption := A.accDescription[V];
end
else
Memo1.Lines.Text := ''
end
end;
Изучите код, у него есть большой потенциал.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Sunshine (статус: Посетитель), 12 августа 2008, 11:31 [#6]:
Да, действительно, довольно мощный код! Забирает текст из многих мест. Большое спасибо! Это уже многое!
|
|
lzt (статус: Посетитель), 28 октября 2008, 18:28 [#7]:
а не подскажите, как определить координаты и длинну/высоту, элемента, из которого берется текст.
то есть. взять эти величины и расчитать над какой БУКВОЙ находиться курсор.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|