Are you one of those people who think the Internet is just a fad, something that will never last? If so, let me tell you something...you\'re wrong! The Internet is huge and it\'s getting bigger every day. In part, the Internet is about the Web and about people spending hour after hour browsing the Web. But the Internet is also about file transfers, email, and electronic commerce. The Internet is big business. It isn\'t going away anytime soon, so you might want to polish your Internet programming skills. Thankfully, Delphi makes it easy to experiment with Internet programming and to do serious Internet programming as well.
Today, you look at some aspects of Internet programming with Delphi. There\'s a whole world waiting out there on the Internet, so let\'s get to it.
Internet Components Available in Delphi
The Internet components in Delphi are located on the Internet page of the Component palette and come in two categories. The first category is a group of components provided by NetMasters. With one exception, these are native VCL components. The exception is the THTML control, which is an ActiveX control. Table BD.1 lists the NetMasters controls and provides a description of each control. The controls are listed in the order in which they appear on the Component palette.
TABLE BD.1. NETMASTERS ACTIVEX INTERNET CONTROLS.
Control Description
TNMDayTime Obtains the date and time from Internet daytime servers.
TNMEcho Sends text to and receives text from Internet echo servers.
TNMFinger Obtains information about a user from an Internet finger server.
TNMFTP Performs file transfers between networked machines using FTP (File Transfer Protocol).
TNMHTTP Performs file transfers using HTTP (Hypertext Transport Protocol). Hypertext documents are normally viewed in a Web browser. You use THTTP to retrieve Web documents that don\'t need to be displayed in a Web browser.
TNMMsg Sends simple ASCII text messages using TCP/IP.
TNMMSGServ Receives messages sent with the TNMMsg control.
TNMNNTP Sends messages to and receives messages from Internet news servers using NNTP (Networking News Transfer Protocol).
TNMPOP3 Retrieves email messages from mail servers using POP3 (Post Office Protocol).
TNMUUProcessor Encodes or decodes MIME or uuencoded files.
TNMSMTP Sends email through SMTP (Simple Mail Transfer Protocol) mail servers.
TNMStrm Sends data streams to a network or Internet stream server.
TNMStrmServ Receives streams sent by the TNMStrm control.
TNMTime Obtains the date and time from Internet time servers.
TNMUDP Transfers data across networks using UDP (User Datagram Protocol).
TPowersock Encapsulates the Winsock API.
TNMGeneralServer Used for general TCP/IP servers.
THTML Displays HTML (Hypertext Markup Language) files. This is a Web
browser component.
TNMURL Converts URL data to a readable string and string data to URL format.
The second category of controls includes native VCL components provided by Borland. The TClientSocket and TServerSocket components come with both the Professional and Client/Server versions of Delphi. The Web Broker components (TWebDispatcher, TPageProducer, TQueryTableProducer, and TDataSetTableProducer) come with only the Client/Server version. The VCL Internet components are listed in Table BD.2.
TABLE BD.2. NATIVE VCL INTERNET COMPONENTS.
Component Description
TClientSocket Manages a TCP/IP client socket connection.
TServerSocket Manages a TCP/IP server socket connection.
TWebDispatcher Converts an ordinary data module to a Web module.
TPageProducer Enables building of dynamic HTML pages.
TQueryTableProducer Takes TQuery results and generates an HTML document from them.
TDataSetTableProducer Takes TDataSet records and generates an HTML document from them.
These two groups of controls give you all the power you need to build high-quality Internet applications.
Building a Web Browser
One of the most visible Internet programming tasks is building a Web browser. Certainly it\'s the most glamorous. The good news is that it can also be the easiest.
Who Needs Yet Another Browser?
You might be wondering why anyone would want to build a Web browser. After all, the world already has Netscape Navigator and Internet Explorer, so who needs another browser? True enough, you probably aren\'t going to try to build a Web browser that competes with Netscape or Microsoft. On the other hand, consider a company that has hundreds or even thousands of employees who need access to the Web. It can be very costly to license thousands of copies of a commercial Web browser. On the other hand, you can write a quality Web application with Delphi in just a few hours, thereby saving the company a lot of money.
Another reason a company might want a custom Web browser is to restrict access to the Web. For example, there might be sites on the Internet that employees have to visit from time to time. A custom Web browser enables access to authorized sites on the Web but not to any other (unauthorized) sites. In fact, a custom browser is perfect for your kids!
Finally, one of the most compelling reasons for a custom Web browser is an intranet. An intranet is a Web site that is local to a particular network. An intranet can contain a variety of information for a company\'s internal use--information on company benefits, company policies, an employee address book, meeting schedules, or even information on the company bowling league. A custom Web application can provide access to an intranet and prevent access to the Internet.
So with that in mind, you\'ll build a simple Web browser. You\'ll probably be surprised how easy it is.
First Steps in Building Your Browser
The THTML control is a ready-to-use Web browser. All you have to do is place one of these controls on a form and call the RequestDoc method. Well, that might be a little oversimplified, but you can display a Web document from anywhere on the Internet as easily as that. With that in mind, let me show you how quickly you can write a Web browser application. Here are the first steps:
1. Start with a new application. Change the form\'s Name property to WebMain and the Caption property to EZ Web Browser.
2. Place a Panel component on the form and change its Align property to alTop and its Height property to 60. Clear the Caption property.
3. Place a ComboBox component on the panel. Move it near the top of the panel and make it as wide as the panel itself. Change the Name property to URLComboBox. Change the Text property to an URL of your choice (try
http://www.turbopower.com). Double-click the Constraints property and change the AnchorHorz constraint to akStretch.
4. Place a StatusBar component on the form. It will automatically position itself at the bottom of the form. Change its Name property to StatusBar and its SimplePanel property to True.
5. Place an HTML control in the middle of the form. Change its Align property to alClient. The HTML control fills the screen. Change the Name property to HTML.
Now your form should look similar to the one shown in Figure BD.1. If your application doesn\'t look exactly like Figure BD.1, adjust as necessary or just leave it. (A little individuality isn\'t a bad thing, after all.)
At this point, you should save the project. Save the form as WebBrwsU.pas and the project as WebBrows.dpr. Now you\'ll add just enough functionality to make the browser do something useful.
FIGURE BD.1. Your new Web browser after the first steps.
6. Click on the URL combo box. Generate an event handler for the OnClick event. Type the following code in the event handler:
if URLComboBox.Text <> `\' then
HTML.RequestDoc(URLComboBox.Text);
The RequestDoc method loads the requested document after first checking that the combo box contains text.
7. Now generate an event handler for the OnKeyPress event. Type the following code in the event handler:
if Key = Char(VK_RETURN) then begin
Key := #0;
if URLComboBox.Text = `\' then
Exit;
URLComboBoxClick(Sender);
end;
This code first checks the Key parameter to see whether the Enter key was pressed. If so, it sets Key to 0 and calls the URLComboBoxTest method (created in step 6). Setting Key to 0 prevents the speaker from beeping when the Enter key is pressed. The call to the URLComboBoxClick method loads the URL into the Web browser.
8. Now compile and run the program. Type an URL in the combo box and press Enter. If you typed in a valid URL, the page will load in the HTML control.
Wow! A Web browser in 15 minutes! Notice that the browser acts like any other Web browser...well, sort of. You need to add a lot of functionality, but it\'s a start.
--------------------------------------------------------------------------------
NOTE: If you are fortunate enough to have a full-time Internet connection, your new browser will work immediately. If you are using dial-up networking with auto dial enabled, the dialer will start automatically and connect to your Internet service provider (ISP). If you don\'t have dial-up networking installed, you have to connect to the Internet manually before running the program.
--------------------------------------------------------------------------------
Adding a Progress Indicator
You now have a good start on your Web browser. One of the features you are missing is some status information on each page as it loads. What you\'ll do is add a routine that updates the status bar as a page loads. You make use of the THTML control\'s OnUpdateRetrieval and OnEndRetrieval events to obtain periodic status updates. You will use the GetBytesTotal and GetBytesDone methods to calculate a percentage and then display the percentage loaded in the status bar. Ready?
1. Click on the HTML control on your form. Generate an event handler for the OnUpdateRetrieval event. Add code to the event handler so that it looks like this:
procedure TWebMain.HTMLUpdateRetrieval(Sender: TObject);
var
Total : Integer;
Done : Integer;
Percent : Integer;
begin
Total := HTML.RetrieveBytesTotal;
Done := HTML.RetrieveBytesDone;
if (Total = 0) or (Done = 0) then
Percent := 0
else
Percent := ((Done * 100) div Total);
StatusBar.SimpleText := Format(
`Getting Document: %d%% of %dK\', [Percent, Total div 1024]);
end;
2. Now generate an event handler for the OnEndRetrieval event. Type this code in the event handler:
StatusBar.SimpleText := `Done\';
Take a closer look at the code in step 1. There isn\'t very much to it. The GetBytesTotal method tells you how many bytes are in the document or the embedded object currently being loaded (objects include images). The GetBytesDone method gives the number of bytes that have been retrieved for the page or object up to this point. From there it\'s a simple matter to calculate the percentage of the object that has been retrieved. Finally, you format a string with the information obtained from the HTML control and send it to the status bar. The code in step 2 simply updates the status bar after the entire document has been loaded.
Run the program again and watch what happens when you load a page. The status bar shows the percentage loaded for the page and for any embedded objects.
Some Finishing Touches
Now for some finishing touches. First, you\'ll add some buttons beneath the URL combo box. (For a peek at the finished product, see Figure BD.2.) Here goes:
1. Place a button on the panel beneath the URL combo box. Make its Name property GoBtn and change its Caption to Go!.
2. Generate an event handler for the OnClick event for the new button. Enter the following code in the event handler:
URLComboBoxClick(Self);
3. Place another button on the panel, just to the right of the first button. Change the Name to StopBtn and the Caption to Stop.
4. Generate an event handler for the OnClick event for this button and type the following code in the event handler:
HTML.Cancel(0);
StatusBar.SimpleText := `Done\';
5. Place a third button on the panel to the right of the other two buttons. Change the Name property to ReloadBtn. Change the Caption property to Reload.
6. Create an event handler for the OnClick event for this button and enter the same code as in step 2:
URLComboBoxClick(Self);
7. Place a fourth (and final) button on the panel. Change the Name to SourceBtn and change the Caption to View Source.
8. Create an event handler for the OnClick event and enter this code:
HTML.ViewSource := not HTML.ViewSource;
if HTML.ViewSource then
SourceBtn.Caption := `View Document\'
else
SourceBtn.Caption := `View Source\';
Your form should now look like the one shown in Figure BD.2.
FIGURE BD.2. The EZ Web Browser with buttons in place.
These steps introduce a couple of new THTML elements. The Cancel method stops the process of loading a document. The ViewSource property is used to toggle between viewing the document as HTML source or as a regular HTML document.
Now run the program again. Check out the new buttons and see what they do. In particular, give the View Source button a try.
Okay, you\'re almost done with your Web browser. Let\'s add a couple of more features. You are going to respond to two more events of the THTML control in order to provide more status information.
1. Generate an event handler for THTML\'s OnDoRequestDoc event. Type this code in the event handler:
StatusBar.SimpleText := `Connecting to ` + URL + `...\';
2. Now create an event handler for the OnBeginRetrieval event. When the event handler appears, type this code:
StatusBar.SimpleText := `Connected...\';
URLComboBox.Items.Insert(0, URLComboBox.Text);
In this sequence, step 1 makes use of the OnDoRequestDoc event, which is generated when a document is requested. The URL parameter of the DoRequestDoc event handler is the URL of the site to which you are connected. As long as the URL is provided, you can use it to build a string to display in the status bar. Step 2 adds a little more status information when the document actually starts to load. It also takes the URL and adds it to the URL combo box\'s list. You need to make sure that you have connected to a site before adding the URL to the list of visited sites.
Congratulations, you have finished (or nearly finished) your first Internet application. Figure BD.3 shows the EZ Web Browser in operation.
FIGURE BD.3. The finished EZ Web Browser displaying a page.
Hey, that\'s good work! There are some things that your Web browser doesn\'t do, but it does a lot, so you can be proud. Stand back and admire your work. You can take your new creation and add some new features of your own. One feature you might want to add is a list of URLs that can be used to implement browse buttons (back and next). You could also replace the standard buttons with a toolbar and add glyphs to the toolbar\'s buttons. If you really want to add the ultimate touch, provide an animation while the document is loading so that your users can tell when your browser is doing something. You can do that most easily with a TImageList component, although the TAnimate component would work, too.
The THTML control has several properties that I didn\'t cover. Most of these properties have to do with user preferences such as background color, the color of links, the color of visited links, the various fonts used for each heading size, and so on. I\'m not going to explain those properties because they are easy to figure out. For the most part you can just accept the default values for these properties. If you want to customize your browser further, though, you can certainly spend some time reviewing the properties list for the THTML control.
Listing BD.1 lists the browser program\'s main unit.
LISTING BD.1. WebBrwsU.pas.
unit WebBrwsU;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, OleCtrls, NMHTML, ComCtrls;
type
TWebMain = class(TForm)
Panel1: TPanel;
URLComboBox: TComboBox;
StatusBar: TStatusBar;
HTML: THTML;
GoBtn: TButton;
StopBtn: TButton;
ReloadBtn: TButton;
SourceBtn: TButton;
procedure URLComboBoxClick(Sender: TObject);
procedure URLComboBoxKeyPress(Sender: TObject; var Key: Char);
procedure HTMLUpdateRetrieval(Sender: TObject);
procedure HTMLEndRetrieval(Sender: TObject);
procedure Gobtnclick(Sender: Tobject);
procedure StopBtnClick(Sender: TObject);
procedure ReloadBtnClick(Sender: TObject);
procedure SourceBtnClick(Sender: TObject);
procedure HTMLDoRequestDoc(Sender: TObject; const URL: WideString;
Element: HTMLElement; DocInput: DocInput;
var EnableDefault: WordBool);
procedure HTMLBeginRetrieval(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebMain: TWebMain;
implementation
{$R *.DFM}
procedure TWebMain.URLComboBoxClick(Sender: TObject);
begin
if URLComboBox.Text <> `\' then
HTML.RequestDoc(URLComboBox.Text);
end;
procedure TWebMain.URLComboBoxKeyPress(Sender: TObject; var Key: Char);
begin
if Key = Char(VK_RETURN) then begin
Key := #0;
if URLComboBox.Text = `\' then
Exit;
URLComboBoxClick(Sender);
end;
end;
procedure TWebMain.HTMLUpdateRetrieval(Sender: TObject);
var
Total : Integer;
Done : Integer;
Percent : Integer;
begin
Total := HTML.RetrieveBytesTotal;
Done := HTML.RetrieveBytesDone;
if (Total = 0) or (Done = 0) then
Percent := 0
else
Percent := ((Done * 100) div Total);
StatusBar.SimpleText := Format(
`Getting Document: %d%% of %dK\', [Percent, Total div 1024]);
end;
procedure TWebMain.HTMLEndRetrieval(Sender: TObject);
begin
StatusBar.SimpleText := `Done\';
end;
procedure TWebMain.GoBtnClick(Sender: TObject);
begin
URLComboBoxClick(Self);
end;
procedure TWebMain.StopBtnClick(Sender: TObject);
begin
HTML.Cancel(0);
StatusBar.SimpleText := `Done\';
end;
procedure TWebMain.ReloadBtnClick(Sender: TObject);
begin
URLComboBoxClick(Self);
end;
procedure TWebMain.SourceBtnClick(Sender: TObject);
begin
HTML.ViewSource := not HTML.ViewSource;
if HTML.ViewSource then
SourceBtn.Caption := `View Document\'
else
SourceBtn.Caption := `View Source\';
end;
procedure TWebMain.HTMLDoRequestDoc(Sender: TObject; const URL: WideString;
Element: HTMLElement; DocInput: DocInput; var EnableDefault: WordBool);
begin
StatusBar.SimpleText := `Connecting to ` + URL + `...\';
end;
procedure TWebMain.HTMLBeginRetrieval(Sender: TObject);
begin
StatusBar.SimpleText := `Connected...\';
URLComboBox.Items.Insert(0, URLComboBox.Text);
end;
end.
Using Internet Explorer as an ActiveX Control
If you have Microsoft Internet Explorer installed on your system, you can use it as an ActiveX control. The first thing you need to do is import the control into Delphi\'s Component palette. After that, you can place it on a form just as you would any control. First, let me show you how to import Internet Explorer. (I showed you how to import ActiveX controls on Day 15, \"COM and ActiveX,\" but it doesn\'t hurt to review.) Here are the steps:
1. Choose Component | Import ActiveX Control from the main menu. The Import ActiveX dialog box is displayed.
2. Locate Microsoft Internet Controls (Version 1.x) in the list of ActiveX controls (see Figure BD.4). If you have Internet Explorer 3 installed, the version number will be 1.0. If you have Internet Explorer 4 installed, the control will be listed as version 1.1. Notice that the Class names field shows TWebBrowser as the control contained in this file. If you have Internet Explorer 4, the Class names field will also show TWebBrowser_V1 (the original WebBrowser control) and TShellFolderViewOC.
FIGURE BD.4. The Import ActiveX dialog box.
3. Click Install to install the control (the rest of the fields on this dialog box can be left on their default values).
4. The Install dialog box appears asking for a package name. Click on the Into new package tab at the top of the dialog and type IE in the File name field. (You can type a description if you want, but it\'s not necessary.) Click OK to create the package.
5. A confirmation dialog box appears asking whether you want to build and install the package. Click Yes to create the package.
Delphi builds the package and then displays a dialog box saying that the TWebBrowser control has been installed. Now you can try out the control:
1. First, choose File | Close All to close all windows, and then create a new application.
2. Click the ActiveX tab on the Component palette. Choose the WebBrowser control and drop it on your main form. Size the control as desired, but leave room on the form for a button.
3. Drop a Button component on the form. Double-click the button to generate an OnClick event handler. Type the following code in the event handler (use any URL you want):
WebBrowser1.Navigate(`http:\\\\
www.turbopower.com\',
EmptyParam, EmptyParam, EmptyParam, EmptyParam););
As you might surmise, the Navigate method loads the document in the Web browser.
4. Click the Run button to run the program.
When the program runs, click the form\'s button. The Web page will load and be displayed in the WebBrowser control.
When you install this control, Delphi creates a unit called SHDocVw_TLB.pas. You can look at this unit to see what properties and methods are available for TWebBrowser.
--------------------------------------------------------------------------------
TIP: You can find documentation for the WebBrowser control on Microsoft\'s Web site. Search the Microsoft site for the text Reusing the WebBrowser Control.
--------------------------------------------------------------------------------
Notice that you can\'t redistribute the TWebBrowser control itself without obtaining a license from Microsoft. However, if you know your users have Internet Explorer installed on their systems, your application will work because the control is already installed. You still have to register the control on your user\'s machine for your application to run. See \"Deploying Internet Applications\" later in this chapter for more information on registering ActiveX controls.
Sending Mail
There are many reasons you might want to send mail from one of your applications. The good news is that sending email isn\'t difficult at all. Maybe you want your program users to be able to email you with any problems they encounter. In that case, your application could pop up a form containing a Memo component and a Send button. Your users can type text in the Memo component, press the Send button, and the message is emailed to you. You can even go so far as to attach a log file from your application to diagnose any problems the user is having.
The TNMSMTP control is used for sending mail through an SMTP server. SMTP is an odd protocol in that it doesn\'t require authenticated logon to the server (at least on most SMTP servers). You can simply connect to any mail server, send the email message, and disconnect. The Host property is used to specify the host name of the mail server to which you want to connect. Most of the time, you can just use mail as the host name. Specifying mail tells the TNMSMTP control to connect to your local mail server, whether it\'s your ISP\'s mail server or your company\'s mail server.
If you want, you can specifically set the mail server name (such as mail.mycompany.com), but it isn\'t usually necessary. If you specify an incorrect mail server, you get an ESockError exception. The Port property is used to specify the port on which to connect. The default SMTP port is port 25. The Port property defaults to a value of 25, so you shouldn\'t have to change this property.
All the pertinent information for the mail message itself is contained in the PostMessage property. This property is a class that contains properties such as ToAddress, FromAddress, Subject, Body, and so on. You fill in the appropriate fields of the PostMessage property and then send the message.
Before you can send a mail message, you need to connect to the SMTP server. This is done with the Connect method:
SMTP.Host := `mail\';
SMTP.Connect;
After you\'re connected, you can send the email. The OnConnect event handler is a good place for this code because you know that you are connected to an SMTP server. For example:
procedure TMainForm.SMTPConnect(Sender: TObject);
begin
with SMTP.PostMessage do begin
FromAddress := `bilbo@baggins.com\';
ToAddress.Add(`gandolf@baggins.com\');
Subject := `Test\';
Body.Add(`This is a test\');
end;
SMTP.SendMail;
end;
This code sets up the FromAddress, ToAddress, Subject, and Body parameters of the PostMessage property and then sends the message with the SendMail method. It\'s as simple as that. Notice that the ToAddress and Body properties of PostMessage are TStringLists. The mail message body can contain several lines of text, so it\'s not surprising that the Body property is a TStringList. The ToAddress property is also a TStringList, so you can specify several recipients for the message.
--------------------------------------------------------------------------------
NOTE: The FromAddress and ToAddress fields are required fields. All other fields (even the message body) are optional.
--------------------------------------------------------------------------------
After you know the message has been sent successfully, you can disconnect from the SMTP server. The OnSuccess event is generated when the mail has been sent. Your OnSuccess event handler might be as simple as the following:
void __fastcall tform1.smtpsuccess(tobject *sender then
begin
SMTP.Disconnect;
end;
You can send several messages per connection, of course. If you have several messages to send, you don\'t have to disconnect from the server and reconnect for each message. Just connect once, send all your messages, and then disconnect from the server.
Your mail message might go through without incident, or it might fail in one way or another. In either case, you must be prepared to disconnect from the server. The OnFailure event is generated if the mail message fails to go through, so you can use that event to disconnect from the server as well as the OnSuccess event. The book\'s code, found at
http://www.mcp.com/info, contains a simple mail program that illustrates how to send mail with TNMSMTP.
Deploying Internet Applications
If your Internet application uses only the VCL Internet components, there is nothing special to do when you deploy your application unless you are using runtime packages. If you are using runtime packages, you need to ship INET40.BPL, and if you are using the page producer components, ship INETDB40.BPL as well.
Deploying an application that uses ActiveX controls, however, requires more work. ActiveX controls must be registered on the machine on which your application will run. The easiest way to register ActiveX controls is with a good installation program. InstallShield Express comes with Delphi Professional and Client/Server versions, so you should try that program. Another good installation program is Wise Install from Great Lakes Business Solutions. The better installation programs register, as part of the installation process, the ActiveX controls that your application uses.
If you don\'t use a commercial installation program, you have to manually register any ActiveX controls your application uses. The TREGSVR.EXE utility is used to register and unregister ActiveX and OCX controls. This utility is in your Delphi 4\\Bin directory. For example, to install the EZ Web Browser application you created earlier today, you ship the following files:
HTML.OCX
NMOCOD.DLL
NMSCKN.DLL
NWM3VWN.DLL
NMORENU.DLL
WEBBROWS.EXE
After you install all these files, you have to run TREGSVR.EXE on the HTML.OCX and NMOCOD.DLL files to register them. From the command line, you type
TREGSVR HTML.OCX
Do the same for NMOCOD.DLL. The THTML control is now registered on your user\'s machine and your program will run as intended.
--------------------------------------------------------------------------------
NOTE: If you don\'t register your ActiveX controls properly, your users will see a message box that says, \"Class not registered.\" when they attempt to run your program. Your application will then terminate, leaving your users wondering what went wrong.
--------------------------------------------------------------------------------
To unregister a control, use the /u switch as follows:
TREGSVR /u HTML.OCX
Here again, a good installation program will have an uninstall option that takes care of this for you.
As you can see, ActiveX controls require a bit of work to install after your application is built. If you aren\'t aware of the fact that you need to register the ActiveX controls, it can lead to confusion for both you and your users. By the way, the files needed to deploy an application using the THTML control total about 900KB, so using ActiveX controls can be expensive in terms of disk space. I prefer to use native VCL controls whenever possible for exactly this reason.
Jeg har fundet det og det virker