The Delphi FAQ

Maintainer: Graham Mainwaring
Last Updated: 8-Oct-1995


Table of Contents

Section 1 - Introduction

1.1. What is the purpose of this FAQ?
1.2. How can I get the latest version of this FAQ?
1.3. Is this FAQ copyrighted?

Section 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 get Delphi files via WWW and FTP?
2.4. What other FAQs or FAQ-like documents exist for Delphi?

Section 3 - General Questions

3.1. What is Delphi?
3.2. What versions of Delphi are there?
3.3. How much disk space, memory, etc., do I need to run Delphi?
3.4. How tough is it to learn Delphi?
3.5. What's the difference between Delphi and Delphi Client/Server?
3.6. Can you write multi-user database applications in regular Delphi?
3.7. What is the history of Delphi?
3.8. Where can I get a copy of Delphi?
3.9. What if I don't have a CD-ROM drive?
3.10. How can I contact Borland?
3.11. What technical support do I get with Delphi?
3.12. What known bugs exist in Delphi?
3.13. I just bought Delphi. Where are the language and library reference manuals?
3.14. Are there commercial applications developed in Delphi?
3.15. What patches to Delphi exist?

Section 4 - Compatibility

4.1. What operating systems does Delphi support?
4.2. What source management tools are compatible with Delphi?
4.3. Can I use DLLs developed in C or C++ from Delphi?
4.4. Can I make calls to Delphi code from C or C++?
4.5. What Dephi-specific third-party packages are available?
4.6. What non-Delphi-specific third-party packages are specifically known to work (or not work) with Delphi?

Section 5 - Database Questions

5.1. How do I get access to a database from Delphi?
5.2. Does Delphi support the back-end?
5.3. What data-aware controls come with Delphi?
5.4. Can I use the ODBC drivers that I got with ?
5.5. What about data-aware VBXes?
5.6. How do I write a "change password" function for a Paradox table?
5.7. Why do I get errors when I call the Add method for a TFieldDefs?
5.8. What is the procedure for connecting Delphi to an MS Access database?
5.9. How can I manipulate data programatically?
5.10. Is it possible to add referential integrity to a Paradox table at run-time?

Section 6 - Programming Questions

6.1. What target formats can I create using Delphi?
6.2. I built a small test project. What are all these files?
6.3. How can I yield the CPU to other tasks, like "DoEvents" in VB?
6.4. Why do I get compile errors acessing the Sender object in events?
6.5. Are there any tools to help me migrate my applications to Delphi?
6.6. What's the Delphi equivalent to Visual Basic control arrays?
6.7. How do I close a modal form? For that matter, what's the best way to close any form?
6.8. Do I have to know a lot about the Windows API to use Delphi?
6.9. Do I have to understand object-oriented programming to use Delphi?
6.10. How does Delphi's exception handling work?
6.11. Does Delphi use Pascal or C style strings?
6.12. How does Delphi handle Windows callbacks?
6.13. How does Run-Time Type Information (RTTI) work?
6.14. I'm creating a toolbar, but I have icons, not bitmaps. Help!
6.15. When I use the Glyph property, how do I know which color is transparent?
6.16. How can I make my Delphi application respond to Windows messages?
6.17. How can I allocate blocks of memory larger than 64k?
6.18. Is it possible to write a Windows screen saver in Delphi?
6.19. I'm trying to call from Delphi and it GPFs. What's up?
6.20. How can I add pages to a TTabbedNotebook at run-time?
6.21. I'm painting complex graphics. How can I speed up redrawing?
6.22. How can I hide MDI child windows?
6.23. How do I write a global error handler?
6.24. Why do I get exception messages even though I'm in protected code?
6.25. 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?
6.26. 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.27. How do I create help for new components so that the Delphi help file is not corrupted?
6.28. What's the best way to handle large data elements (bigger than 64k) in 16-bit Delphi?
6.29. Can I make a form come up centered?
6.30. How do I extract an icon from an .EXE file?
6.31. How can I a form on creation, before it is shown to the user?
6.32. What should I give to Windows API functions that want a hWnd?
6.33. How do I use the palPalEntry in TLogPallette?
6.34. What is required to make a label with an accelerator key set focus to a different control?
6.35. How can I calculate the height and width of text to be displayed in a particular font?

