Опишу, что мне надо: надо, что бы при нажатию на комбинацию клавиш моя прога, которая раньше сидела в трее (можна даже без трея, просто чтобы она могла среагировать на нажатия клавиш. Вроде хук для этого надо ставить...), могла проанализировать код поточной Html страницы в браузере( Internet Explorer), вытянуть нужные ссылки, и скинуть в буфер обмена, реализованный в предыдущей теме . Трей и хуки можно оставить на потом, а сейчас же хотелося бы разобраться с браузером. Основная сложность это узнать Html. Я знаю, что все просматриваемое в браузерах сохраняется на винд, но определить, где он сохраняет все эти данные невозможно, так как Internet Explorer постоянно генерирует новые папки в Temporary Internet Files - система безопасности. Честно говоря, я просто не знаю куда тыкаться и что для этого надо знать. Может меня спасет WinApi? Покажите, пожалуйста, мне путь.
Сообщение отредактировано: Bokul -
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Ты при нажатии клавиш хочешь получить ссылки из IE, со страницы, которая СЕЙЧАС там отображается? Или со страниц, которые БЫЛИ до этого, и еще не обработаны?
Чтобы не возникло путаницы уточню: например, я зашел на сайт для скачки фильма, филь поделен на много частей. На каждую часть есть своя ссылка, так вот мне надо чтобы моя прога просто забирала все эти ссылки. Я уже сделал первую версию проги, но для ее работы мне надо было сохранять страницу на диск, а потом ей передавать путь к сохраненному файлу. Результат она сохраняет в вот таком виде ( теперь просто копирует в ClipBoard).
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
FPC умеет работать с OLE? Умеет... Вот этот Дельфийский код выдирает все линки из страницы, переданной в objIE.Navigate... Как захватить текущую страницу IE написано в DRKB, если надо приведу код, получающий активные URL-ы ВСЕХ открытых на данный момент копий Internet Explorer... Переводишь код на FPC и вешаешь программу в Tray
var objIE:OleVariant; procedure TForm1.Button11Click(Sender: TObject); var i:integer; begin try objIE := CreateOLEObject('InternetExplorer.Application'); objIE.Visible := 0; objIE.Navigate( 'http://www.google.com/'); while objIE.Busy do sleep(200); for i := 0 to objIE.document.links.length - 1 do Memo1.Lines.add(objIE.document.links.Item(i)) finally objIE := unassigned; end; end;
Как захватить текущую страницу IE написано в DRKB, если надо приведу код, получающий активные URL-ы ВСЕХ открытых на данный момент копий Internet Explorer...
Надо! Надо! Надо!
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Ага... Список всех линков, которые там содержатся...
Цитата(Bokul @ 16.09.2006 22:39)
Надо! Надо! Надо!
Ну, если надо, то вот тебе версия для FPC... Запусти несколько окон IE (лучше - чтоб они были с разными страничками, для проверки работоспособности), и запусти это:
{$mode DELPHI} uses windows;
function EnumIEChildProc(AHandle: hWnd; AnObject: TObject): BOOL; stdcall; var theClassName: string; Text: array [0..255] of Char; begin Result := True; SetLength(theClassName, 256); GetClassName(AHandle, PChar(theClassName), 255); if Pos('Edit', theClassName) > 0 then begin SendMessage(AHandle, WM_GETTEXT, SizeOf(Text), Longint(@Text)); if text<>'' then writeln(Text); end; end;
function IEWindowEnumProc(AHandle: hWnd; AnObject: TObject): BOOL; stdcall; var theClassName: string; Text: array [0..255] of Char; begin Result := True; SetLength(theClassName, 256); GetClassName(AHandle, PChar(theClassName), 255); if Pos('IEFrame', theClassName) > 0 then EnumChildWindows(AHandle, @EnumIEChildProc, longInt(0)) end;
begin EnumWindows(@IEWindowEnumProc, LongInt(0)); end.
Насчет переноса Дельфи-кода под FPC, скорее всего должно откомпилироваться без изменений, только вывод делать не на VCL-контролы, а в консоль... Я чуть попозже попробую, скажу что получилось
Запусти несколько окон IE (лучше - чтоб они были с разными страничками, для проверки работоспособности), и запусти это:
Запустить, то я запустил, даже получил правильный результат, но разобраться во всем этом . Как все это работает, понять одному мне, наверное, не под силам... Ух, вопросов выше крыши... Давайте по порядку: Что делает функция?
Цитата
function EnumIEChildProc(AHandle: hWnd; AnObject: TObject): BOOL;
Цитата
stdcall;
А это нужно, чтобы потом можна было вызывать функцию, как параметр?
Цитата
GetClassName(AHandle, PChar(theClassName), 255);
Тут мы, наверное, получаем класс окна... а вот какого окна и что такое клас для меня осталось загадкой... AHandle тоже константа? На что она указывает?
А эта функция и является основной, да? С ее помощью мы наверное и получаем адрес поточной страницы? Кому мы посылаем сообщения? Самому себе? WM_GETTEXT - неужели тоже константа? Даже в могущественном msdn не написано, какие другие значения могут быть на его месте. Longint знаю есть такой тип переменной, но чтобы функция... Ну а загадочный знак '@' ,вообще выше моего понимания.
Цитата
Я чуть попозже попробую, скажу что получилось
Будем ждать.
P.S Volvo, надеюсь у тебя хватет терпения, чтобы не послать меня подальше...
Сообщение отредактировано: Bokul -
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
А, теперь я понял сам принцип, но только принцип - детали остаются тайной, работы проги: С помощью EnumWindows мы проходим все родительские окна, если они проходят проверку if Pos('IEFrame', theClassName) ( так мы проверяем является ли это окно окном IE?), мы проходим через все дочерние окна с помощью EnumChildWindows и снова выполняем проверку if Pos('Edit', theClassName) > 0 then ( а что этим проверяется...), при успешной проверке, выполняем это SendMessage(AHandle, WM_GETTEXT, SizeOf(Text), Longint(@Text)); if text<>'' then writeln(Text);
Правильно? Если да, то это не совсем то, что нужно. Мне надо найти только поточное окно IE, а не все.
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
function EnumIEChildProc(AHandle: hWnd; AnObject: TObject): BOOL;
Смотри... Есть в WinAPI такая функция: EnumChildWindows она получает одним из параметров так называемую CallBack функцию (функцию обратного вызова), и EnumIEChildProc как раз и подставляется как CallBack Function в эту самую EnumChildWindows...
То же самое, кстати, и с EnumWindows ... Ей тоже нужна CallBack Function, и эту роль выполняет IEWindowEnumProc
Цитата(Bokul @ 16.09.2006 23:58)
А это нужно, чтобы потом можна было вызывать функцию, как параметр?
Не совсем...
Цитата(DRKB)
Соглашения о вызовах Директива stdcall Параметры помещаются в стек слева направо. Очистка стека осуществляется вызываемой процедурой. Этот вызов обеспечивает обработку фиксированного числа параметров.
Цитата(Bokul @ 16.09.2006 23:58)
Тут мы, наверное, получаем класс окна... а вот какого окна и что такое клас для меня осталось загадкой... AHandle тоже константа? На что она указывает?
Функции, начинающиеся с Enum... - функции перечисления, то есть действия свои они производят над ВСЕМИ объектами, являющимися ... Как бы это сказать, второй частью названия, что-ли... Если EnumWindows, то над всеми окнами, если EnumСhildWindows, то над всеми дочерними окнами, и т.д.
А AHandle - это передаваемый системой в функцию перечисления Enum... хендл объекта, чтоб с ним (с объектом) можно было работать...
Цитата(Bokul @ 16.09.2006 23:58)
Что мы определяем с его помощю 'Edit'?
Как что? Адресная строка Internet Explorer-а - не что иное, как Edit, и если в имени класса дочернего окна найден 'Edit', то все, забрать оттуда текст, это и будет адрес страницы, отображенной в данный момент в одной из копий IE...
Цитата(Bokul @ 16.09.2006 23:58)
А эта функция и является основной, да? С ее помощью мы наверное и получаем адрес поточной страницы? Кому мы посылаем сообщения? Самому себе?
Это как раз та функция, которая реализует механизм отправки сообщения... Только почему же "самому себе"? Тому объекту, который имеет хендл AHandle... Мы же нашли, что в его имени класса есть Edit, то есть это - адресная строка...
Цитата(Bokul @ 16.09.2006 23:58)
WM_GETTEXT - неужели тоже константа? Даже в могущественном msdn не написано, какие другие значения могут быть на его месте.
Тоже константа... Одна из нескольких тысяч... Я же говорил, что в MSDN все равно придется лазить, что ты ответил?
Цитата(Bokul @ 16.09.2006 23:58)
Longint знаю есть такой тип переменной, но чтобы функция...
А это не функция... Приведение типа... Все параметры должны быть строго того типа, который описан в заголовке, а ноль - он и как байт "ноль", и как Integer - "ноль", и как LongInt - тоже ноль... Вот и указывем, что ЭТОТ НОЛЬ - трактовать именно как имеющий тип LongInt...
Цитата(Bokul @ 16.09.2006 23:58)
Ну а загадочный знак '@' ,вообще выше моего понимания.
Операция взятия адреса?
Вроде, на все вопросы постарался ответить?
Цитата
Мне надо найти только поточное окно IE, а не все.
Что в твоем понимании "поточное окно"? И откуда я знаю, какой у него заголовок... Найду через FindWindow, а это будет другое... И все, некорректная работа программы?
Спасибо, volvo. Не знаю сколько пришлось бы перечитать, чтобы все понять самому.
Цитата
что в MSDN все равно придется лазить
Да я и лажу, а найти не могу.
Цитата
что ты ответил?
ну так это мой первый проект вне доса
Цитата
Вроде, на все вопросы постарался ответить?
Почти, вот этот забыл:
Цитата
что такое клас для меня осталось загадкой
Цитата
Это как раз та функция, которая реализует механизм отправки сообщения
А для чего вообще нужны сообщения? И конкретно в данном случае?
Цитата
if Pos('IEFrame', theClassName) ( так мы проверяем является ли это окно окном IE?)
Значит я прав?
Цитата
Что в твоем понимании "поточное окно"? И откуда я знаю, какой у него заголовок... Найду через FindWindow, а это будет другое... И все, некорректная работа программы?
Поточное - то, что я ввижу перед собой. То есть мне надо брать ссылки не со всех окон IE, а только с этого, ведь ссылки на фильм находятся только на нем...
Сообщение отредактировано: Bokul -
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
А для чего вообще нужны сообщения? И конкретно в данном случае?
Вообще - это основной механизм обмена информацией между приложениями Windows... А в данном случае - это единственный правильный способ получить содержимое контрола чужого приложения.
Цитата
Поточное - то, что я ввижу перед собой. То есть мне надо брать ссылки не со всех окон IE, а только с этого
Смотри на картинки... И в первом, и во втором случае я вижу перед собой почти одно и то же. Но с точки зрения системы - это СОВЕРШЕННО разные ситуации, и если в одном случае я бы мог воспользоваться GetActiveWindow, то в другом без EnumWindows не обойтись...
Цитата
что такое клас для меня осталось загадкой
Смотри здесь: "DRKB -> Системные функции и WinAPI -> Delphi и Windows API (Статья)" ... Там есть объяснение основ работы с WinAPI.
Проблемы пришли оттуда, откуда их меньше всего ждали... Как, впрочем, и всегда...
FPC отказывается работать с OLE. Напрочь. Не хочет, и все тут. Так что, вместо того компактного кода, который я приводил, придется делать одно из двух: 1) либо писать DLL на Дельфи, которая будет вытягивать линки из нужной странички так, как я показал в посте №4, и сохранять их в файл, а потом уже через FPC открывать файл и делать с линками все, что захочется 2) либо по заголовку (или через EnumWindows) находить хендл окна, и пытаться запустить сохранение странички на диск через меню этого окна (это сопряжено с дополнительными трудностями, например, как заставить страничку сохраняться туда, куда НАМ нужно, чтоб потом не рыскать по всем дискам в ее поисках; если все же удастся заменить директорию для сохранения в нее странички - то ее же надо еще и назад вернуть, а то как-то нехорошо получится...)
Смотри на картинки... И в первом, и во втором случае я вижу перед собой почти одно и то же. Но с точки зрения системы - это СОВЕРШЕННО разные ситуации, и если в одном случае я бы мог воспользоваться GetActiveWindow, то в другом без EnumWindows не обойтись...
Может я не понимаю полностью EnumWindows... Вот, например, я зашел на сайт и открыл 5 окон с разными фильмами, но прочитав краткое содержания о каждом, захотел скачать только один. Окно с ним остается перед моими глазами - активное, другие окна с оставшимся 4 фильмами не закрыты. Так вот, EnumWindows позволяет найти только этот фильм? Если да, то никаких проблем. А по-поводу GetActiveWindow и второй картинки - если окно с IE не активное, то можно вывести сообщение о этом. Вопрос другой - когда я буду вызывать свою прогу, сидящею в трее, по комбинации клавиш, какое приложения будет активное? Моя программа или IE? И еще один вопрос - можно ли сделать так, чтобы прога не имела своего окна, только иконку в трее?
Цитата
1) либо писать DLL на Дельфи, которая будет вытягивать линки из нужной странички так, как я показал в посте №4, и сохранять их в файл, а потом уже через FPC открывать файл и делать с линками все, что захочется ----------------------------- Я бы выбрал первый вариант...
Пусть будет первый, я только за. Но Дельфи не знаю, DLL писать не умею. Дельфи 7 есть в наличие.
Цитата
Смотри здесь: "DRKB -> Системные функции и WinAPI -> Delphi и Windows API (Статья)" ... Там есть объяснение основ работы с WinAPI.
Прочитал. Кидайте еще инфу по теме: про DLL, WinAPI и т.п.
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Нет... EnumWindows будет искать ВСЕ копии Internet Explorer-а, которые запущены... Значит, придется делать GetActiveWindow...
Цитата(Bokul @ 17.09.2006 18:20)
Вопрос другой - когда я буду вызывать свою прогу, сидящею в трее, по комбинации клавиш, какое приложения будет активное? Моя программа или IE?
Есд=ли программа будет активизироваться, НЕ показывая своего окна, или показывая его, но не делая активным, то активным останется то, что и было ранее, т.е. IE...
Цитата(Bokul @ 17.09.2006 18:20)
И еще один вопрос - можно ли сделать так, чтобы прога не имела своего окна, только иконку в трее?
Можно, только на самом деле это НЕ "прога не имеет окна, а только иконку", а "программа имеет окно (если этого не будет, она просто не запустится под Windows), и держит его невидимым, и иконку в трее"
А теперь - по поводу первой фразы этого сообщения... Попробовал я сделать DLL, и... Не работает это из консольного режима... Т.е. тебе придется писать программу в оконном режиме, чтобы использовать DLL... Я даже проверил программу в Дельфи без DLL, но в консоли, и это не работает. В принципе, ничего страшного, объем кода чуть увеличится, зато все преимущества Windows будешь использовать на полную катушку...
Теперь встречный вопрос... Если у тебя стоит D7, почему не пишешь на ней? Ты много теряешь, ибо OLE как ты видел - ОЧЕНЬ мощная штука (к сожалению, пока недоступная в FPC), меньше чем в 10 строк помещается процедура, выдирающая линки с любой страницы...
Теперь встречный вопрос... Если у тебя стоит D7, почему не пишешь на ней?
Боюсь я ее. Пару раз пробовал начинать программировать на ней, но то ли книги не те попадались( покажут как кнопочку ставить и сразу к базам данных), то ли я такой отм-ок, через недельку, две кидал я это занятия.
Цитата
Т.е. тебе придется писать программу в оконном режиме, чтобы использовать DLL
На Fpc?
Цитата
В принципе, ничего страшного, объем кода чуть увеличится, зато все преимущества Windows будешь использовать на полную катушку...
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Вот нашел в Drkb тему "Как добавить кнопку в панель инструментов IE?", подумал может это будет лучше чем HotKey, а может можна сделать то и то. Сейчас питаюсь перевести пример на Fpc. Вот сам пример:
Цитата
1. ButtonText = Всплывающая подсказка к кнопке 2. MenuText = Текст, который будет использован для пункта в меню "Сервис" 3. MenuStatusbar = *Ignore* 4. CLSID = Ваш уникальный classID. Для создания нового CLSID (для каждой кнопки) можно использовать GUIDTOSTRING. 5. Default Visible := Показать ей. 6. Exec := Путь к Вашей программе. 7. Hoticon := иконка из shell32.dll когда мышка находится над кнопкой 8. Icon := иконка из shell32.dll
Код
1 -------------------------------------------------------------------- procedure CreateExplorerButton; const TagID = '\{10954C80-4F0F-11d3-B17C-00C0DFE39736}\'; var Reg: TRegistry; ProgramPath: string; RegKeyPath: string; begin ProgramPath := 'c:\folder\exename.exe'; Reg := TRegistry.Create; try with Reg do begin RootKey := HKEY_LOCAL_MACHINE; RegKeyPath := 'Software\Microsoft\Internet Explorer\Extensions'; OpenKey(RegKeyPath + TagID, True); 2 -------------------------------------------------------------------- WriteString('ButtonText', 'Your program Button text'); WriteString('MenuText', 'Your program Menu text'); WriteString('MenuStatusBar', 'Run Script'); WriteString('ClSid', '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'); WriteString('Default Visible', 'Yes'); WriteString('Exec', ProgramPath); WriteString('HotIcon', ',4'); WriteString('Icon', ',4'); end 3------------------------------------------------------------ finally Reg.CloseKey; Reg.Free; end; end;
Как я понимаю в первой части кода проходит открытие ключа. Вот замена для Fpc:
Код
Var x:hWnd; begin RegOpenKey(HKEY_LOCAL_MACHINE,'Software\Microsoft\Internet Explorer\Extensions\{10954C80-4F0F-11d3-B17C-00C0DFE39736}\', x);
Не уверен в третьем параметре...
Во второй части мы модифицируем этот ключ с помощю TRegistry.WriteString, в WinApi этой функции, наверное, отвечает REGSETVALUE...? Аналог
Код
WriteString('ButtonText', 'Your program Button text');
для Fpc:
Код
RegSetValue(HKEY_LOCAL_MACHINE,'Software\Microsoft\Internet Explorer\Extensions\{10954C80-4F0F-11d3-B17C-00C0DFE39736}\','ButtonText',REG_SZ, 'Your program Button text');
Ну и закрываем ключ
Код
RegCloseKey(x);
Правильно?
Сообщение отредактировано: Bokul -
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
Я бы этого не делал... Понимаешь, в чем дело... Реестр - это очень уязвимое место, легко напортачить, и потом что будешь делать?
Я, кстати, набросал тут кое-что, посмотри, насколько отличается размер программы, и... Это уже полноценное Windows-приложение, кроме того не оставляющее кнопки на TaskBar-е и запихивающее иконку в трей... Правда, пока ничего кроме этого приложение делать не умеет, но с каждой строкой, добавленной в программу, она будет уметь все больше и больше...
Еще одна идея... У каждого приложения есть системное меню, так? Ну, то самое, что открывается при нажатии на иконку слева вверху... Можно попробовать сделать так: при загрузке своей программы внедрить в системное меню всех копии IE свой пункт, например, "Get Links", и при его выборе вызывать процедуру, которая будет делать всю работу... Это так, мысли вслух...
Я, кстати, набросал тут кое-что, посмотри, насколько отличается размер программы, и... Это уже полноценное Windows-приложение, кроме того не оставляющее кнопки на TaskBar-е и запихивающее иконку в трей... Правда, пока ничего кроме этого приложение делать не умеет, но с каждой строкой, добавленной в программу, она будет уметь все больше и больше...
Спасибо, только у меня нету модуля ShellApi . Это ж для Fpc?
Цитата
Еще одна идея... У каждого приложения есть системное меню, так? Ну, то самое, что открывается при нажатии на иконку слева вверху... Можно попробовать сделать так: при загрузке своей программы внедрить в системное меню всех копии IE свой пункт, например, "Get Links", и при его выборе вызывать процедуру, которая будет делать всю работу...
А насколько сложно будет сделать такое?
--------------------
Лао-Цзы : Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.