Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
0 / 0 / 1
Регистрация: 15.05.2014
Сообщений: 24
1

Отрисовать DOM-элемент из TWebBrowser (например капчу) на битмап TBitmap

21.04.2017, 12:34. Показов 1486. Ответов 7

Есть на форме webbrowser. в нем страница на которой есть кнопка либо ссылка вообщем элемент

webbrowser.getElementById('button','id')

Задача стоит найти ее координаты(координаты прямоугольной области по сути надо одну точу(любой угол кнопки) )

нашел в сети вот это


Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 function tform1.GetElementTop(gEl:IHTMLElement):integer;
var
  pEl:IHTMLElement;
begin
result:=0;
pEl:=gEl;
while Assigned(pEl) and (pEl.tagName<>'HTML') do
  begin
  result:=result+pEl.offsetTop;
  showmessage(inttostr(result));
  result:=result-(pEl as IHTMLElement2).scrollTop;
  pEl:=pEl.offsetParent;
  end;//while
end;//GetElementTop
 
 
function tform1.GetElementLeft(gEl:IHTMLElement):integer;
var
  pEl:IHTMLElement;
begin
result:=0;
pEl:=gEl;
while Assigned(pEl) and (pEl.tagName<>'HTML') do
  begin
  result:=result+pEl.offsetLeft;
  result:=result-(pEl as IHTMLElement2).scrollLeft;
  pEl:=pEl.offsetParent;
  end;//while
end;//GetElementLeft

при вот таком запросе

Delphi
1
2
x:=GetElementTop(form1.WebBrowser3.getElementById('button','id'));
y:=GetElementLeft(form1.WebBrowser3.getElementById('button','id'));
выводит 1723 1723

хотя реальные координаты 770 и 455



а вообще все эти манипуляции нужны для того чтоб найти координаты рисунка чтоб сделать Принт скрин экрана.

Вообщем главная цель получить рисунок который находится на форме
скачать его нельзя так как он динамический и меняется при любом телодвижении
если сохранить как то с качается другой рисунок
нужен иммено скрин
либо как то вытащить его из КЭШ если это возможно?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.04.2017, 12:34
Ответы с готовыми решениями:

TBitmap отрисовать в OpenGL
Здравствуйте, Имеется готовый TBitmap и пытаюсь его нарисовать используя OpenGL, не подскажите...

Написать скрипт, рекурсивно обходящий дерево DOM страницы dom.html, начиная от корня DOM
Написать скрипт на языке JavaScript, рекурсивно обходящий дерево DOM страницы dom.html, начиная от...

Как отправить капчу решенную капчу в VkNet
Вывел капчу, и хочу отправить решение при обычной кнопки отправить, но проблема в том что я не...

WebBrowser - как отрисовать элемент управления в картинку?
Я уже слегка запутался. Такая проблема: Приложение, через webBrowser грузит страницу, на странице -...

7
586 / 453 / 147
Регистрация: 09.12.2013
Сообщений: 2,386
Записей в блоге: 2
21.04.2017, 14:01 2
Зачем вам координаты элементов? Это как-то дико.

Добавлено через 28 секунд
Какой ещё "рисунок" на какой ещё "форме"?

Добавлено через 1 минуту
Капча что ли? Поиск по форуму по "получить картинку из капчи", где-то было уже, возможно даже с моим участием...

Добавлено через 1 минуту
Суть - взять нужный элемент и приказать ему отрисоваться на битмап.
0
0 / 0 / 1
Регистрация: 15.05.2014
Сообщений: 24
21.04.2017, 20:07  [ТС] 3
Цитата Сообщение от BOGG ART Посмотреть сообщение
Капча что ли?
совершенно верно
Цитата Сообщение от BOGG ART Посмотреть сообщение
Суть - взять нужный элемент и приказать ему отрисоваться на битмап.
это получается без повторного скачивания?
я только учусь

Добавлено через 38 минут
BOGG ART, вы это имели введу ?
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
procedure TForm1.btn2Click(Sender: TObject);
var
  body, imgs, controlRange: olevariant;
begin
        body := wb1.OleObject.document.body;
        imgs := wb1.OleObject.document.images.item(i);//нужный img
        controlRange := body.createControlRange;
        controlRange.add(imgs);
        controlRange.execCommand('Copy', False, EmptyParam);//копируем
        if ClipBoard.HasFormat(CF_BITMAP) then begin
          img1.Picture.Bitmap.LoadFromClipboardFormat(cf_BitMap, ClipBoard.GetAsHandle(cf_Bitmap), 0);//вставляем
          Clipboard.Clear;//если нужно очищаем буфер...
        end;
