На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Как сделать автоматическое нажатье по ссылке в окне браузера?
    Написала программу для открытия страниц браузера. В боковой панели сделала вывод информации о dom-элементах. Чтобы открыть ссылку нужно по ней щелкнуть. Если навести мышкой и посмотреть в панели то атрибут id равняется test. Gif пример работы программы ниже.
    user posted image
    Подскажите можно как-нибудь по id найти в документе html и заставить нажать по ссылке автоматически.

    В своей программе я подключаю дополнительные файлы.
    Цитата

    WBFuncs – для процедуры WB_Navigate.
    MSHTML – для интерфейса IHTMLElement.


    Для работы использую компонент WebBrowser.

    Код полностью (исходники: Прикреплённый файлПрикреплённый файлExampleSource.zip (70,61 Кбайт, скачиваний: 8) )

    ExpandedWrap disabled
      unit Unit1;
       
      interface
       
      uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
        Dialogs, StdCtrls, OleCtrls, SHDocVw, ComCtrls, ExtCtrls, WBFuncs;
       
      type
        TForm1 = class(TForm)
          WebBrowser1: TWebBrowser;
          Button1: TButton;
          PageControl: TPageControl;
          Panel1: TPanel;
          TabSheet1: TTabSheet;
          TabSheet2: TTabSheet;
          PageControl1: TPageControl;
          TabSheet3: TTabSheet;
          TabSheet4: TTabSheet;
          TabSheet5: TTabSheet;
          GroupBox1: TGroupBox;
          edSearchAndHighlight: TEdit;
          Button2: TButton;
          PnlElementInfo1: TPanel;
          PnlHandle: TPanel;
          edElementTag: TEdit;
          Label1: TLabel;
          Panel3: TPanel;
          edElementId: TEdit;
          Label2: TLabel;
          Panel4: TPanel;
          edElementinnerHTML: TEdit;
          Label3: TLabel;
          Timer1: TTimer;
          Panel5: TPanel;
          edElementclassName: TEdit;
          Label4: TLabel;
          Panel6: TPanel;
          edElementinnerText: TEdit;
          Label5: TLabel;
          Panel7: TPanel;
          edElementhref: TEdit;
          Label6: TLabel;
          procedure Button1Click(Sender: TObject);
          procedure Timer1Timer(Sender: TObject);
        private
          { Private declarations }
          FPrevBrowser: TWebbrowser;
        public
          { Public declarations }
          function GetCurrentWB: TWebbrowser;
        end;
       
      var
        Form1: TForm1;
       
      implementation
       
      uses
        MSHTML;
       
      {$R *.dfm}
       
      function TForm1.GetCurrentWB: TWebbrowser;
      begin
        Result := nil;
        with PageControl do
          if ActivePage.ControlCount > 0 then
          begin
            if ActivePage.Controls[0] is TWebbrowser then
            begin
              Result := (TWebbrowser(ActivePage.Controls[0]));
            end else
              Result := FPrevBrowser;
          end;
      end;
       
       
      procedure TForm1.Button1Click(Sender: TObject);
      begin
       
          WB_Navigate(GetCurrentWB, 'http://mysite1.su');
       
          WB_SetFocus(GetCurrentWB);
       
      end;
       
       
       
      procedure TForm1.Timer1Timer(Sender: TObject);
      var
        MausPos: TPoint;
        Element: IHTMLElement;
        imgElement: IHTMLIMGElement;
        scrElement: IHTMLLinkElement;
        x, y: Integer;
        Doc: IHTMLDocument2;
        CurrentWB: TWebbrowser;
      begin
       
          CurrentWB := GetCurrentWB;
          if Assigned(CurrentWB) then
          begin
             Doc := CurrentWB.Document as IHTMLDocument2;
              if Assigned(doc) then
              begin
                GetCursorPos(MausPos);
                mauspos := CurrentWB.ScreenToClient(mauspos);
                x := MausPos.x;
                y := MausPos.y;
       
                Element := GetElementAtPos(doc, x, y);
       
                if Assigned(Element) then
                begin
                   edElementTag.Text := Element.tagName;
                   edElementId.Text := Element.id;
                   edElementinnerHTML.Text := Element.innerHTML;
                   edElementclassName.Text := Element.className;
                   edElementinnerText.Text := Element.innerText;
                   Element.QueryInterface(IHTMLIMGElement, imgElement);
                   if assigned(imgElement) then
                    edElementhref.Text := imgElement.href;
                   Element.QueryInterface(IHTMLLinkElement, scrElement);
                   if assigned(scrElement) then
                    edElementhref.Text := scrElement.href;
                end;
       
              end;
        
       
        end;
      end;
       
      end.


    Исходники приложила. Там сама программа и сайт который я использую для тестирования.
    Сообщение отредактировано: Katerina1993 -
      Вам это нужно?
      ExpandedWrap disabled
        const
          constInvalidHTML = 'Invalid HTML document';
          constInvalidHTMLStructure = constInvalidHTML + ' structure';
         
        // aDocument = WebBrowser.Document, ID = строка ID, iNum = номер вхождения элемента в документ с таким ID (начинаются с 1)
        function GetElementById(const aDocument: IDispatch; const ID: String; iNum: LongInt): IDispatch;
        var
          Doc: IHTMLDocument2;
          Body: IHTMLElement2;
          Tags: IHTMLElementCollection;
          Tag: IHTMLElement;
          i, c, Count: LongInt;
        begin
          Result := nil;
          if iNum < 1 then Exit;
          if Supports(aDocument, IHTMLDocument2, Doc) then begin
            if Supports(Doc.body, IHTMLElement2, Body) then begin
              Tags := Body.getElementsByTagName('*');
              Count := Tags.length;
              c := 0;
              for i := 0 to Count - 1 do begin
                Tag := Tags.item(i, EmptyParam) as IHTMLElement;
                if AnsiSameText(Tag.id, ID) then inc(c);
                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.Button3Click(Sender: TObject);
        var
          Elem: IHTMLElement;
        begin
          try
            Elem := GetElementById(WebBrowser1.Document, 'myid', 1) as IHTMLElement;
            if Assigned(Elem) then begin
        // Делаем с элементом что хотим
            end;
          except
        // Ошибки поиска элементов
          end;
        end;
      Сообщение отредактировано: macomics -
        А вот здесь, что указываем. Вместо звездочки.
        ExpandedWrap disabled
          Tags := Body.getElementsByTagName('*');
          Цитата Katerina1993 @
          А вот здесь, что указываем. Вместо звездочки.

          Ничего. Используйте как есть. '*' получает все тэги из body в document. Или можете передать её через параметры и тогда можно будет искать не просто по id но еще и конкретный тэг (например, только ссылки, указав там 'a' или только блочные тэги, указав 'div').
          Сообщение отредактировано: macomics -
            Просто у меня появляется ошибка, когда я открываю веб-страницу и при нажатии кнопки, где активируется элемент в dom. Пример:
            Цитата
            Access violation at adress 43CFCDAA in module 'mshtml.dll'

            Вот скриншот ошибки.
            Прикреплённый файлПрикреплённый файлScreenshot_1.jpg (112,74 Кбайт, скачиваний: 15)
            Когда я нажимаю OK выделяется эта строка, я решила что с ней что-то не так и нужно в скобках изменить параметр.
            Прикреплённый файлПрикреплённый файлScreenshot_2.jpg (99,61 Кбайт, скачиваний: 15)
            Сообщение отредактировано: Katerina1993 -
              Вот так всегда, когда набираешь код в браузере по памяти и не проверяешь.

              ExpandedWrap disabled
                const
                  constInvalidHTML = 'Invalid HTML document';
                  constInvalidHTMLStructure = constInvalidHTML + ' structure';
                 
                // aDocument = WebBrowser.Document, ID = строка ID, iNum = номер вхождения элемента в документ с таким ID (начинаются с 1)
                function GetElementById(const aDocument: IDispatch; const ID: String; iNum: LongInt = 1; const tagName: WideString = '*'): IDispatch;
                var
                  Doc: IHTMLDocument2;
                  Body: IHTMLElement2;
                  Tags: IHTMLElementCollection;
                  Tag: IHTMLElement;
                  i, c, Count: LongInt;
                begin
                  Result := nil;
                  if iNum < 1 then Exit;
                  if Supports(aDocument, IHTMLDocument2, Doc) then begin
                    if Supports(Doc.body, IHTMLElement2, Body) then begin
                      Tags := Body.getElementsByTagName(tagName);
                      Count := Tags.length;
                      c := 0;
                      for i := 0 to Count - 1 do begin
                        Tag := Tags.item(i, EmptyParam) as IHTMLElement;
                        if AnsiSameText(Tag.id, ID) then inc(c);
                        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.Button3Click(Sender: TObject);
                var
                  Elem: IHTMLElement;
                begin
                  try
                    Elem := GetElementById(WebBrowser1.Document, 'element_id', 1, 'a') as IHTMLElement; // Поиск только среди ссылок
                    if Assigned(Elem) then begin
                // Делаем с элементом что хотим
                    end;
                  except
                // Ошибки поиска элементов
                  end;
                end;
              Вот исправленный. Я вместо Doc.body передавал Doc и не поправил GUID интерфейса после копирования.
              Сообщение отредактировано: macomics -
                Вот в этой строке:
                ExpandedWrap disabled
                  Elem := GetElementById(WebBrowser1.Document, 'element_id', 1, 'a') as IHTMLElement;

                Вместо element_id нужно использовать значения атрибута ссылки? У меня например test.
                  Да. У вас в примере туда надо передать 'test'. Можно так же модифицировать код для поиска элементов без атрибута id.
                  ExpandedWrap disabled
                    const
                      constInvalidHTML = 'Invalid HTML document';
                      constInvalidHTMLStructure = constInvalidHTML + ' structure';
                     
                    // aDocument = WebBrowser.Document, ID = строка ID, iNum = номер вхождения элемента в документ с таким ID (начинаются с 1)
                    function GetElementByIndexIdAndTagName(const aDocument: IDispatch; iNum: LongInt = 1; const sID: String = '*'; const sTagName: WideString = '*'): IDispatch;
                      function AnyID(const s1: String; const s2: String): Boolean; begin Result := True; end;
                    var
                      Doc: IHTMLDocument2;
                      Body: IHTMLElement2;
                      Tags: IHTMLElementCollection;
                      Tag: IHTMLElement;
                      i, c, Count: LongInt;
                      comp: function (const s1: String; const s2: String): Boolean;
                    begin
                      Result := nil;
                      if iNum < 1 then Exit;
                      if (sID <> '*') and (sID <> '') then comp := @AnsiSameText else comp := @AnyID;
                      if Supports(aDocument, IHTMLDocument2, Doc) then begin
                        if Supports(Doc.body, IHTMLElement2, Body) then begin
                          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 comp(Tag.id, sID) then inc(c);
                            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.Button3Click(Sender: TObject);
                    var
                      Elem: IHTMLElement;
                    begin
                      try
                        Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 1, 'test', 'a') as IHTMLElement; // Поиск первой только среди ссылок с id="test" (по тэгу и id)
                        if Assigned(Elem) then begin
                    // Делаем с элементом что хотим
                        end;
                      except
                    // Ошибки поиска элементов
                      end;
                      try
                        Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 10) as IHTMLElement; // Поиск по индексу десятого элемента в документе (только по индексу)
                        if Assigned(Elem) then begin
                    // Делаем с элементом что хотим
                        end;
                      except
                    // Ошибки поиска элементов
                      end;
                      try
                        Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 2, 'myid') as IHTMLElement; // Поиск второго элемента с id="myid" (по индексу и id)
                        if Assigned(Elem) then begin
                    // Делаем с элементом что хотим
                        end;
                      except
                    // Ошибки поиска элементов
                      end;
                      try
                        Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 3, '', 'div') as IHTMLElement; // Поиск третьего блочного элемента (<div>...</div>) (по индексу и тэге)
                        if Assigned(Elem) then begin
                    // Делаем с элементом что хотим
                        end;
                      except
                    // Ошибки поиска элементов
                      end;
                    end;
                    Комментарий в условие
                    Цитата

                    // Делаем с элементом что хотим

                    Все таки, что нужно сделать, чтобы был переход по ссылке и открылась форма?
                      Например
                      ExpandedWrap disabled
                        procedure TForm1.Button3Click(Sender: TObject);
                        var
                          Elem: IHTMLElement;
                        begin
                          try
                            Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 1, 'test', 'a') as IHTMLElement; // Поиск первой только среди ссылок с id="test" (по тэгу и id)
                            if Assigned(Elem) then begin
                        // Делаем с элементом что хотим
                              Elem.click; // Кликнуть по ссылке (выполнить OnClick или переход по href)
                            end;
                          except
                        // Ошибки поиска элементов
                          end;
                        end;
                        macomics, в 8 посту несколько примеров, как искать по блоку, id и по индексу, а как по классу.

                        Сделала заполнение полей.
                        ExpandedWrap disabled
                          procedure TForm1.Button4Click(Sender: TObject);
                          var
                            Elem: IHTMLElement;
                          begin
                            try
                           
                              Elem := GetElementById(WebBrowser1.Document, 'title', 1, 'input') as IHTMLElement; // Поиск только среди ссылок
                              if Assigned(Elem) then begin
                                 Elem.innerText:='Название';
                           
                              end;
                              Elem := GetElementById(WebBrowser1.Document, 'message', 1, 'textarea') as IHTMLElement; // Поиск только среди ссылок
                              if Assigned(Elem) then begin
                                  Elem.innerHTML:='Тестовое описание'
                              end;
                            except
                           
                            end;
                          end;

                        А вот в кнопке у меня только класс прописан, пример на картинке.
                        Прикреплённый файлПрикреплённый файлimg1.jpg (34,51 Кбайт, скачиваний: 14)
                        Еще интерсно как можно на одну кнопку button4 повесить и заполнение полей и отправку?
                          Цитата Katerina1993 @
                          Еще интерсно как можно на одну кнопку button4 повесить и заполнение полей и отправку?

                          Смотря какую кнопку вы имеете ввиду. Если кнопку на странице, тогда просто измените её тип с submit на button и добавьте обработчик onClick. На JavaScript в обработчике нажатия добавляете заполнение полей формы, а в конце вызываете submit для формы
                          ExpandedWrap disabled
                            function clickOnButton(e) {
                              const f = e.target.form; // Получаем форму, на которой находится кнопка
                              e.preventDefault(); // Прерываем цепочку передачи сообщений к нижерасположенным элементам
                              f.title.value = "Hello world"; // Заполняем поля формы (заголовок)
                              f.textbox.innerText = "Autofilled by click!"; // и текстовое поле тоже (не забудьте у textarea добавить name="textbox")
                              f.submit(); // Отправка формы
                            }
                            const formButton = document.querySelector(".submitButton");
                            if (formButton) {
                              formButton.addEventListener("click", clickOnButton);
                            }


                          Если надо заполнить поля формы перед отправкой при нажатии на кнопке Delphi, тогда придется найти каждое поле формы отдельно и установить его соответствующие атрибуты.

                          Если вы хотите, чтобы я вам заполнил поля на форме Delphi для найденного элемента, тогда это будет так (не забудьте выключить таймер)
                          ExpandedWrap disabled
                            procedure TForm1.Button3Click(Sender: TObject);
                            var
                              Elem: IHTMLElement;
                            begin
                              try
                                Elem := GetElementByIndexIdAndTagName(WebBrowser1.Document, 1, 'test', 'a') as IHTMLElement; // Поиск первой только среди ссылок с id="test" (по тэгу и id)
                                if Assigned(Elem) then begin
                            // Делаем с элементом что хотим
                                  edElementTag.Text := WideCharToString(@Elem.tagName[1]);
                                  edElementId.Text := WideCharToString(@Elem.id[1]);
                                  edElementinnerHTML.Text := WideCharToString(@Elem.innerHTML[1]);
                                  edElementclassName.Text := WideCharToString(@Elem.className[1]);
                                  edElementinnerText.Text := WideCharToString(@Elem.innerText[1]);
                             
                                  Elem.click; // Кликнуть по ссылке (выполнить OnClick или переход по href)
                                end;
                              except
                            // Ошибки поиска элементов
                              end;
                            end;
                          Если же надо выполнять поиск по названию класса, тогда можно написать похожую функцию
                          ExpandedWrap disabled
                            const
                              constInvalidHTML = 'Invalid HTML document';
                              constInvalidHTMLStructure = constInvalidHTML + ' structure';
                             
                            // aDocument = WebBrowser.Document, iNum = номер вхождения элемента в документ с таким ID (начинаются с 1), sClassName = строка ID, sTagName = имя тэга у элемента
                            function GetElementByIndexClassNameAndTagName(const aDocument: IDispatch; iNum: LongInt = 1; const sClassName: String = '*'; const sTagName: WideString = '*'): IDispatch;
                              function AnyID(const s1: String; const s2: String): Boolean; begin Result := True; end;
                            var
                              Doc: IHTMLDocument2;
                              Body: IHTMLElement2;
                              Tags: IHTMLElementCollection;
                              Tag: IHTMLElement;
                              i, c, Count: LongInt;
                              comp: function (const s1: String; const s2: String): Boolean;
                            begin
                              Result := nil;
                              if iNum < 1 then Exit;
                              if (sClassName <> '*') and (sClassName <> '') then comp := @AnsiSameText else comp := @AnyID;
                              if Supports(aDocument, IHTMLDocument2, Doc) then begin
                                if Supports(Doc.body, IHTMLElement2, Body) then begin
                                  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 comp(Tag.className, sClassName) then inc(c);
                                    if c = iNum then begin
                                      Result := Tag;
                                      break;
                                    end;
                                  end;
                                end else raise Exception.Create(constInvalidHTMLStructure + '!');
                              end else raise Exception.Create(constInvalidHTML + '!');
                            end;


                          Добавлено
                          И еще
                          Цитата Katerina1993 @
                          Сделала заполнение полей.

                          procedure TForm1.Button4Click(Sender: TObject);
                          var
                            Elem: IHTMLElement;
                          begin
                            try
                           
                              Elem := GetElementById(WebBrowser1.Document, 'title', 1, 'input') as IHTMLElement; // Поиск только среди ссылок
                              if Assigned(Elem) then begin
                                 Elem.innerText:='Название';
                           
                              end;
                              Elem := GetElementById(WebBrowser1.Document, 'message', 1, 'textarea') as IHTMLElement; // Поиск только среди ссылок
                              if Assigned(Elem) then begin
                                  Elem.innerHTML:='Тестовое описание'
                              end;
                            except
                           
                            end;
                          end;

                          А вот в кнопке у меня только класс прописан, пример на картинке.

                          Текст для input задается не как innerText или innerHTML, а в поле value!
                          ExpandedWrap disabled
                            Elem.value := 'Отправить сообщение';
                          Сообщение отредактировано: macomics -
                            Цитата
                            Текст для input задается не как innerText или innerHTML, а в поле value!

                            У меня почему-то выдает сообщение об ошибке.

                            Прикреплённый файлПрикреплённый файлErr1.png (23,56 Кбайт, скачиваний: 15)
                              Значит оно доступно не напрямую, а через getAttribute/setAttribute
                              ExpandedWrap disabled
                                      Text := Elem.getAttribute('value', 0);
                                      Caption := WideCharToString(@Text[1]);
                                      Elem.setAttribute('value', 'Send text!', 0);
                              Сообщение отредактировано: macomics -
                                Работает, только первые две строчки не пойму для чего getAttribute и WideCharToString? Мне удалось запусить только через Elem.setAttribute.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0656 ]   [ 23 queries used ]   [ Generated: 27.04.24, 10:05 GMT ]