Section 7 - Questions about distributing Delphi apps

7.1. Is there anything in Delphi similar to the VB "setup wizard?"
7.2. What files am I allowed to redistribute with my applications?
7.3. If I want to send out a Delphi-compiled EXE file, what other files do I need to send with it?
7.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?


Section 1 - Introduction

1.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 pure sense of the term, because some of the questions answered here are not really very frequently asked at all.

1.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 http://www.mhn.org/delphi.faq.

1.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.


Section 2 - Delphi Resources

2.1. What are some good books about Delphi?

Comments from the denizens of comp.lang.pascal:

James R. Ward jward@neosoft.com says: "Also, I have purchased 'Instant Delphi' which is somewhat introductory, but pretty good. (I'm not returning it!)"

Paul Johnson pauljo@netcom.com says: "I bought a copy of Mr. Duntemann's book two days ago at my local book sellers, so it is definitely out. It appears to be a very good book. I also bought Delphi for Dummies, but I found it too cute for my tastes (which is a shame, because Neil Rubenking is an excellent writer and teacher). The best book I have found is Instant Delphi by Dave Jewel (if memory serves). The examples are good and provide enough detail and background information to get you (me) going in the right direction. I highly recommend it (comes with a disk, too)."

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 1181 460 0650

2.3. Where can I get Delphi files via WWW and FTP?

Borland seems to use CompuServe as their primary on-line service, although their Internet presence is rapidly improving. Borland's home page and their ftp site. Various other web sites have sprung up with Delphi files here and there:

Nick Hodges' Home Page
The Delphi Bug List
Turbo Pascal Programmers Page
Delphi Tech Support Home Page
Wild Thing Cool Delphi Stuff
Coriolis Group Delphi EXplorer
CITY ZOO Inc. Home Page
The Delphi Connection WWW Site
Jeroen Prins' Home Page

2.4. What other FAQs or FAQ-like documents exist for Delphi?

Borland Tech Support maintains a set of Delphi FAQs, also available on CompuServe.

Raymond Kennington marwk@levels.unisa.edu.au has produced a FAQ which contains several fairly lengthy source code examples.

Robert Vivrette e-publishes the "Unofficial Newsletter of Delphi Users," which is available on Wild Thing's Delphi home page and on CompuServe.


Section 3 - General Questions

3.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.

3.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.

3.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.

3.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.

3.5. What's the difference between Delphi 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.

3.6. Can you write multi-user database applications in regular Delphi?

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 slamotte@jenex.mb.ca 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."

3.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 64k 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.

The development of Delphi started sometime in 1993. 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 U.S. on Feb. 14, 1995, and the first release-level copies were shipped on Feb. 28.

3.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.

3.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.

3.10. How can I contact Borland?

If you have the necessary access, you can get information directly from Borland's web site, or 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 East: (33) 1 41 23 11 00
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) 1734 320 022
USA: (408) 431 1000

3.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. The long hold times that were common when Delphi was first released seem to have improved--the current average seems to be about five minutes or so.

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.

3.12. What known bugs exist in Delphi?

A complete listing is beyond the scope of this FAQ; however, there is a separate Delphi bug list.

3.13. 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.

3.14. 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 Delphi.

Chuck Jazdzewski cjazdzewski@wpo.borland.com gives us the details:

The development environment is a Delphi project. This includes all the menus, dialogs, editor interface (display and keystroke interpreter), debugger interface (breakpoint managment, evaluator dialogs, etc), form designer, object inspector, etc. In other words, just about anything you see while using Delphi was written using Delphi. The back-ends are written using other languages since the code already existed. The compiler/linker, for example, is written in assembler (essentially the same compiler technology that shipped in Turbo Pascal 4.0). The debug kernel DLL (PASDBK16) and the editor kernel (text buffer manipulation) (DELPHIED and DELPHIKB) are written in C from a shared code base with the BC++ team.

