Cry about...
Delphi Programming with TWebBrowser


How to read and write form elements


This page provides notes on how to read from and write to forms that are displayed in a web page in a TWebBrowser.

Contents:

The examples on this page assume that the page has been loaded into a TWebBrowser called WebBrowser.


Get the number of forms on a page

function NumberOfForms(document: IHTMLDocument2): integer;
var
  forms: IHTMLElementCollection;
begin
  forms := document.Forms as IHTMLElementCollection;
  result := forms.Length;
end;

and to call it:

procedure TMyForm.Button1Click(Sender: TObject);
var
  nForms: integer;
begin
  nForms := NumberOfForms(WebBrowser.Document as IHTMLDocument2);
  ShowMessage('Form count: ' + IntToStr(nForms));
end;

Get a form by number

Pages can have more than one form on them. The following function will return an instance of a form by number - where the first form is numbered 0, the next 1 and so on:

function GetFormByNumber(document: IHTMLDocument2;
    formNumber: integer): IHTMLFormElement;
var
  forms: IHTMLElementCollection;
begin
  forms := document.Forms as IHTMLElementCollection;
  if formNumber < forms.Length then
    result := forms.Item(formNumber,'') as IHTMLFormElement
  else
    result := nil;
end;

For an example of this function in use see "Get the name of a form" (below).


Get the name of a form

It should be appreciated that HTML does not require forms to be named.

var
  firstForm: IHTMLFormElement;
  document: IHTMLDocument2;
begin
  document := WebBrowser.Document as IHTMLDocument2;
  firstForm := GetFormByNumber(document,0);
  if Assigned(firstForm) then
    ShowMessage('Name of first form is ' + firstForm.Name)
  else
    ShowMessage('This page does not contain any forms');

Get a form by name

Since forms can be named, if you know the name of a form it may be preferable to access the form by name rather than by number.

function GetFormByName(document: IHTMLDocument2;
    const formName: string): IHTMLFormElement;
var
  forms: IHTMLElementCollection;
begin
  forms := document.Forms as IHTMLElementCollection;
  result := forms.Item(formName,'') as IHTMLFormElement
end;

This function will return nil if there is no form with the required name.


List the names of all the fields on a form

function GetFormFieldNames(fromForm: IHTMLFormElement): TStringList;
var
  index: integer;
  field: IHTMLElement;
  input: IHTMLInputElement;
  select: IHTMLSelectElement;
  text: IHTMLTextAreaElement;
begin
  result := TStringList.Create;
  for index := 0 to fromForm.length do
  begin
    field := fromForm.Item(index,'') as IHTMLElement;
    if Assigned(field) then
    begin
      if field.tagName = 'INPUT' then
      begin
        // Input field.
        input := field as IHTMLInputElement;
        result.Add(input.name);
      end
      else if field.tagName = 'SELECT' then
      begin
        // Select field.
        select := field as IHTMLSelectElement;
        result.Add(select.name);
      end
      else if field.tagName = 'TEXTAREA' then
      begin
        // TextArea field.
        text := field as IHTMLTextAreaElement;
        result.Add(text.name);
      end;
    end;
  end;
end;

and to call it:

procedure TMyForm.Button1Click(Sender: TObject);
var
  document: IHTMLDocument2;
  theForm: IHTMLFormElement;
  index: integer;
  fields: TStringList;
begin
  document := TWebBrowser.Document as IHTMLDocument2;
  theForm := GetFormByNumber(WebBrowser.Document as IHTMLDocument2,0);
  fields := GetFormFieldNames(theForm);

  for index := 0 to fields.count-1 do
    ShowMessage('Field ' + IntToStr(index) + ' called ' + fields[index]);
end;

Get the value of a named field

To get the value of a named field from a form:

function GetFieldValue(fromForm: IHTMLFormElement;
  const fieldName: string): string;
var
  field: IHTMLElement;
  inputField: IHTMLInputElement;
  selectField: IHTMLSelectElement;
  textField: IHTMLTextAreaElement;
