• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1990
  • Last Modified:

TWebBrowser -- how?

Hi All,
I have a TWebBrowser component on my form, I pass a url to the component and everything is cool.

The url contains a form which I want to fill out. Javascript gives me a permission denied error. Is there a way to reference form fields in the web browser as objects and set the values to what I want?

Up to 500pts available.
-max
0
maxb
Asked:
maxb
  • 12
  • 12
  • +1
1 Solution
 
MotazCommented:
You can use Indy HTTP client idHTTP to post data to a web server.

Motaz
0
 
CynnaCommented:
maxb,

1. Do you want to general principle of filling form fields for any url, or just this one?

2. When you navigate to this url using IE, can you fill the form OK (by hand) ?

3. What version of Delphi do you have?
0
 
maxbAuthor Commented:
Pretend I wanted to automate the posting of questions or something to EE. I know I can pass the parameters to their script in the URL but some people check the referring URL and know that they are being tricked.

I am doing this to automate my submission process. I submit my artwork to 12 sites 3 times a day and its tedious.

Yes you can fill the form out by hand. Its just a website on as server I DO NOT own. If i try to use javascript, it gives me a "Permission Denied" because it thinks its malicious or something.

Again, I need to fill out the form on someone elses server, I can click the submit button manually, I cant be downloading the form, filling out and then clicking submit.

I have delphi 3-6 so any is fine :)
Thanks again.
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
CynnaCommented:
maxb,

Following code requires you to check html source
of the form you want to submit.
I posted 2 demos for expert-exchange form.Place WebBrowser1 and 2 Buttons on the form for demos.

Copy/Paste:
--------------------

procedure TForm1.PostToURL(URL, Data: String);
//Post data string to the specified URL
var  a,b,c,d: OLEVariant;
     DataSize, Count: Integer;
begin
  if (URL = '') then exit;
  //Set the flags:
  a:=14;
  //Get the length of the post string:
  DataSize:= Length(Data);
  //Create a Variant array of bytes:
  c:= VarArrayCreate([0, DataSize], varByte);
  //Loop through each character and set the array element to the corresponding character:
  for Count:= 0 to DataSize - 1 do c[Count]:= Ord(Data[Count+1]);
  //Add the null terminating character:
  c[DataSize]:= 0;
  //Type cast it to variant array
  TVarData(c).vtype:= varArray;
  //Set the encoding header:
  d:= 'Content-Type: application/x-www-form-urlencoded'+#13+#10+#0;
  //Keep current frame:
  b:= '_top';
  // Finally post data:
  WebBrowser1.Navigate(URL, a, b, c, d);
end;


Demo 1:
------------

procedure TForm1.Button1Click(Sender: TObject);
begin
  // submits search to ex-ex for keyword 'internet':
  PostToURL('http://www.experts-exchange.com/jsp/qSearch.jsp', 'keyWord=internet');
end;


Demo 2:
------------

procedure TForm1.Button2Click(Sender: TObject);
begin
  // logs you on ex-ex (replace string XXXXX with your password):
  PostToURL('http://www.experts-exchange.com/jsp/memberLogin.jsp',
            'loginMemberName=maxb&loginPassword=XXXXX');
end;

0
 
maxbAuthor Commented:
Thats what I meant by "I know I can pass the parameters to their script in the URL but some people check the referring URL and know that they are being tricked."

If they looked for the referring URL, they would see that the post to http://www.experts-exchange.com/jsp/qSearch.jsp came from nowhere and not http://www.experts-exchange.com for example.

Am I reading this wrong?
0
 
CynnaCommented:
maxb,

> Am I reading this wrong?

No you are not.
Sorry, didn't get your point right away.


> Is there a way to reference form fields in the web browser as objects and set the values to what I want?

I think I saw this before. I'll try and post something for you later.  
Do you need only form auto-fill or auto-fill and auto-click on Submit button?
0
 
maxbAuthor Commented:
I will click the submit button myself.
Thank you for your help.
0
 
CynnaCommented:
maxb,

First thing you need is add MSHTML_TLB, COMOBJ to your uses clause.
If the compiler complains, you probably don't have MSHTML_TLB.pas. In that case, you should import Microsoft HTML Object Library (Project->Import Type Library).
During import, you'll have to wait quite a while (it generates over 10Mb source ), so don't loose your patiance, or think your machine has frozen :) ....

Finally just Copy/Paste following function:

function FillFormField(Browser:TWebBrowser; FieldName, FieldValue: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
     begin
        if InputElement.Get_type_ = 'text' then begin
           InputElement.Set_value(FieldValue);
           Result:=TRUE;
        end;
     end;
end;


DEMO:
-------
(place TWebBrowser and TButton on the form)


procedure TForm2.Button2Click(Sender: TObject);
begin
   WebBrowser1.Navigate('http://www.experts-exchange.com/');
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // Fill the search field (named keyWord) with some text:
   FillFormField(WebBrowser1, 'keyWord', '....My search here....');
end;
0
 
maxbAuthor Commented:
Ok, I feel like an idiot. While playing around, I removed the Microsoft HTML Object Library. How do I readd it? :)

I tried reinstalling d4 but no luck.

Thanks guys so much.
0
 
CynnaCommented:
Oh well, I have no hands-on expiriance with this type of situation...
Probably redundant question, but did you try simply repeating Project->Import Type Library, and if yes, what happened exactly?
0
 
maxbAuthor Commented:
I did, the Microsoft HTML Object Library wasnt on the list of items to import.
0
 
CynnaCommented:
Just curious, what did you do during this 'playing around'?  You didn't click 'Remove' button now, didn't you?

Anyway, if you didn't do something really bad to your system, this shoud get you back:
Project->Import Type Library-> Add (opposite from Remove :-)
Then surf to your windows system folder, and look for:
mshtml.tlb

Click OK, and that's it; you should now have your Microsoft HTML Object Library again.
Click 'Install' on it and take a cup of cofee...
After a while, you should have MSHTML_TLB.pas.
Now go back and Copy/Paste my example.
0
 
maxbAuthor Commented:
Cool,
It worked but wouldnt compile. Has problems with the "fonts". Did yours compile? What version of Delphi are you using?

-max
0
 
CynnaCommented:
> Did yours compile? What version of Delphi are you using?

I'm using D5 Enterprise on WinXP, and it compiles without any problems.


> Has problems with the "fonts".

Well, that's not exactly what I'd call a "detailed bug report"... ;)

1. What error message you received exactly ? (copy/paste, please)

2. What line(s) cause this error? (copy/paste problematic line(s)and neighboring lines)
   
3. What OS do you have?


I'm a bit busy right now, so please be patient, I'll get to you later...

In the meanwhile, there are few things for you to try yourself:

1. You said you have D3-D5. Try this on D5 or D6.

2. If you're in a hacking mood, you might try just commenting out
   that line(s) in MSHTML_TLB.pas and see if it compiles OK.
   Probably won't work right away, but won't cost you much...
0
 
maxbAuthor Commented:
It only works in d4 for me, I cant find my d5.
But, d4 doesnt have a TWebBrowser component.

[Error] MSHTML_TLB.pas(97982): Undeclared identifier: 'Get_fontFamily'
[Error] MSHTML_TLB.pas(97998): Undeclared identifier: 'Get_fontStyle'

and so on.

    procedure Set_textKashida(Param1: OleVariant);
    function  Get_textKashida: OleVariant;
    procedure Set_textAutospace(const Param1: WideString);
    function  Get_textAutospace: WideString;

line 32447, this is in D6. I am running XP.
0
 
CynnaCommented:
maxb,

> I cant find my d5.

Then it looks like we're in trouble. I can only speculate about possible solutions, because I can only access D5.


> It only works in d4 for me...
> But, d4 doesnt have a TWebBrowser component

Did you try this:
- Components->Import ActiveX Control,
- select "Microsoft Internet Controls"
- if you can't see it, I think this file is SHDOCVW.DLL; it should be in your system folder.


As for D6:

> Undeclared identifier: 'Get_fontFamily'.... in D6 ...

Well, D6 TLIBIMP.EXE (type library importer) seem to be buggy.
As far as I can see, you have two choices:

1) Update to newest D6 service pack. Also, it might be good  
   idea to search for newest (hopeffuly fixed) TLIBIMP.EXE
   for D6.
   
2) There is a "beta" & "unofficial" version of TLIBIMP.EXE
   that claims to solve some of the problems:
   
   http://www.pdmagic.com/download/tlibimp.zip

  If you decide to give it a try, make a backup of the
  existing one, of course.

0
 
maxbAuthor Commented:
Cool, ill try it over the weekend.
0
 
CynnaCommented:
Well, did it work?
0
 
maxbAuthor Commented:
Sorry, I was on a business trip. No, it still will not compile. Is there any way someone could compile it and give it to me or is there a way to do it with d4?

Thank you.
0
 
CynnaCommented:
What happens in D4?

> It only works in d4 for me...
> But, d4 doesnt have a TWebBrowser component

Do you mean you can import MSHTML_TLB.pas from D4, but
don't have TWebBrowser? What happened when you tried importing "Microsoft Internet Controls" as I suggested?