3.15. What patches to Delphi exist?

Borland has released patches for Delphi, Delphi Client/Server, and the VCL source code. The files are available from Borland's ftp site as delpatch.exe, delcspat.exe, and vclpatch.exe. If you have the VCL source code, apply the Delphi patch first, then the VCL patch.

According to the README.TXT file included with delpatch.exe, the patch file address the following problems:

1. Improved compatibility with Windows 95 M8 beta for MDI (e.g. new child) and OLE2 (e.g. insert object).
2. IDE debugger compatibility fix for NT.
3. Fixed MDI design mode problem when minimizing MDI Child window.
4. Significant updates to OLE2 API unit (see \DELPHI\DOC\OLE2.INT).
5. Fixed unit version problem in DLIB.EXE.
6. Fixed problem in Browser when you double-click a reference to a .PAS file that is not already open in the editor.
7. Fixed Options|Rebuild Library problem when the current project has an active Dataset.
8. Fixed Alt+Tab problem in Grid control.
9. Fixed DBGrid to allow cancel of SetKey mode.
10. TForm.DefineProperty now calls its inherited method.
11. Support for owner draw in TOutline.
12. DBImage.CutToClipboard now correctly updates the clipboard.
13. In TDataSource.OnDataChange, fixed invalid pointer in the Field Parameter.
14. Fixed various demo problems.


Section 4 - Compatibility

4.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. Upgrade pricing has not been announced.

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 whiteley@croughton.win-uk.net 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."

4.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 rat@ab00.larc.nasa.gov 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."

Duncan Murdoch dmurdoch@mast.QueensU.CA adds: "The CONVERT.EXE program does this conversion from the command line. I don't know if it's documented anywhere."

According to Chuck Lownie chuck@mks.com, "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."

4.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.

4.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.

4.5. What Dephi-specific third-party packages are available?

InfoPower: Super Database Grid, Lookup Comboboxes, Advanced Filtering, Auto-Expanding Memo, Database Sort Component, Incremental Search Component, Dialog Component. Woll2Woll Software, (800) WOL2WOL or (408) 293-9369;

Rocket: Database engine compatible with FoxPro, Clipper, and HyPer-Six (whatever that is). Their ad says: "Plus, we've included a set of Delphi CLASS-WRAPPERS for complete plug-n-play integration." The control was originally developed for VB. SuccessWare, (909) 699-9657.

DrawKit: Drawing and design application builder kit. Handles .wmf, .bmp and .drw files. Includes floating toolbox component. 25+ compoments. Mobius Ltd., +44 131 467 3267. (This is a UK number. You can also use e-mail to 73563.533@compuserve.com.)

Business Builder: Contains "specialized table subclasses" with built-in functions for common items like customers, vendors, sales & purchase orders, etc. 30+ components. Mobius Ltd., +44 131 467 3267. (This is a UK number. You can also use e-mail to 73563.533@compuserve.com.)

VisualPROS for Delphi: Progress meter, background-bitmap tool for controls and forms, improved balloon help, INI files and Registry component, Visual Prompt, Visual LED, enhanced bitmap button, and improved menu control. Shoreline Software, (800) 261-9198 or (203) 870-5707.

Async Professional for Windows: Comm port control, including Zmodem, Kermit, CIS B+, Ymodem and Xmodem; ANSI emulation; modem database. TurboPower Software, (800) 333-4160 or (719) 260-9136.

Orpheus: Currently in beta test, but you can buy it as an "early experience" product. Data entry fields, array editors, virtual listbox, 16Mb-capacity text editor, unlimited-size viewer for text or binary data, improved tabbed notebook control, timer pool, rotated font label, calendar, meter, spinner, four-way spinner. TurboPower Software, (800) 333-4160 or (719) 260-9136.

