Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.208.72] |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Цитата Katerina1993 @ Работает, только первые две строчки не пойму для чего getAttribute и WideCharToString? Мне удалось запусить только через Elem.setAttribute. Первые две строчки это получение. Необходима дополнительная переменная типа WideString перед преобразованием кодировок. Свойство Caption у формы требует для установки строку в кодировке ANSI, а из интерфейса будет получен OleVariant. Присвоение его к строке нужного типа автоматически преобразует данные в строку WideString. А вот дальше из WideString надо руками преобразовать текст в ANSI путем вызова WideCharToString. Но в качестве параметра этой функции нужна строка типа PWideChar. Преобразовать сразу из OleVariant в PWideChar не так просто. Гораздо проще использовать дополнительную переменную, которая уже будет содержать исходные данные для перекодировки в ANSI. И уже в заголовке формы строка будет отображена в правильной кодировке символов. И третья строка изменяет значение свойства value на 'Send text!'. Но помните, что там тоже используются не String, а WideString и требуется соблюдать и преобразовывать кодировку текста. |
Сообщ.
#17
,
|
|
|
Ошибку выдает, на строке где Caption.
var Elem: IHTMLElement; Text: OleVariant; Caption : WideString; ..... Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); Цитата [Error] Unit1.pas(232): Variable required |
Сообщ.
#18
,
|
|
|
Так где вы это вызываете. Если вне метода основного окна программы, тогда используйте Form1.Caption
|
Сообщ.
#19
,
|
|
|
В процедуре вызываю:
procedure TForm1.Button4Click(Sender: TObject); var Elem: IHTMLElement; Text: OleVariant; Caption : WideString; begin try Elem := GetElementById(WebBrowser1.Document, 'title', 1, 'input') as IHTMLElement; // Поиск только среди ссылок if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; except end; end; |
Сообщ.
#20
,
|
|
|
Тогда зачем вам там переменная Caption?
procedure TForm1.Button4Click(Sender: TObject); var Elem: IHTMLElement; Text: WideString; begin try Elem := GetElementById(WebBrowser1.Document, 'title', 1, 'input') as IHTMLElement; // Поиск только среди ссылок if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; except end; end; |
Сообщ.
#21
,
|
|
|
Еще замечание по поиску элементов по классу. Я этого не делал, но значение className у элемента будет содержать не имя класса, а список классов через разделитель. Необходимо перечислять все классы при поиске или сделать разделение className на соответствующие классы и искать среди них. Как один из вариантов функцию можно организовать так
const constInvalidHTML = 'Invalid HTML document'; constInvalidHTMLStructure = constInvalidHTML + ' structure'; // Функция поиска элемента на странице с учетом тэга, индекса и имени идентификатора (id) или класса (className) // aDocument = WebBrowser.Document, // iNum = номер вхождения элемента в документ с таким ID (начинаются с 1), // sClassNameOrID = строка с именем класса начинающимся с точки // или строка с id (не должна начинаться с точки), // sTagName = имя тэга у элемента function QueryElement(const aDocument: IDispatch; iNum: LongInt = 1; const sClassNameOrID: String = ''; const sTagName: WideString = ''): IDispatch; function AnyID(const s1: String; const s2: String): Boolean; begin Result := True; end; function min(a, b: LongInt): LongInt; inline; begin if a < b then Result := a else Result := b; end; function PosDef(const aPattern: WideString; const aText: WideString; iDefault: LongInt): LongInt; begin Result := Pos(aPattern, aText); if Result = 0 then Result := iDefault; end; const aTabChar: WideString = ' '; aSpaceChar: WideString = #9; var Doc: IHTMLDocument2; Body: IHTMLElement2; Tags: IHTMLElementCollection; Tag: IHTMLElement; c, i, l, n, Count: LongInt; f, m: Boolean; w, s: WideString; comp: function (const s1: String; const s2: String): Boolean; begin f := False; Result := nil; if iNum < 1 then Exit; if (sClassNameOrID <> '*') and (sClassNameOrID <> '') then begin comp := @AnsiSameText; f := sClassNameOrID[1] = '.'; end else comp := @AnyID; if Supports(aDocument, IHTMLDocument2, Doc) then begin if Supports(Doc.body, IHTMLElement2, Body) then begin if sTagName = '' then Tags := Body.getElementByTagName('*') else Tags := Body.getElementsByTagName(sTagName); Count := Tags.length; c := 0; for i := 0 to Count - 1 do begin Tag := Tags.item(i, EmptyParam) as IHTMLElement; if f then begin // Если ищем по имени класса, тогда надо вручную // разбить строку className на составляющие и сравнивать имя класса отдельно для каждого класса у элемента m := False; // Флаг совпадения одного из классов w := Tag.className; // сохраняем значение в локальную переменную для изменения l := Length(w); // можно не буду описывать тривиальные действия while l > 0 do begin // цикл достижения конца строки (в строке не осталось имен классов) inc(l); // можно не буду описывать тривиальные действия // нахождение позиции ближайшего к началу строки разделителя имен классов n := min(PosDef(aSpaceChar, w, l), PosDef(aTabChar, w, l)); s := '.' + Copy(w, 1, n - 1); // копирование очередного имени класса в отдельную переменную // пропуск всех символов разделителей между именами (вместо этого можно воспользоваться trim после Delete, но так лучше) while (n < l) and ((w[n] = aSpaceChar) or (w[n] = aTabChar)) do inc(n); Delete(w, 1, n - 1); // Убираем из строки className очередное имя класса со всеми последующими разделителями l := Length(w); // можно не буду описывать тривиальные действия if comp(s, sClassNameOrID) then begin // Сравнение имен классов с именем в параметре m := True; // При совпадении устанавливаем флаг ... break; // ... и прерываем цикл по именам классов end; end; if m then inc(c); // Если флаг установлен, тогда совпадение найдено и просто увеличиваем счетчик совпадений end else if comp(Tag.id, sClassNameOrID) then inc(c); // тоже самое, но для id if c = iNum then begin // Счетчик совпадений равен индексу элемента из параметра Result := Tag; // Возвращаем этот элемент как найденный... break; // ... и прерываем цикл по элементам end; end; end else raise Exception.Create(constInvalidHTMLStructure + '!'); end else raise Exception.Create(constInvalidHTML + '!'); end; Я оставил комментарии в коде. Надеюсь они помогут вам исправить ошибки (особенно проверьте индексы). Добавлено Ну и примеры поиска элементов с её помощью procedure TForm1.Button4Click(Sender: TObject); var Elem: IHTMLElement; Text: WideString; begin try Elem := QueryElement(WebBrowser1.Document, 'title', 1) as IHTMLElement; // Поиск первого среди всех на странице по id if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '.submitbutton', 1) as IHTMLElement; // Поиск первого среди всех на странице по className if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, 'title', 5) as IHTMLElement; // Поиск пятого элемента среди всех на странице по id и индексу if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '.submitbutton', 3) as IHTMLElement; // Поиск третьего элемента по className и индексу if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, 'title', 1, 'input') as IHTMLElement; // Поиск только среди input по id if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '.submitbutton', 1, 'input') as IHTMLElement; // Поиск только среди input по className if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, 'title', 2, 'input') as IHTMLElement; // Поиск второго элемента только среди input по id и индексу if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '.submitbutton', 4, 'input') as IHTMLElement; // Поиск четвертого элемента только среди input по className и индексу if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '') as IHTMLElement; // Поиск первого элемента на странице по индексу (неявно) if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '*', 1) as IHTMLElement; // Поиск первого элемента на странице по индексу (явно) if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '', 3, '*') as IHTMLElement; // Поиск третьего элемента на странице по индексу (явно и с указанием маски тэгов) if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; Elem := QueryElement(WebBrowser1.Document, '*', 4, 'input') as IHTMLElement; // Поиск четвертого элемента только среди input по индексу if Assigned(Elem) then begin Text := Elem.getAttribute('value', 0); Caption := WideCharToString(@Text[1]); end; except end; end; |
Сообщ.
#22
,
|
|
|
macomics, Inline поддерживается начиная с delphi 2005, а у меня Delphi 7.
|
Сообщ.
#23
,
|
|
|
Цитата Katerina1993 @ macomics, Inline поддерживается начиная с delphi 2005, а у меня Delphi 7. Это не критично, если она будет не inline (просто уберите этот модификатор, я по привычке его использовал). У меня так вообще Lazarus на Linux и адаптировать под Delphi 7 c Internet Explorer бывает сложно. |