> Is there any way someone could compile it and give it to me
If none of the proposed ways for D6 didn't work out,
you need access to a machine with D5.
There, you should generate MSHTML_TLB.pas and copy it to
your Imports directory.
Unfortunately, MSHTML_TLB.pas is about 10Mb, which makes
it very hard for download from someone else, unless, of course, you have fixed net connection.
0
 
maxbAuthor Commented:
Ok, sweet.

[Error] Unit1.pas(56): Not enough actual parameters

AT:

WebBrowser1.Navigate('http://www.experts-exchange.com/');

It wants 4 more OLEVariant type parameters. I have no idea what to put there.

Please advise.
0
 
maxbAuthor Commented:
Got it to work. Ill post final code and grade of A with 250pts if you can tell me how to check and uncheck a checkbox, radio button, change selection in a dropdown

Thank you again so much.
0
 
CynnaCommented:
So, what was the problem?

About your additional requests... well, I don't know this exactly offhand - will have to search MSDN a while. This is a bit of work, especially if you want working copy/paste demo. I'm kind of short on time right now, so please be patient...
0
 
maxbAuthor Commented:
Thank you. The key was to read the MSHTML_TLB.pas
0
 
CynnaCommented:
Here you go:

function FillFormField(Browser:TWebBrowser; FieldName, FieldValue: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
     begin
        if InputElement.Get_type_ = 'text' then begin
           InputElement.Set_value(FieldValue);
           Result:=TRUE;
        end;
     end;
end;

function CheckFormField(Browser:TWebBrowser; FieldName: String; CheckBoxIndex: Integer; CheckIt: Boolean): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, CheckBoxIndex);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
        if InputElement.Get_type_ = 'checkbox' then  InputElement.checked:=CheckIt;
end;

function RadioFormField(Browser:TWebBrowser; FieldName: String; RadioIndex: Integer): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    InputElement : IHTMLInputElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, RadioIndex);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLInputElement, InputElement) = 0 then
        if InputElement.Get_type_ = 'radio' then InputElement.checked:=TRUE;
end;

function SelectFormField(Browser:TWebBrowser; FieldName, SelectionIndex: String): Boolean;
var WebDoc : IHTMLDocument2;
    pDispatch : IDISPATCH;
    FormCollection : IHTMLElementCollection;
    FormElement : IHTMLFormElement;
    FormItem : IHTMLElement;
    SelectElement: IHTMLSelectElement;
begin
     Result:=FALSE;
     OleCheck(Browser.Document.QueryInterface(IID_IHTMLDocument2, WebDoc));
     FormCollection := WebDoc.Get_forms;
     pDispatch := FormCollection.item(0, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLFormElement, FormElement));
     pDispatch := FormElement.item(FieldName, 0);
     OleCheck(pDispatch.QueryInterface(IID_IHTMLElement, FormItem));
     if FormItem.QueryInterface(IID_IHTMLSelectElement, SelectElement) = 0 then
        SelectElement.selectedIndex:=StrToInt(SelectionIndex);
end;



// DEMO
// -------------
// (you'll need Button1 and Button2)

procedure TForm1.Button1Click(Sender: TObject);
var site: String;
begin
   site:='http://edit.yahoo.com/config/eval_register?.intl=us&new=1&.done=&.src=ym&.partner=&.p=&promo=&.last=';
   WebBrowser1.Navigate(site);
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // Fill first name:
   FillFormField(WebBrowser1, '.fn', 'maxb');
   // Uncheck  special offers.. field:
   CheckFormField(WebBrowser1, '.offer', 0, FALSE);
   // Check Entertainment and Computers & Technology fields
   CheckFormField(WebBrowser1, '.userPrefs', 0, TRUE);
   CheckFormField(WebBrowser1, '.userPrefs', 5, TRUE);
   // Select 5. element from Industry field (Computers):
   SelectFormField(WebBrowser1, '.ind' , '5');
end;

procedure TForm1.Button2Click(Sender: TObject);
var site: String; // Radio button demo
begin
   site:='http://www.altavista.com/sites/search/webadv';
   WebBrowser1.Navigate(site);
   // Wait for page to fully load:
   while WebBrowser1.ReadyState<>READYSTATE_COMPLETE do begin
         Sleep(1);
         Application.ProcessMessages;
   end;
   // check 'only this host or URL'::
   RadioFormField(WebBrowser1, 'rc', 2);
   // check 'by date range':
   RadioFormField(WebBrowser1, 'dt', 1);
end;

0
 
ozi_lionCommented:
Hello, I know this is very old question but I need to use those codes with SSL enabled sites and frame enabled sites, I have tried to change the code but no chance,  can someone help me about it. Thanks in advance.
0

Featured Post

[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

  • 12
  • 12
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now