Delphi3 started to have the TWebBrowser component, but it appeared in the form of ActiveX controls at that time and needed to be introduced by itself. In the subsequent 4.0 and 5.0, it appeared as one of the Internet component groups after encapsulating shdocvw.dll. The component panel is on. I often hear people scold Delphi for doing very poorly. This time, TWebBrowser is a Microsoft item, so it will naturally not be much better. Although there are everything on MSDN, the content is too complicated. If there is no entry point, it will be more. It is an annoying thing. The feeling it gives people when searching can be described in one sentence: very complex and very complicated.
Here are some experiences about using TWebBrowser to make programs and some examples and information collected from the Internet. I have sorted it out, hoping to bring some help to friends who are interested in programming with TWebBrowser.
1. Initialization & Finalization
When you execute a method of TWebBrowser to perform the desired operation, such as ExecWB, etc., you may have encountered errors such as "trying to activate the unregistered missing target" or "OLE object not registered", or there is no error but it is not done. To the desired result, such as not being able to copy the selected web page content to the clipboard, etc. When I used it to program, I found that ExecWB sometimes works but sometimes doesn't work. Adding TWebBrowser to the default project main window generated by Delphi will not cause the "OLE object not registered" error when running. It was also an accidental opportunity that I realized that OLE objects need to be initialized and terminated (there are too few things to understand).
I used the method mentioned in my previous article "Delphi Program Window Animation & Solutions for Normal Arrangement Tile". When I ran the error mentioned above, I guessed that there should be statements such as OleInitialize, so I found and added the following sentences and finally got it done! The reason, I think it is probably because TWebBrowser is an embedded OLE object and is not a VCL written in Delphi.
Initialization
OleInitialize(nil);
Finalization
try
OleUninitialize;
except
end;
These sentences are placed after all the statements in the main window, before "end."
-------------------------------------------------- ---------------------------------
2. EmptyParam
In Delphi 5, the Navigate method of TWebBrowser is overloaded multiple times:
PRocedure Navigate(const URL: WideString); overload;
procedure Navigate(const URL: WideString; var Flags:
OleVariant); overload;
procedure Navigate(const URL: WideString; var Flags:
OleVariant; var TargetFrameName: OleVariant); overload;
procedure Navigate(const URL: WideString; var Flags:
OleVariant; var TargetFrameName: OleVariant; var PostData:
OleVariant); overload;
procedure Navigate(const URL: WideString; var Flags:
OleVariant; var TargetFrameName: OleVariant; var PostData:
OleVariant; var Headers: OleVariant); overload;
In actual applications, when calling the latter method, since we rarely use the latter parameters, but the function declaration requires variable parameters, the general method is as follows:
var
t:OleVariant;
Begin
webbrowser1.Navigate(edit1.text,t,t,t,t);
end;
It is very troublesome to define the variable t (and there are still many places to use it). In fact, we can use EmptyParam instead (EmptyParam is a common Variant empty variable, don't assign a value to it), just one sentence:
webbrowser1.Navigate(edit1.text,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
Although it's a little longer, it's much more convenient than defining variables every time. Of course, the first method can also be used.
webbrowser1.Navigate(edit1.text)
-------------------------------------------------- ---------------------------------
3. Common command operations can be completed using the ExecWB method. ExecWB is also reloaded many times:
procedure ExecWB(cmdID: OLECMDID; cmdexecopt:
OLECMDEXECOPT); overload;
procedure ExecWB(cmdID: OLECMDID; cmdexecopt: OLECMDEXECOPT;
var pvaIn:
OleVariant); overload;
procedure ExecWB(cmdID: rOLECMDID; cmdexecopt:
OLECMDEXECOPT; var pvaIn:
OleVariant; var pvaOut: OleVariant); overload;
Open: The "Open Internet Address" dialog box pops up, and the CommandID is OLECMDID_OPEN (if the browser version is IE5.0,
Then this command is not available).
Save As: Call the Save As dialog box.
ExecWB(OLECMDID_SAVEAS,OLECMDEXECOPT_DODEFAULT,
EmptyParam,
EmptyParam);
Print, print preview and page settings: Call the "Print", "Print Preview" and "Page Settings" dialog boxes (IE5.5 and above only support the "Type" versions
print preview, so implementation should check whether this command is available).
ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DODEFAULT,
EmptyParam,
EmptyParam);
if QueryStatusWB(OLECMDID_PRINTPREVIEW)=3 then
ExecWB(OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DODEFAULT,
EmptyParam,EmptyParam);
ExecWB(OLECMDID_PAGESETUP, OLECMDEXECOPT_DODEFAULT,
EmptyParam,
EmptyParam);
Cut, copy, paste, select all: There is no need to say much about the function, it is important to note that cutting and pasting not only provides text for editing frames, but also non-editing on web pages.
The text of the editing box is also effective. If used well, you may be able to make something with special functions. Obtain its command enable status
There are two ways to execute commands (taking copy as an example, cutting, pasting and selecting all will replace the respective keywords.
Just change it, namely CUT, PASTE and SELECTALL, respectively):
A. Use the QueryStatusWB method of TWebBrowser.
if(QueryStatusWB(OLECMDID_COPY)=OLECMDF_ENABLED) or
OLECMDF_SUPPORTED) then
ExecWB(OLECMDID_COPY, OLECMDEXECOPT_DODEFAULT,
EmptyParam,
EmptyParam);
B. Use the QueryCommandEnabled method of IHTMLDocument2.
var
Doc: IHTMLDocument2;
Begin
Doc :=WebBrowser1.Document as IHTMLDocument2;
if Doc.QueryCommandEnabled('Copy') then
Doc.ExecCommand('Copy',false,EmptyParam);
end;
Search: Refer to the ninth "Find" function.
-------------------------------------------------- ---------------------------------
4. Font size
Similar to the five items from "maximum" to "minimum" on the "font" menu (corresponding to integers 0~4, Largest, etc., assuming that the names of the five menu items are as follows, Tag
The properties are set to 0~4 respectively).
A. Read the font size of the current page.
var
t: OleVariant;
Begin
WebBrowser1.ExecWB(OLECMDID_ZOOM,
OLECMDEXECOPT_DONTPROMPTUSER,
EmptyParam,t);
case t of
4: Largest.Checked :=true;
3: Larger.Checked :=true;
2: Middle.Checked :=true;
1: Small.Checked :=true;
0: Smallest.Checked :=true;
end;
end;
B. Set the page font size.
Largest.Checked :=false;
Larger.Checked :=false;
Middle.Checked :=false;
Small.Checked :=false;
Smallest.Checked :=false;
TMenuItem(Sender).Checked :=true;
t :=TMenuItem(Sender).Tag;
WebBrowser1.ExecWB(OLECMDID_ZOOM,
OLECMDEXECOPT_DONTPROMPTUSER,
t,t);
-------------------------------------------------- ---------------------------------
5. Add to favorites and organize favorites
const
CLSID_ShellUIHelper: TGUID =
'{64AB4BB7-111E-11D1-8F79-00C04FC2FBE1}';
var
p:procedure(Handle: THandle; Path: PChar); stdcall;
procedure TForm1.OrganizeFavorite(Sender: Tobject);
var
H: HWnd;
Begin
H := LoadLibrary(PChar('shdocvw.dll'));
if H <> 0 then
Begin
p := GetProcAddress(H, PChar('DoOrganizeFavDlg'));
if Assigned(p) then p(application.Handle,
PChar(FavFolder));
end;
FreeLibrary(h);
end;
procedure TForm1.AddFavorite(Sender: TObject);
var
ShellUIHelper: ISHellUIHelper;
url, title: Olevariant;
Begin
Title := Webbrowser1.LocationName;
Url := Webbrowser1.LocationUrl;
if Url <> '' then
Begin
ShellUIHelper := CreateComObject(CLSID_SHELLUIHELPER) as
IShellUIHelper;
ShellUIHelper.AddFavorite(url, title);
end;
end;
The method of using the above method to open the "Add to Favorites" dialog box through the ISHellUIHelper interface is relatively simple, but there is a drawback, that is, the window opened is not a mode window, but is independent of the application. It is conceivable that if you use the same method as the OrganizeFavorite procedure to open the dialog, you can naturally implement the mode window because you can specify the handle of the parent window (the effect is the same as opening the "Add to Favorite" dialog in Explorer and IE) . The problem is obviously this. The author of the above two processes only knew the prototype of DoOrganizeFavDlg in shdocvw.dll but not the prototype of DoAddToFavDlg, so he had to use the ISHellUIHelper interface to implement it (maybe it was not rigorous enough and thought it didn't matter if it was a pattern window? ).
The following process will tell you the function prototype of DoAddToFavDlg. It should be noted that the dialog box opened in this way does not perform the "Add to Favorites" operation. It just tells the application user whether "OK" is selected, and at the same time returns the second parameter of DoAddToFavDlg, the user wants to place the Internet shortcut. The path to create the .Url file is done by the application itself.
procedure TForm1.AddFavorite(IE: TEmbeddedWB);
procedure CreateUrl(AUrlPath, AUrl: PChar);
var
URLfile: TIniFile;
Begin
URLfile := TIniFile.Create(String(AUrlPath));
RLfile.WriteString('InternetShortcut', 'URL',
String(AUrl));
RLfile.Free;
end;
var
AddFav: function(Handle: THandle;
UrlPath: PChar; UrlPathSize: Cardinal;
Title: PChar; TitleSize: Cardinal;
FavIDLIST: pItemIDList): Bool; stdcall;
FDoc: IHTMLDocument2;
UrlPath, url, title: array[0..MAX_PATH] of char;
H: HWnd;
pidl: pItemIDList;
FRetOK: Bool;
Begin
FDoc := IHTMLDocument2(IE.Document);
if FDoc = nil then exit;
StrPCopy(Title, FDoc.Get_title);
StrPCopy(url, FDoc.Get_url);
if Url <> '' then
Begin
H := LoadLibrary(PChar('shdocvw.dll'));
if H <> 0 then
Begin
SHGetSpecialFolderLocation(0, CSIDL_FAVORITES, pidl);
AddFav := GetProcAddress(H, PChar('DoAddToFavDlg'));
if Assigned(AddFav) then
FRetOK :=AddFav(Handle, UrlPath, Sizeof(UrlPath),
Title, Sizeof(Title), pidl)
end;
FreeLibrary(h);
if FRetOK then
CreateUrl(UrlPath, Url);
end
end;
-------------------------------------------------- ---------------------------------
6. Make WebBrowser focus
TWebBrowser is very special. The SetFocus method inherited from TWinControl does not allow the documents it contains to gain focus, so it cannot use the Internet immediately.
Explorer itself has shortcut keys, the solution is as follows:
procedure TForm1.SetFocusToDoc;
Begin
if WebBrowser1.Document <> nil then
with WebBrowser1.Application as IOleobject do
DoVerb(OLEIVERB_UIACTIVATE, nil, WebBrowser1, 0, Handle,
GetClientRect);
end;
Apart from that, I also found an easier way, which is listed here:
if WebBrowser1.Document <> nil then
IHTMLWindow2(IHTMLDocument2(WebBrowser1.Document).ParentWindow).focus
Just found an easier way, perhaps the easiest:
if WebBrowser1.Document <> nil then
IHTMLWindow4(WebBrowser1.Document).focus
Also, you need to determine whether the document has gained focus:
if IHTMLWindow4(WebBrowser1.Document).hasfocus then
-------------------------------------------------- ---------------------------------
7. Click the "Submit" button
Just as there is a "default" button on each form in the program, each Form on the web page also has a "default" button - that is, a button with the attribute "Submit". When the user presses the Enter key It is equivalent to clicking "Submit" on the mouse. However, TWebBrowser does not seem to respond to the Enter key, and even if the KeyPreview of the form containing the TWebBrowser is set to True, the keys sent by the user to TWebBrowser cannot be intercepted in the KeyPress event of the form.
My solution is to use the ApplicatinEvents component or write the OnMessage event of the TApplication object by yourself, judge the message type and respond to the keyboard message. As for clicking the "Submit" button, you can do it by analyzing the web source code, but I have found a simpler and faster method. There are two types. The first one is what I thought of myself, and the other is what someone else wrote. The code is provided here for everyone for reference.
A. Use the SendKeys function to send the Enter key to WebBrowser
In Delphi
5 There is a SndKey32.pas file in the Info/Extras/SendKeys directory on the CD, which contains two functions SendKeys and AppActivate. We can use the SendKeys function to send the Enter key to the WebBrowser. I am using this method now. It's very simple. When WebBrowser gets focus (does not require the documents contained in WebBrowser to get focus), use one statement:
Sendkeys('~',true);// press RETURN key
The detailed parameter description of the SendKeys function, etc., are included in the SndKey32.pas file.
B. Pass the received keyboard message to WebBrowser in the OnMessage event.
procedure TForm1.ApplicationEvents1Message(var Msg: TMsg;
var Handled: Boolean);
{fixes the malfunction of some keys within webbrowser
control}
const
StdKeys = [VK_TAB, VK_RETURN]; { standard keys }
ExtKeys = [VK_DELETE, VK_BACK, VK_LEFT, VK_RIGHT]; {
extended keys }
fExtended = $01000000; { extended key flag }
Begin
Handled := False;
with Msg do
if ((Message >= WM_KEYFIRST) and (Message <= WM_KEYLAST))
and
((wParam in StdKeys) or
{$IFDEF VER120}(GetKeyState(VK_CONTROL) < 0) or {$ENDIF}
(wParam in ExtKeys) and
((lParam and fExtended) = fExtended)) then
try
if IsChild(Handle, hWnd) then { handles all browser
related messages }
Begin
with {$IFDEF
VER120}Application_{$ELSE}Application{$ENDIF} as
IOleInPlaceActiveObject do
Handled := TranslateAccelerator(Msg) = S_OK;
If not Handled then
Begin
Handled := True;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
except
end;
end; // MessageHandler
(This method comes from EmbeddedWB.pas)
-------------------------------------------------- ---------------------------------
8. Get the web page source code and Html directly from TWebBrowser
Let’s first introduce an extremely simple method to obtain the source code of the web page that TWebBrowser is accessing. The general method is to use the impersistStreamInit interface provided by the Document object in the TWebBrowser control to implement it. Specifically, check whether the WebBrowser.Document object is valid, and exit if it is invalid; then obtain the IPersistStreamInit interface, then obtain the HTML source code size, allocate the global heap memory block , create a stream, and then write HTML text into the stream. Although the program is not complicated, there are simpler methods, so the implementation code is no longer given. In fact, basically all IE functions TWebBrowser should have a relatively simple way to implement them, and the same is true for obtaining web page source code. The following code displays the web page source code in Memo1.
Memo1.Lines.Add(IHtmlDocument2(WebBrowser1.Document).Body.OuterHtml);
At the same time, it is very simple to save HTML files as text files when browsing TWebBrowser, and no syntax parsing tools are needed, because TWebBrowser is also completed, as follows:
Memo1.Lines.Add(IHtmlDocument2(WebBrowser1.Document).Body.OuterText);
-------------------------------------------------- ---------------------------------
9. "Find" function
The search dialog box can be called by pressing the key Ctrl-F when the document gets focus. In the program, the member function Exec of the IOleCommandTarget object is called to execute the OLECMDID_FIND operation. The method given below is how to use code in the program to make it. Text selection, that is, you can design the search dialog box yourself.
var
Doc: IHtmlDocument2;
TxtRange: IHtmlTxtRange;
Begin
Doc :=WebBrowser1.Document as IHtmlDocument2;
Doc.SelectAll; //This is abbreviation. For the method to select all documents, please refer to the third command operation.
//This sentence is particularly important, because the premise that the method of the IHtmlTxtRange object can be operated is
//Document already has a text selection area. Since the following statement is executed, it will not
//See the process of selecting all documents.
TxtRange :=Doc.Selection.CreateRange as IHtmlTxtRange;
TxtRange.FindText('Text to be searched',0.0);
TxtRange.Select;
end;
Also, you can get the currently selected text content from Txt.Get_text, which is useful at some point.
-------------------------------------------------- ---------------------------------
10. Extract all links in the web page
This method comes from a friend of the Monopoly Forum hopfield forum answering a question. I wanted to experiment myself, but I always failed.
var
doc:IHTMLDocument2;
all:IHTMLElementCollection;
len,i:integer;
item:OleVariant;
Begin
doc:=WebBrowser1 .Document as IHTMLDocument2;
all:=doc.Get_links; //doc.Links is also OK
len:=all.length;
for i:=0 to len-1 do begin
item:=all.item(i,varempty); //EmpryParam is also OK
memo1.lines.add(item.href);
end;
end;
-------------------------------------------------- ---------------------------------
11. Set the encoding of TWebBrowser
Why do I always miss a lot of opportunities? In fact, I should have thought of it for a long time, but a difference in thought will make it a world of difference. If I had thought about it more and tried it more, it would not have been ranked 11th. Here is a function, which is unimaginably simple to solve.
procedure SetCharSet(AWebBrowser: TWebBrowser; ACharSet:
String);
var
RefreshLevel: OleVariant;
Begin
IHTMLDocument2(AWebBrowser.Document).Set_CharSet(ACharSet);
RefreshLevel :=7; //This 7 should come from the registry to help with bugs.
AWebBrowser.Refresh2(RefreshLevel);
End;