TOLEAutomationClient: The component lets you control OLE Automation servers using Delphi syntax that's analogous to the way it's done in Visual Basic. Besides taking care of initialising the Windows OLE libraries, etc., it lets you activate a server and then access its exposed properties and call its exposed methods, passing arguments either by value or by reference. Fax: +64 9 832 0088; E-mail: sraike@iconz.co.nz

4.6. What non-Delphi-specific third-party packages are specifically known to work (or not work) with Delphi?

- Package/Manufacturer/Tested By/Comments
- Crystal Reports VBX/Crystal Services/graham (at) 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 (at) 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 (at) 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 4.0/MicroHelp/graham (at) mhn.org, alexdy@mistral.co.uk/Most controls work fine, except the ones that are specific to VB, and the fact that the data-aware controls aren't.
- Data Widgets/Sheridan Software/graham (at) mhn.org/Can be made to work, sort of; but no data connectivity, so what's the point?
- Formula One/VisualTools/david_zaret@il.us.swissbank.com/Works great with Delphi.
- Visual Speller/VisualTools/graham (at) mhn.org/Works fine--the DLL interface seems a bit more robust, although the VBX works too.

Hey, you! I know you've used some VBXes (or whatever) with Delphi. Please e-mail graham (at) mhn.org with your findings so that this list can become more complete.
minimum of


Section 5 - Database Questions

5.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.

5.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.

5.3. What data-aware controls come with Delphi?

Steve Teixeira steixeir@borland.com 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

5.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.

5.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.

5.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 graham (at) mhn.org if you want it.

5.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);

5.8. What is the procedure for connecting Delphi to an MS Access database?

David Zaret zaretd@il.us.swissbank.com posted the following (the text formatting has been edited to support the HTML version of the FAQ)):

Here is the step-by-step process that I took to connect my Delphi app. to an Access database:

1) Open up the Windows Control Panel.
2) Open up the ODBC "Data Sources" icon.
3) ADD a new Data Source of Type ACCESS DATA.
4) Provide a unique "Data Source Name" (it doesn't really matter what you call it - description is optional).
5) Choose the Database File by clicking the "Select Database" button.
6) Close the "Data Source" window.
7) Open up the "Database Engine Configuration" to get to the "BDE Configuration Utility" screen.
8) Click on the "NEW ODBC Driver" button.
9) Provide a "SQL Link Driver" - once again, it doesn't really matter what you call it.
10) Select a Default ADBC Driver of type ACCESS DATA.
11) Under "Default Data Source Name" choose the name of the ADBC driver that you provided from the Control Panel.
12) Create a new alias by clicking on the "Alis" page tab.
13) Click on the "New Alias" button.
14) Give the alias a name.
15) Select an Alias Type of ODBC_[WHATEVER YOU CALLED IT IN STEP 11].
16) Save your settings with File/Save.
17) You can now close the BDE Config. Utility.
18) IN YOUR PROJECT --- (I am sure that there are many ways to approach the next steps, but here's what I did)
18.a) Add a Tdatabase component
18.a.1) Set the AliasName to the new alias that you just defined.
18.a.2) Provide a dummy DatabaseName.
18.a.3) Set the LoginPrompt to FALSE (if you don't want permission checking).
18.b) Add a TQuery component.
18.b.1) Set the DatabaseName to the dummy name you provided in a.2)
18.c) Add a TDataSource component.
18.c.1) Set the DataSet to the name of the TQuery comp.

And you are done! You now have a SQL-ready, data-aware form that you can plop SQL into and data-aware components on to!

5.9. How can I manipulate data programatically?

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.10. Is it possible to add referential integrity to a Paradox table at run-time?

Not quickly. With some work, it should be possible to do it using the dbiprocs and dbitypes units. If someone gets it to work, please let me know...


Section 6 - Programming Questions

6.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.