end;
пробовал не работает у меня ошибка на строке controlRange.add
0
586 / 453 / 147
Регистрация: 09.12.2013
Сообщений: 2,386
Записей в блоге: 2
21.04.2017, 20:35 4
Нет. Через интерфейс. Сейчас попробую вспомнить название.

Добавлено через 11 минут
Интерфейс IHTMLElementRender и его метод DrawToDC. В старых версиях Делфи может быть не объявлен.
Пример на форуме: Показать сообщение UI-Maker отдельно - и как раз капчу "фоткают", и объявляют сами. Лучше примера вам не найти нигде.


Не по теме:

Прошу модераторов переименовать тему в "Отрисовать DOM-элемент из TWebBrowser на битмапе (например капчу)".

1
0 / 0 / 1
Регистрация: 15.05.2014
Сообщений: 24
21.04.2017, 21:35  [ТС] 5
Цитата Сообщение от BOGG ART Посмотреть сообщение
Лучше примера вам не найти нигде.
Спасибо! пошел смотреть

Добавлено через 40 минут
я првельно понял что мне нужен вотт этот кусок

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Procedure TForm1.Button1Click(Sender: TObject);
Var i, j: Integer; Element, Collection, Form, Options, Captcha: OleVariant; CaptchaImg: TBitmap; Render: IHTMLElementRender;
Begin
WB.Navigate('');
While WB.ReadyState<>READYSTATE_COMPLETE Do
      Application.ProcessMessages;
Element:=WB.OleObject.Document;
Element:=Element.getElementById('input');
Form2.Image1.Picture.Graphic:=Nil;
Form2.Edit1.Text:='';
If CheckVariant(Element) Then
      Begin
      Collection:=Element.GetElementsByTagName('div');
      If CheckVariant(Collection) Then
            Begin
            Form:=Collection.Item(0);
            Collection:=Form.All;
            If CheckVariant(Collection) Then
                  For i:=0 To Collection.Length-1 Do
                        Begin
                        
                        If Element.ID='captchaContainer' Then
                              Begin // Êàï÷à (ñàìî èçîáðàæåíèå)
                              If IHTMLElement2(TVarData(Element).VUnknown).QueryInterface(IID_IHTMLElementRender, Render)=S_OK Then
                                    Begin
                                    CaptchaImg:=TBitmap.Create;
                                    CaptchaImg.Width:=Element.offsetWidth;
                                    CaptchaImg.Height:=Element.offsetHeight;
                                    Render.DrawToDC(CaptchaImg.Canvas.Handle);
                                    Form2.Image1.Picture.Graphic:=CaptchaImg;
                                    CaptchaImg.Free;
                                    End;
                              End;
                    
                       
            If Form2.ShowModal=mrOk Then
                  Begin
                  Captcha.Value:=Form2.Edit1.Text; // Ââîä êàï÷è
                  Form.Submit;
                  End;
            End;
      End;
     
End;
0
586 / 453 / 147
Регистрация: 09.12.2013
Сообщений: 2,386
Записей в блоге: 2
23.04.2017, 01:05 6
Лучший ответ Сообщение было отмечено zozo как решение

Решение

Если ваша Делфи довольно старой версии, в ней может быть не объявлен интерфейс. Тогда понадобится объявить вручную:
Delphi
1
2
3
4
5
6
7
8
Const
      IID_IHTMLElementRender: TGUID = '{3050F669-98B5-11CF-BB82-00AA00BDCE0B}';
 
Type
      IHTMLElementRender = Interface(IUnknown) ['{3050F669-98B5-11CF-BB82-00AA00BDCE0B}']
            Function DrawToDC(DC: HDC): HRESULT; StdCall;
            Function SetDocumentPrinter(bstrPrinterName: WideString; DC: HDC): HRESULT; StdCall;
      End;
