?
Solved

Saving IE page with button click (500 points)

Posted on 2005-02-25
15
Medium Priority
?
537 Views
Last Modified: 2011-10-03
When I click a button on the Delphi form, I need the currently open page of Internet Explorer to be saved. If it can be saved to a certain directory on the user's hard-drive, so much the better.

I am using Delphi 6.  This is worth 500 points as it is/was needed yesterday!  Many thanks for your help.
0
Comment
Question by:rincewind666
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
  • 2
  • +3
15 Comments
 
LVL 13

Expert Comment

by:BlackTigerX
ID: 13406558
what if there are more than one instances of IExplorer running? you want to save all the pages?
0
 

Author Comment

by:rincewind666
ID: 13406714
No - just the current page. The user loads a page and clicks my button instead of going to File/Save as... in IE.
0
 
LVL 13

Expert Comment

by:BlackTigerX
ID: 13406742
is it a TWebBrowser inside your application?

for that see this article:
http://delphi.about.com/od/internetintranet/l/aa062904a.htm

or is it for an external instance of Internet Explorer?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:rincewind666
ID: 13408080
It's an external IE - as supplied with the user's Windows.
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 13408846
Downloading and parsing a url is described here
http://delphi.about.com/od/internetintranet/l/aa062502a.htm
All that is left is to get the url from the current IE window
0
 
LVL 11

Expert Comment

by:calinutz
ID: 13411263
Try this link . It's the best there is. You can find out how to get the Address from the running IE, how to download a html from a location, and everything else.
http://www.euromind.com/iedelphi/app.htm
Check all the links on the page
Cheers
0
 
LVL 11

Expert Comment

by:calinutz
ID: 13411295
Or try this:
Function GetText(WindowHandle: hwnd):string;

var

txtLength : integer;

buffer: string;

begin

 TxtLength := SendMessage(WindowHandle, WM_GETTEXTLENGTH, 0, 0);

 txtlength := txtlength + 1;

 setlength (buffer, txtlength);

 sendmessage (WindowHandle,wm_gettext, txtlength, longint(@buffer[1]));

 result := buffer;

end;

 

function GetURL:string;

var

ie,toolbar,combo,

comboboxex,edit,

worker,toolbarwindow:hwnd;

begin

� ie := FindWindow(pchar('IEFrame'),nil);

� worker := FindWindowEx(ie,0,'WorkerA',nil);

� toolbar := FindWindowEx(worker,0,'rebarwindow32',nil);

� comboboxex := FindWindowEx(toolbar, 0, 'comboboxex32', nil);

� combo := FindWindowEx(comboboxex,0,'ComboBox',nil);

� edit := FindWindowEx(combo,0,'Edit',nil);

� toolbarwindow := FindWindowEx(comboboxex, 0, 'toolbarwindow32', nil);

 

� result := GetText(edit);

{-------------------------------------------------------}

 

procedure TForm1.Button1Click(Sender: TObject);

begin

showmessage(GetURL);

end;
0
 

Author Comment

by:rincewind666
ID: 13411438
I got the following error, calinutz:

[Error] Unit1.pas(62): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(64): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(66): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(68): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(70): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(72): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(74): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(78): Illegal character in input file: '&' ($26)
[Error] Unit1.pas(81): Statement expected but 'PROCEDURE' found
[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'

I need the user to be able to see the page before saving. If correct, they can then save it by clicking a button....
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 13413113
uses
  SHDocVw, MSHtml;

{ ...}
var
  ShellWindows: IShellWindows;
  Browser: IWebBrowser2;
  i: integer;
  Doc: IHTMLDocument2;
{ ...}
  { Use ShellWindows to get the active browser window }
  ShellWindows := CoShellWindows.Create;
  for i := 0 to ShellWindows.Count - 1 do
  begin
    if Supports(ShellWindows.Item(i), IWebBrowser2, Browser) then
    begin
      Doc := Browser.Document as IHTMLDocument2;
      Memo1.Clear;
      Memo1.Lines.Add(Doc.body.innerText);
{ ...}
0
 
LVL 9

Expert Comment

by:ginsonic
ID: 13413114
uses
  MSHTML_TLB, ActiveX;


function GetHTMLCode(WB: IWebbrowser2; ACode: TStrings): Boolean;
var
  ps: IPersistStreamInit;
  s: string;
  ss: TStringStream;
  sa: IStream;
begin
  ps := WB.document as IPersistStreamInit;
  s := '';
  ss := TStringStream.Create(s);
  try
    sa:= TStreamAdapter.Create(ss, soReference) as IStream;
    Result := Succeeded(ps.Save(sa, Bool(True)));
    if Result then ACode.Add(ss.Datastring);
  finally
    ss.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ShellWindow: IShellWindows;
  WB: IWebbrowser2;
  spDisp: IDispatch;
  IDoc1: IHTMLDocument2;
  k: Integer;
begin
  ShellWindow := CoShellWindows.Create;
  // get the running instance of Internet Explorer
  for k := 0 to ShellWindow.Count do
  begin
    spDisp := ShellWindow.Item(k);
    if spDisp = nil then Continue;
    // QueryInterface determines if an interface can be used with an object
    spDisp.QueryInterface(iWebBrowser2, WB);
    if WB <> nil then
    begin
      WB.Document.QueryInterface(IHTMLDocument2, iDoc1);
      if iDoc1 <> nil then
      begin
        WB := ShellWindow.Item(k) as IWebbrowser2;
        begin
          // Add HTML Code to Memo
          Memo1.Lines.Add('****************************************');
          Memo1.Lines.Add(WB.LocationURL);
          Memo1.Lines.Add('****************************************');
          GetHTMLCode(WB, Memo1.Lines);
        end;
      end;
    end;
  end;
end;  
0
 

Author Comment

by:rincewind666
ID: 13434173
ginsonic, I am getting the following error:

[Error] Unit1.pas(27): Undeclared identifier: 'IWebbrowser2'
[Error] Unit1.pas(34): Missing operator or semicolon
[Error] Unit1.pas(34): Operator not applicable to this operand type
[Error] Unit1.pas(49): Undeclared identifier: 'IShellWindows'
[Error] Unit1.pas(55): Undeclared identifier: 'CoShellWindows'
[Error] Unit1.pas(55): Missing operator or semicolon
[Error] Unit1.pas(57): 'DO' expected but identifier 'Count' found
[Error] Unit1.pas(59): Missing operator or semicolon
[Error] Unit1.pas(63): Operator not applicable to this operand type
[Error] Unit1.pas(65): Missing operator or semicolon
[Error] Unit1.pas(68): Missing operator or semicolon
[Error] Unit1.pas(68): Operator not applicable to this operand type
[Error] Unit1.pas(71): Undeclared identifier: 'Memo1'
[Error] Unit1.pas(71): Missing operator or semicolon
[Error] Unit1.pas(72): Missing operator or semicolon
[Error] Unit1.pas(72): Missing operator or semicolon
[Error] Unit1.pas(72): 'END' expected but ')' found
[Error] Unit1.pas(79): '.' expected but ';' found
[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'


Also please note my comment above: It's an external IE - as supplied with the user's Windows.
0
 
LVL 5

Expert Comment

by:DeerBear
ID: 13442308
Did you try using IE automation?

Cheers,

Andrew
0
 

Author Comment

by:rincewind666
ID: 13444584
What is IE automation?
0
 
LVL 5

Accepted Solution

by:
DeerBear earned 1000 total points
ID: 13444861
IE Automation is the COM object hierarchy exposed by IE.

Delphi does export TWebBrowser component, but that's not the only one available through IE.
There's a component(namely, TInternetExplorer) that does just that - interact with IE windows.

Project |Import Type Library|select "Microsoft Internet Controls" and you gain access to it.
Now, looking at the imported SHDOC_W type library, you'll find these constants:

// Constants for enum OLECMDID
type
  OLECMDID = TOleEnum;
const
  OLECMDID_OPEN = $00000001;
  OLECMDID_NEW = $00000002;
  OLECMDID_SAVE = $00000003;
  OLECMDID_SAVEAS = $00000004;

OLECMDID_SAVEAS is the one you want. Now, if you look back into the TInternetExplorer component, you'll find this method:

procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT); overload;
procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT; var pvaIn: OleVariant); overload;
procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT; var pvaIn: OleVariant;
                            var pvaOut: OleVariant); overload;

It has 3 overloaded versions, you can experiment a bit and find out which one to use.
Or go to MSDN to get further help.
I did a quick search for you but there doesn't seem to be any useful information on how to use the OLECMDID_SAVEAS command. Anyway, my *wild* guess at using it is a syntax like the following:

var DestFileName : WideString;//OleVariant compliant string
begin
  DestFileName := 'Test.html';
  IE.ExecWB(OLECMDID_SAVEAS,OLECMDEXECOPT_DONTPROMPTUSER,0,DestFileName);
end;

Try this and report here :D

Cheers,

Andrew
0
 

Author Comment

by:rincewind666
ID: 13900710
I got errors with the other solutions so I am awarding the points to DeerBear - perhaps it may help others.  Maybe this was harder than I thought. Anyway I will close this now.  Thanks to everyone for trying to help.
0

Featured Post

Want to be a Web Developer? Get Certified Today!

Enroll in the Certified Web Development Professional course package to learn HTML, Javascript, and PHP. Build a solid foundation to work toward your dream job!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses
Course of the Month8 days, 22 hours left to enroll

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question