The Delphi FAQ
                Maintainer: Graham Mainwaring <[email protected]>
                          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 <mumble> back-end?
    4.3 What data-aware controls come with Delphi?
    4.4 Can I use the ODBC drivers that I got with <mumble>?
    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 <mumble> 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
  <http://www.mhn.org/delphi.faq>.

  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 <[email protected]> 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, <http://www.borland.com>, 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:
  <http://www.cybernetics.net/users/bstowers/delphi-bugs.html>.

  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 <http://vislab-www.nps.navy.mil/~jnhodges/> or
  <http://www.cybernetics.net/users/bstowers>.

  ------------------------------
  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 <[email protected]> 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 <[email protected]> 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 <[email protected]>, "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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/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/[email protected]/Works fine, except that it
       isn't data-aware once you load it into Delphi.
  VBTools Card Deck/MicroHelp/[email protected]/Works fine
  VBTools Dice/MicroHelp/[email protected]/Works fine
  Data Widgets/Sheridan Software/[email protected]/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 [email protected] 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 <mumble> 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 <[email protected]> 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 <mumble>?

  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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <blah>;". 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
<[email protected]>
  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 <[email protected]> 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 <[email protected]> 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.

  5.20 I'm trying to call <mumble> 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 <[email protected]> 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 <[email protected]> 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.