Полезная функция для проверки наличия данных в OleVariant:
Delphi
1
2
3
4
Function CheckVariant(Const V: OleVariant): BooLean;
Begin (* Info: NONE; Version: 0.3; Uses: {System,Variants}; *)
Result:=Not (VarIsNull(V) Or VarIsEmpty(V) Or VarIsClear(V));
End;
Напишем функцию для получения текущего изображения напрямую:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Function DrawHTMLElementToBitmap(Const Element: OleVariant; Const Bitmap: TBitmap; Const AutoSize: BooLean = False): BooLean;
Var Ret: HRESULT; Renderer: IHTMLElementRender;
Begin (* Info: NONE; Version: 0.5; Uses: {System,SysUtils,Graphics,ComObj,Windows,MSHTML}; *)
Result:=False;
If Not CheckVariant(Element) Then
      Exit;
If Not Assigned(Bitmap) Then
      Exit;
If Supports(Element, IID_IHTMLElementRender, Renderer) Then
      With Bitmap, Canvas Do
            Begin
            If AutoSize Then
                  Begin
                  Width:=Element.offsetWidth;
                  Height:=Element.offsetHeight;
                  End;
            Lock();
            Ret:=Renderer.DrawToDC(Handle);
            Unlock();
            If (Ret=S_OK) Then
                  Result:=True
            Else
                  OleCheck(Ret);
            Renderer:=Nil;
            End
Else
      Raise Exception.Create('[Failed] Element not supports IID_IHTMLElementRender');
End;
Всё остальное наглядно в примере от UI-Maker.
Находите ваш элемент, передаёте его в функцию DrawHTMLElementToBitmap() вместе с битмапом на который надо нарисовать. Условно:
Delphi
1
2
3
...
DrawHTMLElementToBitmap(Element, Image1.Picture.Bitmap, True);
...
2
0 / 0 / 1
Регистрация: 15.05.2014
Сообщений: 24
23.04.2017, 19:27  [ТС] 7
BOGG ART, Спасибо огромное!
0
0 / 0 / 1
Регистрация: 15.05.2014
Сообщений: 24
21.12.2017, 07:42  [ТС] 8
Приветствую всех.
подскажите как определить этот элемент:
Delphi
1
<img data-captcha-img="" class="b-image" width="120" height="72" src="/captcha/0.07803130685398596" style="background:#f5f5f5;margin-bottom:10px;">
раньше я его определял вот так:
Delphi
1
2
3
 
             Element:=WebBrowser3.OleObject.Document;
            Element:=Element.getElementById('captchaImageContainer');
у него был ID сейчас нету не могу передать его вот сюда:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Function TForm1.DrawHTMLElementToBitmap(Const Element: OleVariant; Const Bitmap: TBitmap; Const AutoSize: BooLean = False): BooLean;
Var Ret: HRESULT; Renderer: IHTMLElementRender;
Begin (* Info: NONE; Version: 0.5; Uses: {System,SysUtils,Graphics,ComObj,Windows,MSHTML}; *)
Result:=False;
If Not CheckVariant(Element) Then
      Exit;
If Not Assigned(Bitmap) Then
      Exit;
If Supports(Element, IID_IHTMLElementRender, Renderer) Then
      With Bitmap, Canvas Do
            Begin
            If AutoSize Then
                  Begin
                  Width:=Element.offsetWidth;
                  Height:=Element.offsetHeight;
                  End;
            Lock();
            Ret:=Renderer.DrawToDC(Handle);
            Unlock();
            If (Ret=S_OK) Then
                  Result:=True
            Else
                  OleCheck(Ret);
            Renderer:=Nil;
            End
Else
      Raise Exception.Create('[Failed] Element not supports IID_IHTMLElementRender');
End;
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.12.2017, 07:42

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Tbitmap.create и Tbitmap.scanline
Если после создания bitmap-а загрузить изображение (loadfromfile()) то изменение пикселей через...

Удалить элемент DOM
Здравствуйте! Как удалить элемент DOM и все обработчики к нему (элементу). Возможно, уже есть...

Получить элемент из DOM
Есть HTML: &lt;div class=&quot;moduletable_topmenu&quot;&gt; &lt;ul id=&quot;topmenu_main&quot; class=&quot;menu&quot;&gt; ...

Вставить новый элемент в DOM
Вообщем такое дело: имеется код на jquery, но нужно его переделать на чистый js, чтобы делал тоже...

Элемент dom как объект
Есть инпут на котором стоит функция по клику filter(this). Как можно получить параметр this в...

Как узнаться находиться ли элемент в DOM
С помощью document.getElementsById('мой id'); Нахожу нужный мне элемент. Как узнать находиться...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.