The Delphi FAQ Maintainer: Graham Mainwaring Last Updated: May 22, 1995 Questions discussed in this FAQ: 0. Introduction. 0.1 What is the purpose of this FAQ? 0.2 How can I get the latest version of this FAQ? 0.3 Is this FAQ copyrighted? 1. General Questions. 1.1 What is Delphi? 1.2 What versions of Delphi are there? 1.3 How much disk space, memory, etc., do I need to run Delphi? 1.4 How tough is it to learn Delphi? 1.5 What's the difference between Delphi Desktop and Delphi Client/Server? 1.6 Can you write multi-user database applications in Delphi Desktop? 1.7 What is the history of Delphi? 1.8 Where can I get a copy of Delphi? 1.9 What if I don't have a CD-ROM drive? 1.10 How can I contact Borland? 1.11 What technical support do I get with Delphi? 1.12 What known bugs exist in Delphi? 1.13 I just bought Delphi. Where are the language and library reference manuals? 2. Delphi Resources. 2.1 What are some good books about Delphi? 2.2 Does anyone publish a Delphi magazine or journal? 2.3 Where can I find sample source code and utilities for Delphi? 3. Compatibility. 3.1 What operating systems does Delphi support? 3.2 What source management tools are compatible with Delphi? 3.3 Can I use DLLs developed in C or C++ from Delphi? 3.4 Can I make calls to Delphi code from C or C++? 3.5 What third-party packages are specifically known to work (or not work) with Delphi? 4. Database Questions. 4.1 How do I get access to a database from Delphi? 4.2 Does Delphi support the back-end? 4.3 What data-aware controls come with Delphi? 4.4 Can I use the ODBC drivers that I got with ? 4.5 What about data-aware VBXes? 4.6 How do I write a "change password" function for a Paradox table? 4.7 Why do I get errors when I call the Add method for a TFieldDefs? 4.8 What is the procedure for connecting Delphi to an MS Access database? 4.9 How can I manipulate data programmatically? 5. Programming Questions. 5.1 What target formats can I create using Delphi? 5.2 I built a small test project. What are all these files? 5.3 How can I yield the CPU to other tasks, like "DoEvents" in VB? 5.4 Why do I get compile errors accessing the Sender object in events? 5.5 Are there any tools to help me migrate my applications to Delphi? 5.6 What's the Delphi equivalent of Visual Basic control arrays? 5.7 How do I close a modal form? For that matter, what's the best way to close any form? 5.8 Are there commercial applications developed in Delphi? 5.9 Do I have to know a lot about the Windows API to use Delphi? 5.10 Do I have to understand object oriented programming to use Delphi? 5.11 How does Delphi's exception handling work? 5.12 Does Delphi use Pascal or C style strings? 5.13 How does Delphi handle Windows callbacks? 5.14 How does Run-Time Type Information (RTTI) work? 5.15 I'm creating a toolbar, but I have icons, not bitmaps. Help! 5.16 When I use the Glyph property, how do I know which color is transparent? 5.17 How can I make my Delphi application respond to Windows messages? 5.18 How can I allocate blocks of memory larger than 64k? 5.19 Is it possible to write a Windows screen saver in Delphi? 5.20 I'm trying to call from Delphi and it GPFs. What's up? 5.21 How can I add pages to a TTabbedNotebook at run-time? 5.22 I'm painting complex graphics. How can I speed up redrawing? 5.23 How can I hade MDI child windows? 5.24 How do I write a global error handler? 5.25 Why do I get exception messages even though I'm in protected code? 5.26 I've added code to my OnKeyPress event that traps Enter keys, but it keeps beeping at me and/or activating the default button. How do I make it stop? 5.27 I want to modify a component's properties at run-time, but it isn't convenient to store a pointer to the component. Is there an easy way to get access to it? 6. Questions about distributing Delphi applications. 6.1 Is there anything in Delphi similar to the VB "setup wizard?" 6.2 What files am I allowed to redistribute with my applications? 6.3 If I want to send out a Delphi-compiled EXE file, what other files do I need to send with it? 6.4 I want to distribute a database application, but I don't want to force all my users to create BDE aliases. What do I do? ------------------------------ 0. Introduction. 0.1 What is the purpose of this FAQ? This FAQ is intended to answer some questions about the new development environment from Borland International called Delphi. Information in this document is not guaranteed to be correct. Use it at your own risk. This is not really a FAQ in the purist sense of the term, because some of the questions answered here are not really very frequently asked at all. 0.2 How can I get the latest version of this FAQ? This FAQ is posted to comp.lang.pascal approximately monthly. If it's expired on your news server, you can get it via anonymous ftp to ftp.mhn.org as /pub/delphi.faq; or you can get it from WWW as . 0.3 Is this FAQ copyrighted? Yes. A work is copyrighted by the act of publication. But you are hereby authorized to do whatever you want, however you want. I request that if you distribute all or part of this FAQ, you also distribute the 0 section. Also, this authorization applies to *this version* only. I reserve the right to apply whatever copyright restrictions I see fit to future versions. ------------------------------ 1. General Questions. 1.1 What is Delphi? Delphi is a product of Borland International. It is a native code compiler that runs under Windows 3.1 and provides visual programming tools somewhat similar to those found in Microsoft Visual Basic 3.0. The underlying language is Object Pascal, which is an extension of the object-oriented Pascal found in Turbo/Borland Pascal starting with version 5.5. 1.2 What versions of Delphi are there? Delphi has been available in beta-test for many months now, and Borland has also given away a large number of "prerelease" copies. As far as the official release is concerned, though, there are two packages: Delphi (sometimes referred to as Delphi Desktop) and Delphi Client/Server. Both are version 1.0. 1.3 How much disk space, memory, etc., do I need to run Delphi? The minimum installation of Delphi takes about 30Mb, and the full install takes 80Mb. In order to run it well, you'll need a 486 with a minimum of 8Mb of RAM, though I personally wouldn't try to run it in less than about 12Mb. I use a 486DX2/66 at home and a Pentium-90 at work, and to be honest, there's not much difference between them--Delphi's compiles are so fast that the CPU is really not a bottleneck. 1.4 How tough is it to learn Delphi? If you're lucky, you already have lots of experience with both Object Pascal (or, as it used to be called, Borland Pascal With Objects-- essentially, Turbo Pascal v5.5 or later) and with Visual Basic. If you fit this description, then Delphi will be a breeze for you. Okay, now for everyone else. In order to make full use of the Delphi environment, you have to know Pascal, you have to have some grasp of object orientation, and you have to understand event-driven programming. Once you're over those three hurdles, you've pretty much got it. See section 5 for more information. On the other hand, most people don't need to make "full" use of the environment. If you just want to pull a simple application together that doesn't do anything too fancy, Delphi shouldn't be any harder to learn than VB--it's just that there's a whole lot more you *can* do in Delphi, which will make you feel more lost than you really are. 1.5 What's the difference between Delphi Desktop and Delphi Client/Server? Delphi Client/Server includes everything from Delphi Desktop, plus the following: - SQL-Links 2.5, which includes native client drivers for Oracle, Sybase, Informix, and InterBase, and includes full royalty-free redistribution rights to those drivers, and which costs $995 if bought separately; - The Local InterBase Deployment Kit, $495 (*); - ReportSmith/SQL, $300 (**); - "Team development support" -- interoperation with PVCS (obviously, this is no use to you if you don't own PVCS), not available separately; - The visual query builder, which creates SQL statements for you, also not available separately; - The VCL source code, which is available separately for $100. (*) Local InterBase is a single-user SQL database engine. The version included in Delphi Desktop is intended to be used by developers who want to write SQL applications that can be seamlessly migrated to client/server environments, but without buying their own (expensive) server platform. However, Delphi Desktop does not include redistribution rights. If you want to distribute a single-user application that uses Local InterBase, you have to pay extra for the deployment kit. (**) The version of ReportSmith bundled with Delphi Desktop specifically detects and excludes any server-based ODBC drivers from its list of acceptable connections. Yes, you heard that right. Even though you've got third-party ODBC drivers, and even though you can talk to these drivers just fine from the Delphi environment, ReportSmith still won't work. If you want to do this without buying Delphi Client/Server, you can buy ReportSmith/SQL separately for $300. As an alternative, if you happen to already own a copy of Visual Basic, you can use the Crystal Reports VBX just fine from within Delphi. 1.6 Can you write multi-user database applications in Delphi Desktop? Using regular, non-client/server Delphi, I have developed an application that talks to a Sybase server using ODBC drivers. I didn't have to go to any serious trouble getting it to work, and data access speed is quite acceptable, better than it was under Visual Basic. Steven Lamotte says: "I think the benefits of the native SQL drivers relate mostly to speed. It may be true that ODBC allows you to do most everything a server permits, but your SQL commands still have to be processed by ODBC. I once wrote a program to compare Sybase SQL Server access with C++ using ODBC and using OpenClient (the native SQL interface for SQL Server) and the results were that the native interface version performed several times better than ODBC." 1.7 What is the history of Delphi? Delphi is the descendant of Turbo Pascal, which was first released in 1983 for the CP/M operating system. Turbo Pascal was ported to MS-DOS in early 1984. During the early history of the IBM PC, Turbo Pascal was arguably the most popular language for serious development work--mostly because it was a real compiler, including the program editor and everything, that cost $19.95 and would run on a 128k machine. Borland introduced Turbo Pascal for Windows in 1990. The latest release of Borland Pascal (as it is now called), not including Delphi, was version 7.0 in late 1992. Delphi had an unusually long deveopment cycle--somewhere between 18 months and two years, depending on who you talk to. Various beta-test and prerelease copies have been circulated, including several hundred "early experience" copies which were given away at the trade show Software Development '95. Delphi was officially announced in the US on Feb. 14, 1995, and the first release-level copies were shipped on Feb. 28. 1.8 Where can I get a copy of Delphi? If you are in the US, You can order Delphi Desktop on CD-ROM for an introductory price of $199 by calling Borland's credit card order desk at 1-800-331-0877. If you are a registered user of any version of Turbo Pascal or Borland Pascal, you qualify for an upgrade price of $149, and you can also buy the Visual Component Library Source Code for $49. The introductory pricing is good through approximately May 15, 1995; after that, the price will be raised to $495. Delphi Client/Server is $1999. Of course, if you buy through a reseller, you will probably pay less. According to Borland, "Delphi is available through the following US resellers: CompUSA, Best Buy, Elek-Tek, Computer City, Babbages, Software Etc., Fry's, Electronics Boutique, Corporate Software, ASAP Software Express, Egghead Software, Softmart, Software Spectrum, CDW, PC Connection, Programmer's Paradise, Programmer's Warehouse, ProVantage Shop, and Micro Warehouse." Note that you do NOT have to go through Borland directly to get the upgrade price. When you buy a copy of Delphi at the discounted retail price (US street prices are $179-$189), the box contains a coupon for the $50 discount if you mail in a serial number for Turbo or Borland Pascal. You have to send in a photocopy of your install disk, or the original first page of your manual. Borland also maintains list prices in several other currencies through their various international offices. In addition, distributors sell Borland products across the globe. I do not currently have any verified information about non-U.S. pricing for Delphi; check with the closest Borland office or with your distributor or reseller. 9 What if I don't have a CD-ROM drive? Borland will ship Delphi on 3.5" floppy diskettes, but they charge extra for them. The resellers I have spoken to only carry the CD-ROM version because they don't want to have to stock two different items. I got my copy on CD, but the CD has directories on it called DISK1 through DISK15, so I assume it would be 15 diskettes if you got it that way. If you don't get the CD, you won't get the stuff they use to fill up space on the CD, like an AVI file of an animated spinning Delphi logo. 1.10 How can I contact Borland? If you have the necessary access, you can get information directly from Borland at their web site, , or at their anonymous ftp site, ftp.borland.com. If this doesn't work for you, here is a list of their (voice) telephone numbers: Australia (61) 2 911 1000 Belgium/Luxembourg (32) 2 4610 448 Brazil (55) 11 851 5326 Canada (416) 229 6000 Chile (56) 2 233 7113 Denmark, Norway (45) 22 62 89 00 Eastern Europe, Mediterranean, Russia, Middle (33) 1 41 23 11 00 East France (33) 1 41 23 11 00 Germany, Austria, Switzerland (49) 61 03 9790 Asian Headquarters/Hong Kong (852) 540 4380 Italy (39) 2 26 91 51 Japan (81) 3 5350 9370 Korea (82) 2 551 2795 Latin America Headquarters (408) 431 1074 Malaysia (60) 3 230 2618 Netherlands (31) 020 540 5400 Singapore (65) 339 8122 Spain (34) 1 650 7250 Sweden, Finland (46) 8 799 20 00 Taiwan (886) 2 718 66 27 United Kingdom (44) 734 320 022 USA (408) 431 1000 11 What technical support do I get with Delphi? You get access to the "up and running" line, which will only answer questions related to installing Delphi and getting it to run on your machine. Also, it is worth noting that the hold times on this line are very long indeed--don't expect to talk to anyone without waiting 20 to 30 minutes. In order to get what borland calls "consultative" tech support (I.E. someone with whom you can discuss reasons why a program is not working), you have to pay $2/minute. You can call (900) 555-1015 and have the charges put on your phone bill, or else (800) 330-3372 and use a credit card. I have called twice, and they couldn't answer my question either time; however, they didn't charge me for the calls. 1.12 What known bugs exist in Delphi? A complete listing is beyond the scope of this FAQ; however, if you have WWW access, you can look at: . 1. I just bought Delphi. Where are the language and library reference manuals? They don't ship those manuals with Delphi because of their size. The component library reference is over 1000 pages. You can get all this information from the on-line help, or you can ftp the manuals from Borland in Acrobat format, or you can order the actual books for an additional charge. ------------------------------ 2. Delphi Resources. 2.1 What are some good books about Delphi? Delphi for Dummies, by Neil Rubenking, is the only one that has been widely circulated to general bookstores, and as usual with a For Dummies books, contains quite a bit of good information among the silly chapter headings and excitable prose. Other books that are either in print or on their way to print are: The Delphi Programmer Explorer, Duntemann/Mischel/Taylor Teach Yourself Delphi, Devra Hall Delphi by Example, Blake Watson Using Delphi, Special Edition, Namir Shammas Delphi Developer's Guide, XavierPacheco/Steve Teixeira Mastering Delphi, Charlie Calvert Teach Yourself Delphi in 21-Days, Andrew Wozniewicz Delphi How-To, Gary Frerking Developing Windows Applications Using Delphi, Paul Penrod Instant Delphi, Dave Jewell Delphi Nuts and Bolts, Gary Cornell and Troy Strain Software Engineering with Delphi, Edward C. Webber, J. Neal Ford, Special Edition Using Delphi, John Matcho, Mark Andrew, et al Developing Client/Server Applications with Delphi, Killen/Todd Delphi Programming Unleashed, Charlie Calvert Mastering Delphi, Tom Swan Mastering Delphi, Marco Cantu 2.2 Does anyone publish a Delphi magazine or journal? The following magazines are listed on the Borland WWW server: Delphi Developer, 12 issues/$99, Pinnacle Publishing (206) 251-1900 Delphi Informant, 12 issues/$49, Delphi Informant (916) 686-6610 Inside Delphi, 12 issues/$79, Cobb Group (502) 493-3200 The Delphi Magazine, 6 issues/???, The Delphi Magazine +44 0 181 460 0650 2.3 Where can I find sample source code and utilities for Delphi? Borland seems to use CompuServe as their primary on-line service. There are quite a lot of Delphi files in Borland's forum there. Borland also maintains ftp and www sites, but they don't include nearly as many files as the CompuServe forum. Various other web sites have sprung up with Delphi files here and there; try or . ------------------------------ 3. Compatibility. 3.1 What operating systems does Delphi support? The only version of Delphi that has been released is for Windows 3.1. There is no reason why it should not run correctly under systems that provide Windows 3.1 emulation, like OS/2 Warp, Windows NT, etc. Borland has announced plans for a 32-bit version to coincide with Windows 95. It is rumored that this might be a free upgrade to users of Delphi 1.0, but I wouldn't count on it. It is also known that Delphi 1.0 does not run correctly on the prerelease version of Windows 95. Applications built in Delphi are Windows 3.1, 16-bit applications. However, Borland has stated that existing Delphi applications will compile unmodified in 32-bit Delphi. Francis Whiteley points out that the readme.txt file for Delphi says: "Delphi has been tested under Windows 3.1, Windows for Workgroups 3.11, Windows NT 3.5, OS/2 Warp, and the latest pre- release version of Windows 95. Note that we do not recommend large-scale deployment of database applications running under Windows 95 until Microsoft certifies a release for commercial use." 3.2 What source management tools are compatible with Delphi? Delphi Client/Server is said to include built-in connectivity to PVCS. In addition, it should be possible to connect to most non-language-specific source control systems. However, Delphi forms are stored in non-text format, so a source control package must support binary data if it is to work with Delphi. If your have a source manager that simply cannot deal with binary files, Rick Thompson points out: "According to the docs (User Guide, pp. 94-95) you can save forms as ASCII text for editing or version control purposes. ASCII forms can also be loaded and resaved in binary *.DFM format." According to Chuck Lownie , "MKS Source Integrity (MKS SI is 2nd in PC/PCLAN source management market next to PVCS with over 35,000 developers using SI) also offers integration into Delphi. Our integration into Delphi is currently being shipped along with MKS Source Integrity, however, in a future maintenance release of Delphi, our integration will also be shipped in the Delphi box, similar to PVCS." 3.3 Can I use DLLs developed in C or C++ from Delphi? Delphi is capable of making calls to and receiving callbacks from any standard Windows DLL. In addition, it is said to be possible (though rather tricky) to get Delphi to access classes within C++ DLLs. Borland's WWW server has instructions on how to do this. I wasn't able to get it to work, but I think that's because I have weird DLLs. 3.4 Can I make calls to Delphi code from C or C++? Delphi can generate DLLs, which can be called from C, C++, Visual Basic, Powerbuilder, or anything else that understands standard Windows DLLs. There is an example of a database-capable DLL in the DEMOS\DB\DLL directory. As is the case in all Windows programming languages that I know of, DLLs are difficult to debug and will crash your system if they aren't quite right. Save your source code frequently. 3.5 What third-party packages are specifically known to work (or not work) with Delphi? Package/Manufacturer/Tested By/Comments Orpheus/TurboPower Software/graham@mhn.org/Orpheus is a package of native VBX controls (I.E. true Delphi objects, not VBXes), including full source code. It's in beta test, and expected to be in full production by May. It has a text editor that works with up to 16Mb files, a virtual list box, smart data entry fields, a timer pool that allows multiple timers without consuming as any Windows resources, spinners, better tabbed notebooks, and various other things. Crystal Reports VBX/Crystal Services/graham@mhn.org/The version of Crystal Reports that is included with Visual Basic works fine. I haven't tried other versions. The default class name, TReport, conflicts with the ReportSmith class built into Delphi, so I renamed it to TCrystalReport. Spread-VBX 2.0/FarPoint Systems/graham@mhn.org/When I tried to load Spread- VBX, Delphi immediately crashed, and shortly thereafter my entire system locked up. I guess that means it isn't compatible... Visual Basic's Grid/Microsoft/graham@mhn.org/This loads and runs fine, although once again Tgrid conflicts with stuff built into Delphi, so I renamed it to TVBGrid. I only installed this to see if it would work; Delphi's built-in grids are better. VBTools 3D Calendar/MicroHelp/graham@mhn.org/Works fine, except that it isn't data-aware once you load it into Delphi. VBTools Card Deck/MicroHelp/graham@mhn.org/Works fine VBTools Dice/MicroHelp/graham@.mhn.org/Works fine Data Widgets/Sheridan Software/graham@mhn.org/Can be made to work, sort of; but no data connectivity, so what's the point? Hey, you! I know you've used some VBXes (or whatever) with Delphi. Please e-mail graham@mhn.org with your findings so that this list can become more complete. 4. Database Questions. 4.1 How do I get access to a database from Delphi? In general, you have to go to "BDE Config" and define an alias for the database you want to connect to. This allows you to avoid hard-coding a directory path into your application; you just refer to the alias. Then, you create a minimum of three objects on the desktop: A Query or Table object that actually talks to the alias and gets some data; a Data Source object that links between the data and the controls, and at least one data- aware control. If you've been trying for hours to get this to work, and no matter what you do you just don't see anything happening, try setting the "active" property on the Table or Query to "True." This will open the database. I have seen many people get caught out by this the first time they try it. 4.2 Does Delphi support the back-end? Delphi Desktop does not directly support any back-ends except for Local InterBase, and of course the BDE (Borland Database Engine) itself. Delphi Client/Server directly supports Oracle, Sybase, Informix, and InterBase. In both cases, you can use third-party ODBC drivers to connect to any system you want. 4.3 What data-aware controls come with Delphi? Steve Teixeira says: Both versions contain the same data-aware components: TDBGrid (a data grid) TDBEdit (an edit control) TDBNavigator (a navigator with buttons to move around in a table) TDBLabel (a label control) TDBMemo (a multiline edit control useful for text blobs) TDBImage (a component that displays graphic fields) TDBRadioButton and TDBCheckBox (self-explanatory) TDBListBox, TDBComboBox, TDBLookupListBox, TDBLookupComboBox 4.4 Can I use the ODBC drivers that I got with ? Yes, generally. I have not encountered any ODBC drivers that don't work with Delphi, but on the other hand, I haven't tried any really exotic ones. 4.5 What about data-aware VBXes? Delphi only supports Level 1 VBX controls. This means that data-aware VBX controls *do not work* with Delphi. In general, anything that works with Microsoft Visual C++ should be okay in Delphi. Also, some data-aware VBX controls are sufficiently well-written that Delphi can make use of them and simply not access the data properties. See the compatibility list in section 3.5. 4.6 How do I write a "change password" function for a Paradox table? There is no way to do this within the Delphi VCL. Seems like a pretty serious omission to me. However, it is possible to do it by talking directly to the Borland Database Engine through the interface provided by the DBIPROCS and DBITYPES units. You call DbiDoRestructure, but set all the "number of" variables to zero, which makes it leave the existing values intact. I have code to do this, but it's a bit too long to included here. E-mail if you want it. 4.7 Why do I get errors when I call the Add method for a TFieldDefs? Because the documentation is wrong. There is an additional boolean flag that defines whether the field is required or not. The correct declaration for TFieldDefs.Add is as follows: procedure Add(const Name: string; DataType: TFieldType; Size: Word; Required: Boolean); 4.8 What is the procedure for connecting Delphi to an MS Access database? David Zaret posted: Here is the step-by-step process that I took to connect my Delphi app. to an Access database: Open up the Windows Control Panel. Open up the ODBC "Data Sources" icon. ADD a new Data Source of Type ACCESS DATA. Provide a unique "Data Source Name" (it doesn't really matter what you call it - description is optional). Choose the Database File by clicking the "Select Database" button. Close the "Data Source" window. Open up the "Database Engine Configuration" to get to the "BDE Configuration Utility" screen. Click on the "NEW ODBC Driver" button. Provide a "SQL Link Driver" - once again, it doesn't really matter what you call it. Select a Default ADBC Driver of type ACCESS DATA. Under "Default Data Source Name" choose the name of the ADBC driver that you provided from the Control Panel. Create a new alias by clicking on the "Alis" page tab. Click on the "New Alias" button. Give the alias a name. Select an Alias Type of ODBC_[WHATEVER YOU CALLED IT IN STEP 11]. Save your settings with File/Save. You can now close the BDE Config. Utility. IN YOUR PROJECT --- (I am sure that there are many ways to approach the next steps, but here's what I did) a) Add a Tdatabase component 1) Set the AliasName to the new alias that you just defined. 2) Provide a dummy DatabaseName. 3) Set the LoginPrompt to FALSE (if you don't want permission checking). b) Add a TQuery component. 1) Set the DatabaseName to the dummy name you provided in a.2) c) Add a TDataSource component. 1) Set the DataSet to the name of the TQuery comp. And you are done! You now have a SQL-ready, data-aware fomr that y ou can plop SQL into and data-aware components on to! 4.9 How can I manipulate data programmatically? It is sometimes desirable to write code that deals with databases but is not associated with any particular form or user-interface details. To do this, you declare variables of type TDatabase, TTable and/or TQuery, and set their properties in code just as you would in the design environment. Make sure that you include the DB and DBTables units in your uses statement, or you will get "unknown identifier" errors during compilation. ------------------------------ 5. Programming Questions. 5.1 What target formats can I create using Delphi? Delphi can create Windows 3.1 EXE files and DLL files. I am told that you can also create VBXes, but I have yet to figure out how you would go about it. Delphi does NOT create DOS EXE files. 5.2 I built a small test project. What are all these files? Here is a list of the file extensions created by Delphi and what they all mean: DPR - Delphi Project File. This is actually a Pascal source file; it just happens to be the main program for the application. ~DP - A backup file of the DPR file before the last save operation. PAS - In Delphi, PAS files are always the source code to either a unit or a form. The main program of an application is in the DPR file. ~PA - A backup of a .PAS file. DFM - These files are always paired with PAS files. The DFM file is the binary data used to set up initial data for components (IE, the properties you set in design mode rather than in code). You can't edit a DFM file with a text editor, but if you open it in Delphi, you will see a textual version of the contents. ~DF - A backup of a .DFM file. DCU - A compiled unit, similar in concept to an OBJ file. OPT - Project Options; i.e. compiler and linker settings, which form is the main form, what icon to use for the application, etc. Generally, the stuff you edit under Options/Project. RES - A Windows resource file; generated automatically by Delphi and required by the compilation process. You don't need to worry about this file, but don't delete it either. EXE - All of the above linked together into runnable format. 5.3 How can I yield the CPU to other tasks, like "DoEvents" in VB? The Delphi equivalent is Application.ProcessMessages. There is also an API function called Yield that seems to do the same thing, but it isn't safe to use from most Delphi applications. Steve Teixeira explains: You should not use Yield() unless your application is *guaranteed* not to receive any messages (ie, your application contains no windows). Instead, the way to do this in Delphi is to call Application.ProcessMessages. ProcessMessage encapsulates a PeekMessage() loop, which is the correct "API-way" to do this. 5.4 Why do I get compile errors accessing the Sender object in events? If you look at the declaration, the Sender object is of type TObject, which is the class from which (almost) all other objects are derived. You're probably trying to access a property that isn't defined in TObject, like Text or Caption or something. For this reason, "Sender.Text" will fail, but if (for example) you know that the sender is of type TEdit, then you could use "(Sender As TEdit).Text". If you aren't certain that the Sender object will always be the same type, you can check it with "if (Sender is TEdit) then ;". See section 5.14. 5.5 Are there any tools to help me migrate my applications to Delphi? There is an automated translator that converts Visual Basic projects to Delphi. I have heard from a couple people who have tried using it, and the results seem to be pretty mixed. It's very useful for some people, but not useful at all for others. It is made by: EarthTrek 7 Mountain Rd. Burlington, MA 01803 (617) 273-0308 5.6 What's the Delphi equivalent of Visual Basic control arrays? There isn't one. Delphi components do not have an Index property like VB controls, so you can't declare an array of them. However, there are three main reasons why you might want to, and each of them can be done in Delphi. Here's how: Reason 1. You want to share event handlers between different controls on a form. This is really easy. All you have to do is select the same event handler procedure in each of the controls' events. This is better than control arrays because you can even have the same event handler function across different kinds of control; for example, a toolbar button and a menu item can call the same function directly in each of their Click events. Reason 2. You want to be able to dynamically allocate and deallocate controls at run-time. This is also pretty easy in Delphi. Suppose you have a button on a form, and each time it is clicked, you want to create another, different button. The following sample code shows how to do this: procedure TForm1.Button1Click(Sender: TObject); var NewButton: TButton; begin NewButton := TButton.Create(Self); NewButton.Parent := Self; end; It is important to note that once this event finishes, the NewButton variable goes out of scope and we no longer have a pointer to the newly- created control. You can't deallocate a control within its own event handlers, so if at some point you want to remove one or more dynamically- created controls, you have to search for them in the Form.Controls array and/or maintain your own list of pointers to the controls you create. Assuming that there are no control event handlers running, it is safe to deallocate a control by just calling its Free method. Reason 3. You really want to access controls by number. I ran across this when I decided to write a board game similar to Reversi as a Delphi learning project. I had 100 TShape controls on a form, in a 10x10 grid. So, I painted all the shapes in the form designer and allowed it to give them names like "ShapeNN", but then I also declared an array of pointers to controls: "Board: array[1..10, 1..10] of ^TShape;" and populated it in the form's Create event. This is a hundred lines of code that really shouldn't be necessary, but from then on I could access controls in a two-dimensional array, like this: "Board[3,5]^.Brush.Color := clRed;" -- which is more than I could have done with VB. 5.7 How do I close a modal form? For that matter, what's the best way to close any form? Generally speaking, you call the form's Close method. This runs the OnClose event, which may decide it doesn't want to close, for example if there is unsaved data in the form. Close doesn't free the memory associated with the form, unless of course you put a call to Release in the form's OnClose event. If you want to close a form without giving it a chance to argue, call the form's Release method. This is similar to Free, but it allows event handlers (e.g. OnDestroy) to finish running before the memory goes away. Modal forms "end their modal state" when you set the form's ModalResult property to anything greater than zero. If you put a button on a modal form and set the button's ModalResult property to some value, then when the user clicks on that button the form will close with the result you specified. You can find out what the result was by calling ShowModal as a function; i.e. result := Form.ShowModal. 5.8 Are there commercial applications developed in Delphi? Not as far as I know. Delphi hasn't been released that long--give it time. If you can write a commercial application in VB, then you can definitely write one in Delphi. Of course, Delphi itself is written in a combination of Delphi and assembler (or so it is said), and it's certainly a commercial product. 5.9 Do I have to know a lot about the Windows API to use Delphi? There seems to be a feeling that you need to know more about Windows to use Delphi than you do to use Visual Basic. This isn't really true; you can get by in both environments with a very minimal understanding of Windows internals. However, in both environments, you have to know at least a little about the Windows API in order to really make the most of what you have. The difference is that Delphi gives you a lot more power to do all these interesting things, so you feel more limited if you don't know how. 5.10 Do I have to understand object oriented programming to use Delphi? Well, yes, to a point. Delphi's user interface design tools produce object- oriented code. However, if you're familiar with either Visual Basic or Powerbuilder, you probably have enough understanding of OOP to get by. You can do a great deal in Delphi without having to create your own objects, which is the point at which it becomes important to really understand something about them. 5.11 How does Delphi's exception handling work? The basic structure goes something like this: p := new(big_thing); try blah(p); foo(p); finally dispose(p); end; The first line allocates a big block of memory. Then, in the "try" block, we execute several statements, each of which might produce an error--or, in other words, "raise an event." If an error does occur, the rest of the "try" block will be skipped, "finally" blocks will be executed. If there are no errors, then the "finally" block will be entered when the last statement in the "try" block completes. So, either way, the big block of memory gets freed. These "try/finally" blocks will trap anything up to and including a Windows GPF. In addition, you can construct "except" blocks which can provide local error handling either for all errors or for particular types of error; and you can also create your own global error handler to trap exceptions that aren't otherwise handled by try blocks. See Chapter 7 in the Delphi User's Guide for more details. 5.12 Does Delphi use Pascal or C style strings? Both. Delphi has two different sets of string manipulation functions, one for null-terminated strings, and one for Pascal-type (I.E. length byte) strings. You will find yourself stumbling across this distinction from time to time. Mostly, there are Delphi functions that wrap around the most common Windows API functions; for example, MessageBox, which is a Windows API call, requires a PChar; but Delphi also has MessageDlg, which accepts Pascal-type strings. If you have text in a Pascal string and you want to pass it to a function that expects a PChar, the following code is a "quick and dirty" way of doing it, assuming that s is of type string and that the string has room for one more character: s[length(s)+1] := #0; { Appends a null to the end of the string } C_Style_Function(@s[1]); { @s[1] is a PChar to the beginning of s } 5.13 How does Delphi handle Windows callbacks? Just like C: You can get a far pointer to your callback procedure (you have to remember to declare it with the "far" qualifier, unless you have {F$+} in effect to force all calls to be far), pass the pointer to the Windows callback function, and there it is. 5.14 How does Run-Time Type Information (RTTI) work? There are two new operators: "as" and "is." The "as" operator is a protected typecast. You can use it to force the compiler to treat an object of one type as another type, but if at run-time the typecast is not properly compatible, then you will get an error. For example, if you have a class called TSport, with descendants TBasketball and TFootball, you might want a variable of type TSport--but you might also happen to know at a certain point in the program that this variable actually contains an instance of a TFootball. So, you can refer to it as (MySport as TFootball) in order to get access to its football-specific properties. However, if you are wrong and somehow a TBasketball gets passed in, instead of just looking at the data in some oddball way like a regular typecast, this will generate an error. The "is" operator is used to compare an instance of an object to a class of objects, to see if a typecast using "as" will work. If you have a variable MySport of type TSport, and it currently contains an instance of a TBasketball, then the following statements are true: (MySport is TSport) (MySport is TBasketball) not (MySport is TFootball) The combination of these two operators might lead to code such as the following: function player_goodness(var MySport: TSport): integer; begin if (MySport is TBasketball) then player_goodness := (MySport as TBasketball).rebound_shots else if (MySport is TFootball) then player_goodness := (MySport as TFootball).total_yardage; end; It has been pointed out that this would be better implemented as a method which TSport defines and TBasketball and TFootball override, but then it wouldn't illustrate how RTTI works, would it? :-) 5.15 I'm creating a toolbar, but I have icons, not bitmaps. Help! Your best bet is to own something like HiJaak which can do the conversion directly. However, assuming that you have nothing but Windows and Delphi, the following procedure can be used to convert an icon to a bitmap: Display the icon somehow. Doesn't matter how you do it. Press Alt-PrintScreen to copy the current window to the clipboard. Load Paintbrush and do an Edit/Paste. Highlight the icon using the square selection tool and do an Edit/Copy. Go to Options/Image Attributes and set the working area to 32x32 pixels. Do an Edit/Paste again. Save the result as a BMP file. 5.16 When I use the Glyph property, how do I know which color is transparent? Delphi always assumes that the color of the bottom left-hand corner pixel is the background color and should be displayed as transparent. Yes, it took me a while to figure this out. It's not documented anywhere, but if you have the VCL source, you can look at the code in BUTTONS.PAS. 5.17 How can I make my Delphi application respond to Windows messages? Using WM_WININICHANGED as an example, Chuck Jazdzewski says: Declaring a method in a TForm will allow you to handle WM_WININICHANGED messages: procedure WMWinIniChange(var Message: TMessage); message WM_WININICHANGE; The body of the implementation could look like: procedure TForm1.WMWinIniChange(var Message: TMessage); begin inherited; {.. react to someone mucking with control panel ..} end; The call to "inherited" is important. Note also that message handlers are special when calling their inherited since you don't refer to the name of the inherited. This is because the inherited is referring to the inherited message handler for this message number, which might not have a visible name or or even the same name as you have given it, or in some cases, might not even exist (in which case you are really calling DefaultHandler). 5.18 How can I allocate blocks of memory larger than 64k? Reinier Sterkenburg says: The answer is: use GlobalAlloc and GlobalLock from the WinProcs unit. New question is then: why can't we use GlobalAllocPtr anymore? Answer: I don't know. 5.19 Is it possible to write a Windows screen saver in Delphi? Thomas W Wolf says: Someone posted a message requesting information on how to use Delphi for a screen saver. a) In the project file (*.dpr) add '{$D SCRNSAVE } after the uses clause. b) On the main form, turn off the border and icon controls. In the activate method set the form left and top to 0, and set the Windowstate to wsMaximize. c) In the form create method, set the application.OnMessage to a method that controls the deactivation of the screen saver. Set the application.OnIdle method to whatever display method for the saver. d) In the form create method the command line should be tested for /c and /s. These are the command line parameters windows uses to define whether the screensaver should run or configure. (/c is for configuration) e) Compile the program, and rename the .exe to .scr. Move it to the windows directory, and it should show up in the control panel. 5.20 I'm trying to call from Delphi and it GPFs. What's up? Based on the number of postings to comp.lang.pascal, it would seem that by far the largest number of problems calling Windows API functions or non- Delphi DLLs are caused by passing Pascal-style strings to functions that expect null-terminated (PChar) strings. This is the first thing you should check if you get a GPF or other strange results when calling an external function. See section 5.12 for more information on which type of strings go where. 5.21 How can I add pages to a TTabbedNotebook at run-time? The following source code, which assumes that you have a tabbed notebook called TabbedNotebook1, will add a new page that contains an "OK" button: procedure whatever_whenever; var NewPage: TTabPage; NewPageNumber: word; NewButton: TButton; begin {Create the new TTabPage object} NewPage := TTabPage.Create(Application); {The page must be a child of the notebook} TabbedNotebook1.InsertControl(NewPage); {Add text to the notebook's Pages property; this will cause the new page to be added as the last tab on the notebook} NewPageNumber := TabbedNotebook1.Pages.Add(`New Page'); TabbedNotebook1.PagesObjects[NewPageNumber] := NewPage; {The page needs controls on it; here's how to add one} NewButton := TButton.Create(Self); (TabbedNotebook1.Pages.Objects[NewPageNumber] as TWinControl) .InsertControl(NewButton); NewButton.Top := 10; NewButton.Height := 30; NewButton.Width := 100; NewButton.Caption := `OK'; end; 5.22 I'm painting complex graphics. How can I speed up redrawing? Steve Teixeira says: Use a TBitmap component as a memory DC. You can then copy from Bitmap.Canvas to your form's Canvas. 5.23 How can I hade MDI child windows? Steve Teixeira says: You can't hide MDI children. Windows does weird things when you try to hide MDI children, so VCL doesn't permit it. 5.24 How do I write a global error handler? Use the Application.OnException event. Look in the help under "application events" for details of how to create and attach an event handler to the application variable. 5.25 Why do I get exception messages even though I'm in protected code? By default, the internal debugger will halt any time there is an exception, even if the exception is trapped by code. This can often be useful for debugging purposes. If it offends you, turn it off. You control it from the Options/Environment menu. 5.26 I've added code to my OnKeyPress event that traps Enter keys, but it keeps beeping at me and/or activating the default button. How do I make it stop? The problem is that even though you're running your own handler code, you are also allowing the Enter key to pass through and activate the default behavior for an Enter key. In order to prevent this, set key := 0, which will send a null keystroke through to the default handler. 5.27 I want to modify a component's properties at run-time, but it isn't convenient to store a pointer to the component. Is there an easy way to get access to it? Use the library function FindComponent to search by name. If you need to search by properties other than name, iterate through the form's Components array. ------------------------------ 6. Questions about distributing Delphi applications. 6.1 Is there anything in Delphi similar to the VB "setup wizard?" No. There are some third-party tools available, but out of the box Delphi does not have anything to automate the creation of setup disks. You can of course write your setup program in Delphi, but you have to write it yourself. If you do decide to use a third-party installation tool, check out Chief's Installer Pro. You can get it via anonymous ftp to ftp.demon.co.uk as /pub/ibmpc/windows/chief/pro/cinstp17.zip. 6.2 What files am I allowed to redistribute with my applications? If you have Delphi Desktop, you are allowed to redistribute run-time versions of the Borland Database Engine and of ReportSmith. Of course, you can also distribute the EXE or DLL files you create yourself. Borland has some rather odd and overly restrictive licensing terms; for example, your programs are required to bear a valid copyright notice (if not yours, then Borland's)--which seems to mean that you can't create public domain applications using Delphi. Also, if you distribute the Borland Database Engine, you are required to send out the whole thing with all relevant drivers. This is because other, previously-installed applications may also use BDE functions, and if you take away their drivers, well, that's a bad thing. 6.3 If I want to send out a Delphi-compiled EXE file, what other files do I need to send with it? None. Everything is compiled into the .EXE file. Of course, if you've developed other files (like a HLP file, data files, etc.), or if you're using VBX files, then you have to send them as well. If you use VBX files, you must also include BIVBX11.DLL. If the application uses database functions, you also have to include the Borland Database Engine. You can just distribute the two pre-packaged disks on the Delphi CD (they don't get installed to your hard drive). And if the application uses ReportSmith, you have to distribute the ReportSmith run- time. These are big; the BDE is two disks and ReportSmith is five. 6.4 I want to distribute a database application, but I don't want to force all my users to create BDE aliases. What do I do? The simplest answer is to avoid using aliases in your application. Everyting you can set in an alias, you can also set as properties or in the Params section of a TDatabase object. For example, if you are accessing Paradox files, you can add a "PATH=d:\dir\path" line to the Params collection, avoiding the need to use a BDE alias to specify the directory where the files reside.