Duncan Murdoch dmurdoch@mast.QueensU.CA clarifies: "The command line compiler can create DOS and DOS-DPMI programs, with the same /CD and /CP options that BPC used. The main problem is that Delphi doesn't ship with libraries for these; you'd have to write those yourself, and it would be a lot of work."

6.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.
DSM - Symbol information file, used by the internal debugger. This file is recreated each time you do a build. If you delete it, Delphi will complain until you rebuild.
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.

6.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 steixeir@borland.com 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.

6.4. Why do I get compile errors acessing 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 < blah> ;". See section 5.14.

6.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

6.6. What's the Delphi equivalent to Visual Basic control arrays?

There isn't one, precisely. Delphi components do not have an Index property like VB controls, so you can't manipulate an array of them at design-time the same way you can in VB. In fact, it causes an error if you try to declare an array of controls in the top section of a form object; the design-mode interface can't interpret it. However, there many ways to achieve similar results, depending on why you wanted control arrays in the first place:

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. When I did this initially, I just used a hundred lines of code, but it has subsequently been pointed out that since these are the only TShape controls on the form, I could just as easily have iterated through the form's Controls array. Anyway, once it was set up 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.

6.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.

6.8. 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.

6.9. 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.

6.10. 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.

6.11. 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 }

6.12. 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.

6.13. 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? :-)

6.14. 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:

1. Display the icon somehow. Doesn't matter how you do it.
2. Press Alt-PrintScreen to copy the current window to the clipboard.
3. Load Paintbrush and do an Edit/Paste.
4. Highlight the icon using the square selection tool and do an Edit/Copy.
5. Go to Options/Image Attributes and set the working area to 32x32 pixels.
6. Do an Edit/Paste again.
7. Save the result as a BMP file.

6.15. 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.

6.16. How can I make my Delphi application respond to Windows messages?

Using WM_WININICHANGED as an example, Chuck Jazdzewski cjaz@borland.com 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).

6.17. How can I allocate blocks of memory larger than 64k?

Reinier Sterkenburg < sterkenb@pml.tno.nl> says:
The answer is: use GlobalAlloc and GlobalLock from the WinProcs unit.

Chuck Jazdzewski cjazdzewski@wpo.borland.com elaborates:
Also you might want to use the MemAlloc from Graphics which will allocate the memory from the normal pascal sub-allocater if it is less than 64k. This routine will always the memory the way
that is most efficient.

Once you have allocated a larger-than-64k block of memory, you will probably need to access elements within it. The problem is, pointer arithmetic won't work too well when it crosses a 64k boundary. Thomas AW Brown T.Brown@ite.ac.uk discusses one way to solve this problem:

The OffsetPointer procedure was lifted directly from the VCL source code (in the CLASSES.PAS file). My knowledge of assembler is rather limited, so suffice to say that you can drop it into a Unit and just use it PROVIDED THAT YOU ALSO DECLARE the __AHSHIFT PROCEDURE PRIOR. Here is a unit you could use, and include in a project and forget...

{This works in Windows 3.1, 3.11, WorkGroups 3.11 and Windows95 preview}
Unit OfsetPtr;

interface

function OffsetPointer(P: Pointer; Ofs: Longint): Pointer;

implementation

procedure __AHSHIFT; far; external 'KERNEL' index 113;

function OffsetPointer(P: Pointer; Ofs: Longint): Pointer; assembler;
asm
MOV AX,Ofs.Word[0]
MOV DX,Ofs.Word[2]
ADD AX,P.Word[0]
ADC DX,0
MOV CX,OFFSET __AHSHIFT
SHL DX,CL
ADD DX,P.Word[2]
end;

end.

6.18. Is it possible to write a Windows screen saver in Delphi?

Thomas W Wolf twwolf@cacd.rockwell.com 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 < saver name> } 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.

6.19. 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 6.11 for more information on which type of strings go where.

6.20. 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;

6.21. I'm painting complex graphics. How can I speed up redrawing?

Steve Teixeira steixeir@borland.com says:

Use a TBitmap component as a memory DC. You can then copy from Bitmap.Canvas to your form's Canvas.

