Mastering Delphi 7
Updates and Corrections
Last Udpated on October 17th, 2003
- Page 7: Towards the middle, the registry key for changing the sort order of the Window menu is discussed without mentioning its actual name, "Sort Window Menu".
- Page 16: In the bullet starting with Ctrl+Shift+I, the page of the Editor Options dialog with the number of spaces to indent is "Source Options" (and not "Editor" as stated in the book).
- Page 27: In the tip the "Make All From Here" project manager local menu command is in fact "Compile All From Here".
- Page 28 ): In the second last line, the dcc command line compiler is actually dcc32 since Delphi 2!
- Page 30: In a couple of places the book mentions a "Build All" command, while in fact the menu command is Build followed by the name of the active project (which is useful to know when you have multiple projects open in a project group).
- Page 32: in the secodn last line the reference to the shortcut menu of the Project Explorer should be to the menu of the Project Browser.
- Page 33: The External Translation Manager is hosted in the etm70.exe ececutable file (not etm60.exe, which was Delphi 6 version).
- Page 40: The sidebar "The Empty Project Template" mentions "adding an Empty Project template to the Gallery". Should have been "adding an Empty Project template to the Objects Repository".
- Page 60 (first paragraph): "Many of these regional settings are copied by Delphi into constants defined in the library, such as LongMonthNames." They are in fact variables (used to be constants in the early versions of Delphi) as they can be modified directly by the program's code.
- Page 64 (last paragraph): "To redefine a static method, you add a method to an inherited class having the same parameters or different parameters than the original one, without any further specifications." This is correct, but the text fails to mention that the method must have the same name of the one in the base class.
- Page 61: First line of code should be TMyDerivedClass = class (TMyClass), with the initial "T".
- <>Page 77 (4th line): "When you declare a class reference variable, such as MyClassRef, you can then assign to it that specific class and any inherited class". To follow the code presented the class reference variable name should have been AClassRef.
- Page 84 (first bullet): The Object Pascal language has been renamed as the Delphi language, but I missed this reference.
- Page 86 (note): The text uses some slashes (Source/Rtl/Common) instad of the proper backslashes (Source\Rtl\Common).
- Page 87 (just after the one line listing): the function name is Supports, not Support.
- Page 87 (last line): Shoudl be IncludeTrailingPathDelimiter, not Including....
- Page 88 (the section on Extended Formatting Routines): The book mentions that if the user modifies the Regional Settings in Control Panel while the program is running, the program will respond to the broadcast message. However, it fails to mention that this is true only for an application using the visual controls and specifically the global Application object of the VCL. The refresh doesn't happen on server-side, non-visual applications. Finally, an alternative solution to avoid a system override of your local settings is to block them by assigning False to the Application.UpdateFormatSettings property.
- Page 90 (last line, code): an open parenthesis is missing, should have been SimpleRoundTo ((d * 10, 0) / 10).
- Page 104 (middle page): Again Object Pascal language should have been converted to Delphi language.
- Page 116 (middle): The book indicates that the third optional parameter of GetPropValue can be used to spell out the values of a set. It fails the mentions that the same parameter can be used to obtain the string representation of the value of an enumerated property.
- Page 125 (final code line): shoudld have been Button1.OnClick := .... Anyway, using MyButton as a class name is quite a bad choice: TMyButton would have been more coherent with Delphi standards.
- Page 128 (section "Lists and String Lists"): the first sentence indicates that a TList is a generic list of objects, while two lines below the book correctly states this represents a list of pointers (although you can in practice place object references into it). Actually, to manage a list of objects is more handly to use the inherited TObjectList collection (covered at page 131) rather than a plain TList.
- Page 129 (section "Name-Value Pairs"): the first paragrah introduces the sampel string lastname=john, which is not a smart idea. Using firstname=john would have been better...
- Page 137 (the long code snippet): There should have been a try-finally block to protect the release of the stream object (and of the related file handle):
n := 10;
str := ‘test string’;
stream := TFileStream.Create (‘c:\tmp\test’, fmCreate);
stream.WriteBuffer (n, sizeOf(integer));
stream.WriteBuffer (str, Length (str));
Page 139 (initial listing): The code opens the target stream (Stream2)with the file mode fmOpenWrite or fmCreate. This is actually not needed, as fmCreate alone creates the file or opens it in write mode if the file already exists. However, this is not the code you'd want to use for appending data to an existing file, rather than overriding it. In such a case you'd need to open the file in different modes depending if it already exists, then move to the end and write to it, as int he following code:
procedure TForm1.Button1Click(Sender: TObject);
aStream : TFileStream;
strOutput := Form1.Caption + sLineBreak;
if not FileExists (edFileName.Text) then
aStream := TFileStream.Create (edFileName.Text, fmCreate)
aStream := TFileStream.Create (edFileName.Text, fmOpenReadWrite);
// go to the end
aStream.Position := aStream.Size;
aStream.Write(strOutput, Length (strOutput));
Page 139 (just before the note): The TBlobField class is BDE specific. There are other classes for BLOB fields having the same methods, though.
Page 145 (second half): The text refers to the compression/decompression stream calsses with the wrong names. TCompressStream and TDecompressStream should have been TCompressionStream and TDecompressionStream as in the later code.
Page 146 (listing): The line comprStream.CompressionRate; is useless. I should have assigned a compression rate value to the property.
Page 147 (second-last bullet): the FindClass method should have been the FindClass function, as it is a global function.
- Page 164: In the Warning note, "CXL" should rather be CLX (as in the following line).
- Page 162: The 4th line mentions a possibility of creating a widget around an existing Qt object and the existence of an OwnHandle property. However, the property doesn't exist, and the creation of a widget over an existing object is not as simple as depicted here.
- Page 182: In the section "Using the Fly-By Hints" I mention the ShowHints property, which in fact should have been ShowHint. Moreover, the text fails to mention the existence of the useful ParentShowHint property, and the fact you can activate hints for a set of control or for their parent control (and this is thanks to ParentShowHint).
- Page 197: Towards the middle of the page the book referst to an OnCreateNodesClass event, whcih in fact is called OnCreateNodeClass.
- Page 204: In the second listing PageControl1.Pages.Caption should read PageControl1.Pages[I].Caption.
- Page 215: The first line of text should be "The availability of the Paste operation cannot be determined by..." (it is Paste and not Copy and it is not the operation itself to be determined by the Clipboard status, but the fact it is enabled or not).
- Page 268: Towards the middle of the apge there is a reference to Chapter 7, which is the current chapter. It should have pointer to Chapter 5, where I discuss techniques related to controls, such as alignment and anchors.
- Page 285: There are a couple of references to an OnDoubleClick event which is in fact OnDblClick
- Page 299: In the "TMainForm.FormCreate" listing, the first comment should have been "set the secondary forms counter", as this is the counter of the number of secondary forms (plural).
- Page 338: The final "tip" note mentions the Delphi 6 version of some packages, like DCLSTD60.BPL and VCL60.BPL. Should have been dclstd70.bpl and vcl70.bpl.
- Page 343: In the method TMdFontCombo.CreateWnd, intead of checking that the owner is a form I could have used the handy function GetParentForm global function, as in:
if FChangeFormFont then
ItemIndex := Items.IndexOf (GetParentForm(Self).Font.Name);
Page 346: At the end of the package listing, the contains portion refers to a unit called MdFontBox, while the correct name is MdFontCombo, as indicated in Figure 9.1.
Page 348: In the second bullet, I refer again to a wrong unit name, as the resource file shoudl have been MdFontCombo.dcr.
Page 368: At line 8 I mention a non-existent OnChar event. Should have been OnKeyPress.
Regarding ModelMaker (the tool this chapter is focused onto) it is relevant to notice that Borland has recently acquired (or merged with) Together Soft, makers of a powerful UML design sytem based on what is called "LiveCode"(TM) technology. With this technology there is no separation among the model and the source code, but the source provides the only physical representation of the model. This way the two are always in sync. If Together Soft products are very interesting and powerful and have a long history of quality (I witnessed one of their first presentations to Borland in 1994, if I'm not wrong!), they are available for C++, Java and now C#.
It is certainly possible that future offerings will include support for the Delphi language, which will certainly diminish the role of ModelMaker (at least for Borland, if not for the current and future ModelMaker users). If ModelMaker is not as powerful, certainly the price tag it carries is more limited (at least this happened in the past) making it a good alternative for programmers on a tighter budget. As I'm not an expert on either products, it might as well be that ModelMaker has features that Together products lack, but I have to say that for what I've seen I prefer the code-centric approach Together has pushed over the years.
- Page 460: the third last line refers to building a "COM server hosted by a COM server DLL", which mnakes little sense. Should have been a "COM object hosted by a COM server DLL".
- Page 475: Before the second listing, the book says: "Here is an example of the first approach." What follows, in fact, is an example of the second approach, namely "store it in a variant variable."
- Page 481: The Tip at the end of the page ends by saying "and align both of them to the client area of the form". It shuold have been "to the client area of their contaners". The OLE container component, in fact, should be aligned to the client area of the panel hosting it as described in the Tip.
- Page 490: The last line refers to "UpdateOleObject and UpdatePropertyPage", but the name of the first method is UpdateObject.
- Page 497: The "Tip" refers to the discussion of SOAP in Chapter 22, while in fact it is in Chapter 23, "Web Services and SOAP".
- Page 506: The second-last paragraph refers to "the ClientDataSet and Provider, in particular" but should have actually indicate the specific DataSetProvider component. Similarly at page 508, at the end of the first paragraph "imported by another dataset using a Provider component" shuold have said "a DataSetProvider component".
- Page 511: The paragraph "XML and CDS Formats" mentions a folder "Borland Shared\Demo" which is, in fact, "Borland Shared\Data. There is also a factual error. MyBase by default saves the dataset in the internal CDS format, not in XML. It uses XML format only if you specify a filename with .xml extension for the Filename property. This is obvious by looking to the SaveToFile method of the ClientDataSet component, defined as:
procedure SaveToFile(const FileName: string = ''; Format TDataPacketFormat=dfBinary);
Page 512: The last paragraph starts with "Filtering a ClientDataSet is a matter of...". It should have been "Indexing a ClientDataSet...", as this is the topic discussed in the section.
Page 513: After the first Tip the text describeds the use of the IndexDefs property. The problema is that the sentence "Doing so allows you to define several indexes and keep them in memory, switching even faster from one to the other" can be misunderstood. You might think that multiple indexes are kept in memory, so that when you change the index the application is "faster". Instead, only one index is kept at a time, and recalculated when you swicth it. With "faster" I was referring to the fact you need to write less code. HEre is an upated version: "Doing so allows you to define several indexes and keep their definitions in memory, writing less and cleaner code to switch from one to the other".
Page 513: The second paragraph of the section about "Filtering" says:
"When you’re retrieving large amounts of data from a server (in a client/server architecture) you should try to use a proper query so you don’t retrieve a large dataset from a SQL server." This sentence doesn't sound exaclty clear. Here is a rephrased version: "When you are working with a large amount of data, filtering locally with a ClientdataSet is far from an optimal choice. When you work in a client/server architecture, you should reduce the amount of data you work with by setting up a proper SQL query. Filtering up front..."
Page 514: I should have added a Warning note to the section on "Locating Records", with the following text: "In the ClientDataSet the Locate and Lookup operations are based on a filter and a complete sequential scan of the data. The "old-fashioned" FindKey/SetKey/GotoKey methods, instead, can use the currrent index if this is based on the same fields, speeding up the search operation considerably. The reason the FindKey/SetKey/GotoKey methods are not commonly used is that they were the standard technique for Paradox data (using the TTable component), but when Locate was added it was more optimized than these older methods, and became a standard choice.
Page 514 and 515: The sections "Undo and SavePoint" and "Enabling and Disabling Logging" should be of a higher level, the same of "Locating records" and not under it.
Page 516: In the list of "Text-Based Data-Aware Controls" one is notably missing. Add the following entry:
"DBRichEdit Lets the user work with an RTF document, a fully formatted text generally saved in a BLOB field in the database. When you want to handle and display real text documents this is often much better than using a DBMemo, which allows you to display the text only in a single font and supports no formatting options at all."
Page 519: The Tip at the end of the page says "If you set the IndexFieldNames property of the ClientDataSet containing the orders data to the Company field..." while the ClientDataSet to be ordered is the one hosting the clients data, not the orders data.
Page 520: Again, some additional material at the end of the section "Graphical Data-Aware Controls":
"There is actually a second graphical data-aware control, the DBChart, which is the data-aware version of the Chart component of the Additional page of Delphi’s Components Palette. Both components display business graphics (like pie charts, istograms, and so on). The data-aware version is capable of displying the data of a record or showing in a graps the values of the same fields of the various records of a dataset. All it takes is set up a few properties, and the result can indeed be very nice."
Add also the following note:
Note: These two business-graphics components have been in Delphi since the early versions but actually come from a third-party company, Steema Software (www.steema.com), which sells an extended version of the components, called teeChart Pro.
The same section mentions that to enable support of JPEGs all you need to do is to add a related uses statemet. This is true for the standard TImage component, while showing a database BLOB field storing a JPEG requires extra manual coding.
Page 524: In the list of values for the State property of the dataset, I've omitted the status dsSetKey. However, from what I've mentioned earlier (see page 514 above) I should have kept this status, which is not releant just for Paradox's Table component but also for the ClientDataSet one.
Page 525: In the second listing two semicolons are missing at the end of the code lines.
Page 526: After Figure 13.5, "The Fields Editor’s Define command lets you define a new calculated field, lookup field, or field with a modified type". The Fields Editor command is called "New Field" and it lets you define any type of field. It can be used as the manual version of the Add Fields command in case the dataset is not hooked to th database at design time but you still want to define persistent fields.
Page 529: Table 13.2. There are two references to Chapter 14. The first is in the description of TAggregateField, and should refer to "later in this chapter" as the topic is covered in Chapter 13. The second reference is in the description of TAutoIncField but this topic is not covered elsewhere in the book, so the reference should be omitted.
In the same table the description of the TBinaryField class is not correct, as this is the base class of the TBytesField class (and not "the next two classes").
Page 537: The second bullet refers to the Locate, which in fact was discussed earlier in the chapter, not "in the next section".
Page 542: In the section "A Grid Allowing Multiple Selection" I indicate the use of the Ctrl key plus mouse clicks for selecting multiple rows. A keyboard-based alternative is to press the Shift key and the up and down arrows.
Page 544: In the section "Dragging to a Grid" I refer to the "protected hack", which in fact was discussed in Chapter 2, not Chapter 3.
Page 545: The last line before the listing indicates the event is called OnAfterSrcoll instead of AfterScroll.
Page 552: The section "Master/Detail Structures" refers to the DataSource property of the TDataSet class. This is correct, but it is important to notice that for two very relevant derived classes, TClientDataSet and TTable, the property is called MasterSource. The first paragraph of the sub-section "Master/Detail with ClientDataSets" is in error referring to the DataSource property, which is in fact MasterSource, as indicated in the following DFM listing.
- Page 555: In the first paragraph I claim that "This chapter moves on to the use of SQL server databases, focusing on client/server development with the BDE and the new dbExpress technology". The chatper covers dbExpress and IBX, and there is no mention of the BDE technology (on purpose).
- Page 562: In the sidebar "A Short History of Interbase", the initial reference to the Groton Database Systems company, but the extension is gdb (Groton DataBase). Nowadays in Borland the preferred extension is IB, for InterBase. In the same sidebar, the description of the FireBird project is accompanied by its SourceForge address, but the most relevant link is to its home page, http://www.firebirdsql.org.
- Page 573: The paragraph after Figre 14.5 ends with "...if you specify the SortFieldNames property, it will include a sort by directive", but it shuold have been "it will include an order by directive".
- Page 574: The sidebar "The TimeStamp Field Type" includes the text "A time stamp is a record-based representation of a date or time", which should have been "date and time".
- Page 576: In the second listing the code refers to SQLClientDatSet1 instead of SimpleDataSet1. Should have been:
- Page 618: The tip refers to Dmitry Kovalenko’s IBProvider. This can be found at the simpler URL www.ibprovider.com. Bin Ly’s OLE DB Provider Development Toolkit, instead, can be found at www.techvanguards.com/products/optk/. Notice, anyway, that this tool hasn't been updated recently.
- Page 634: The steps in the section "Nested Transactions" refer to Microsoft's classic Northwind demo database. As the example now uses the ADO version of Borland's dbdemos, they cannot be followed literally. Perforning similar steps with the example should not be too difficult, though. The same problem shows up at the top of page 640, in another series of steps.
- Page 658: The final paragraph (the last two lines of the page) states you can set the ResolveToDataSet property of the TDatasetProvider component, to determine the update process. However the final line is wrong. You can use this Boolean property to indicate whether to send the updates to the dataset used for input (if this is supported, as detailed in the following sentence) or let the internal Resolver object of the provider compose and execute the udpate queries. There is no way to specifcy a "second dataset used for the updates". Your third option, discussed much later, is to handle the udpates with local events, and completely customize the process.
Page 687 and following: The rde paragraph of this page properly states that the 2 virtual abstract methods of Delphi 5's TDataSet are not down to only 5. In the following text, however, some of the virtual methods are still mentioned as if they were virtual abstract.
Page 702: The GetFieldData and SetFieldData methods are called twice GetData and SetData.
Page 710: The last paragraph starts with "The class is used by the InternalInitFieldDefs method..." The class in question is the one "stored in the ObjClass property", as the previous paragraph states. The distance among the two make the text hard to follow.
Page 715: The chapter's introduction mentions "Microsoft’s Word to Sun’s OpenOffice". Actually, the latter product is called either Sun's StarOffice or OpenOffice.org. The second is the totally free (and open source) version of the same core product. As an additio, I have to say I've kept using OpenOffice.org more and more and written progrmas to interact with it and to work on its file format, and I have to say I'm more and more pleased by this tool.
Page 724: In the section "The FontMaster Component", the first paragraph ends by saying "You have to keep track of which fonts must be the same typeface, size, and style, ..." which should have been "You have to keep track of which objects must have the same font typeface, size, and style, ..."
Page 731: The Warning note mentions that the wizard for master/detail reports didn't work in the shipping version of Delphi 7. Subsequent updates of Rave fixed the issue.
Page 732: The description of the scripting example sugests to add "two different FontManager components to the report page". The component I was referring to is actually called FontMaster.
- Page 746: The text at the middle includes the following description: "LoggedOn, a data field" which should have been "LoggedOn, a date field".
- Page 759: The core event of the PageProducer component is called OnHTMLTag and not OnTag (this is wrong in other paragraphs, as well).
IntraWeb has seen a large number of changes from version 5.0 (discussed in the book) to version 5.1 (a free download for registered Delphi 7 users). This change have made impossible to compile the book examples as they are, and involved some of the class, properties and method names covered in the text. This makes the book from from updated, although all of the core concept are still the same and the chapter still provides a very good introduction to IntraWeb.
Page : .
Page : .
Page : .
Page : .
Page : .