begin
  field := fromForm.Item(fieldName,'') as IHTMLElement;
  if not Assigned(field) then
    result := ''
  else if field.tagName = 'INPUT' then
  begin
    inputField := field as IHTMLInputElement;
    if (inputField.type_ <> 'radio') and
       (inputField.type_ <> 'checkbox')
    then
      result := inputField.value
    else if inputField.checked then
      result := 'checked'
    else
      result := 'unchecked';
  end
  else if field.tagName = 'SELECT' then
  begin
    selectField := field as IHTMLSelectElement;
    result := selectField.value
  end
  else if field.tagName = 'TEXTAREA' then
    begin
    textField := field as IHTMLTextAreaElement;
    result := textField.value;
  end;
end;

and to call it:

procedure TMyForm.Button1Click(Sender: TObject);
var
  document: IHTMLDocument2;
  theForm: IHTMLFormElement;
  index: integer;
begin
  document := TWebBrowser.Document as IHTMLDocument2;
  theForm := GetFormByNumber(WebBrowser.Document as IHTMLDocument2,0);
  ShowMessage('Field "name" has value ' + GetFieldValue(theForm,'name'));

The "GetFieldValue" function is long because it tests to determine the type of field before extracting the value. If you are sure about the type of field (i.e. radio button, check box, text box etc, then you can shorted this function considerably.

For example, if you are absolutely sure that the field is an input field (i.e. in the HTML it is defined using the <input ...> tag) then you could simply use:

function GetInputField(fromForm: IHTMLFormElement;
  const inputName: string;
  const instance: integer=0): HTMLInputElement;
var
  field: IHTMLElement;
begin
  field := fromForm.Item(inputName,instance) as IHTMLElement;
  if Assigned(field) then
  begin
    if field.tagName = 'INPUT' then
    begin
      result := field as HTMLInputElement;
      exit;
    end;
  end;
  result := nil;
end;

Calling it in the same way as you would GetFieldValue (above).


Set the value of a named field

To set the value of a field:

procedure SetFieldValue(theForm: IHTMLFormElement;
  const fieldName: string; const newValue: string;
  const instance: integer=0);
var
  field: IHTMLElement;
  inputField: IHTMLInputElement;
  selectField: IHTMLSelectElement;
  textField: IHTMLTextAreaElement;
begin
  field := theForm.Item(fieldName,instance) as IHTMLElement;
  if Assigned(field) then
  begin
    if field.tagName = 'INPUT' then
    begin
      inputField := field as IHTMLInputElement;
      if (inputField.type_ <> 'radio') and
         (inputField.type_ <> 'checkbox')
      then
        inputField.value := newValue
      else
        inputField.checked := (newValue = 'checked');
    end
    else if field.tagName = 'SELECT' then
    begin
      selectField := field as IHTMLSelectElement;
      selectField.value := newValue;
    end
    else if field.tagName = 'TEXTAREA' then
    begin
      textField := field as IHTMLTextAreaElement;
      textField.value := newValue;
    end;
  end;
end;

and to call it:

procedure TMyForm.Button1Click(Sender: TObject);
var
  document: IHTMLDocument2;
  theForm: IHTMLFormElement;
  index: integer;
begin
  document := TWebBrowser.Document as IHTMLDocument2;
  theForm := GetFormByNumber(WebBrowser.Document as IHTMLDocument2,0);
  SetFieldValue(theForm,'name','Brian Cryer');


Submit the form

The above functions demonstrate how to read values from a form and how to set values in the form. The only thing remaining is how to submit a form. This is simply:

theForm.submit;

for example:

procedure TMyForm.Button1Click(Sender: TObject);
var
  document: IHTMLDocument2;
  theForm: IHTMLFormElement;
  index: integer;
begin
  document := TWebBrowser.Document as IHTMLDocument2;
  theForm := GetFormByNumber(document,0);
  SetFieldValue(theForm,'name','Brian Cryer');
  theForm.submit;

Note: Be aware that there are cases where this will not achieve the expected effect. This is because some forms are not actually submitted, but the action is either performed in response to JavaScript on a button or by the "onsubmit" handler of the form.


Other examples

Other examples of reading and writing form elements can be found on the following pages:


These notes are believed to be correct for Delphi 6 and Delphi 7, and may apply to other versions as well.



About the author: is a dedicated software developer and webmaster. For his day job he develops websites and desktop applications as well as providing IT services. He moonlights as a technical author and consultant.