6.22. How can I hide MDI child windows?

Steve Teixeira steixeir@borland.com says:

You can't hide MDI children. Windows does weird things when you try to hide MDI children, so VCL doesn't permit it.

6.23. 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.

6.24. 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.

6.25. 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.

6.26. 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.27. How do I create help for new components so that the Delphi help file is not corrupted?

Raymond Kennington marwk@levels.unisa.edu.au says:

"It is necessary in HelpInst to load the current .KWF file which one wants to add the new help file to before running the add option."

6.28. What's the best way to handle large data elements (bigger than 64k) in 16-bit Delphi?

Ivar Steinsund has created a huge array unit for Borland Pascal, and it works in Delphi. It came to me from Raymond Kennington, and is available on the MHN FTP server.

6.29. Can I make a form come up centered?

Set the form's Position property to poScreenCenter, and it will come up centered forever after.

6.30. How do I extract an icon from an .EXE file?

Anders Ohlsson ao@spirou.e.kth.se says:

The API has a function ExtractIcon that does the job nicely.

Like:

{ Extract the icon }
TheIcon := ExtractIcon(HInstance,IconFile,IconNr);
if TheIcon < 2 then
TheIcon := LoadIcon(0,idi_Question);

The rest of the code is available at Anders Ohlsson's home page in my application launcher...

6.31. How can I a form on creation, before it is shown to the user?

The best way to do this is to make sure that the form's Visible property is set to False in design mode. Then, do whatever you want in the form's OnCreate event; your code will be executed before the form is displayed.

6.32. What should I give to Windows API functions that want a hWnd?

Each form has a property called Handle, which contains the form's hWnd. Many controls also have hWnd properties. However, don't try to pass Canvas.Handle to an API function expecting a hWnd, because TCanvas's Handle property is a hDC, not a hWnd.

6.33. How do I use the palPalEntry in TLogPallette?

Marten Larsson marten.larsson@gdpc.se says:

> Can someone explain the palpalentry? I don't understand what the
> array[0..0] does and how to use it. I would think for this record
> that you would want a way to make the array of variable length but
> I have no idea what array[0..0] does.

Yes, you can use this for indicating the number of colours your palette is
to contain. You should use should allocate memory for the palette dynamically,
this way you can decide how much memory you want to put aside for the
palette, i.e.

VAR LogPal : PLogPalette;
Palette : HPalette;
PalSize : LongInt;
BEGIN
...
PalSize:=2*SizeOf(Word)+n_Colors*SizeOf(TPaletteEntry));
{ 2 * SizeOf(Word) to get space for palVersion and palNumEntries }
{ n_Colors is (of course) the number of colors in the palette }
GetMem(LogPal,PalSize);
LogPal^.palVersion:=$0300;
LogPal^.palNumEntries:=n_Colors;
LogPal^.palPalEntry[0]:= {Some colour};
LogPal^.palPalEntry[1]:= {Some other colour};

etc.
...
FreeMem(LogPal,PalSize);
...

END;

This has to be compiled with $R- (no range checking), otherwise you will
get an error when you try using palPalEntry with an index higher than
0.

6.34. What is required to make a label with an accelerator key set focus to a different control?

Johan de Lange sierra@xs4all.nl says:

Place A label on your Form and make a Accelerator with the & in the caption. Set the FocusControl property of the label to the edit control. That's all there is to it.

6.35. How can I calculate the height and width of text to be displayed in a particular font?

Roger Browne rogerb@eiffel.demon.co.uk says:

This works for me in Delphi:

canvas.font := my_font; {or assign separately to the fields of 'canvas.font'}
width := canvas.textwidth(my_text);
height := canvas.textheight(my_text);

You need a canvas to use 'textwidth' and 'textheight', but it can be
any old canvas (e.g. one that belongs to a handy bitmap).


Section 7 - Questions about distributing Delphi apps

7.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.

7.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 of its 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.

7.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.

7.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.