                        - January '96 Issue -

Delphi-Talk: delphi-talk@bridge.net the very best of delphi-talk.
Summary January 1996
Final Update.

These questions and answers are taken from the delphi-talk of
delphi-talk@bridge.net and was built up from:
Marko Tietz
tietz@mailserv.rz.fh-merseburg.de

You can read it or download it from:
http://www.fh-merseburg.de/~tietz/delphi.html, Delphi Superpages and others.

I can't guarantee that all answers are correctly! Please use all information
at your own risk!

For subscribing to Delphi-Talk:
Send a mail to Majordomo@bridge.net and write into body (subject line will
not be processed!) subscribe delphi-talk or have a look at http://www.qns.com
/html/~delphi.

I dedicate this file to Claudia Junge also known as wurli ;-)



                      -  DELPHI KNOWLEDGE BASE -

You can also download all dtXXXX.txt files as a Paradox database. It is called
Delphi Knowledge Base. Look at http://www.fh-merseburg.de/~tietz/delphi.html
dkb*.zip. * stands for the actual version.

Delphi Knowledge Base archive contains:
- all questions and answers from dtXXX.txt files in a Paradox database,
- a database reader, which allows you to read, search, copy questions and
  answers
- a Paradox for Windows form to handle database within Paradox for Windows 5.0
  or Paradox for Windows 5.0 Runtime.

Delphi Knowledge Base current version:
- Database with all questions and answers from September 1995 to November 1995
- Database reader version 1.6
- Paradox form version 1.0

Delphi Knowledge Base is free for all private programmers! I hope you enjoy it!

Delphi Knowledge Base 2.0 - The future watch:
- DKB will appear as 32-bit application for Windows 95 and Windows NT.
- DKB should be more than a database reader. Edit your own categories, answers
  and questions to paradox table within dkb.
- Uses BDE 32 bit.
- Will be out in May / June 1996.


                     - DELPHI KNOWLEDGEBASE WinHELP -

There is a nice WinHelp-File from Eric Miles (milese@usafe14.ramstein.af.mil)
on Delphi Superpages. It contains all questions and answers from dt0995.txt to
dt1295.txt. Good work, Eric!


                          - DELPHI 2.0 Update -

        BORLAND ANNOUNCES THREE NEW VERSIONS OF DELPHI 2.0
               FOR MICROSOFT WINDOWS 95 AND NT
    Delphi#s Unique Object-Oriented Architecture Now Enhanced By
            The World#s Fastest Optimizing 32-Bit Compiler

        SCOTTS VALLEY, Calif. -- January 15, 1996 -- Borland
International Inc. today announced the new Delphi 2.0 product line,
the company#s second release of the award-winning application
development software.  Scheduled to ship this quarter, the Delphi 2.0
product line includes three versions that are each designed for specific
types of developers: Delphi Client/Server Suite 2.0 for client/server
developers; Delphi Developer 2.0 for professional LAN-based
developers; and Delphi Desktop 2.0 for individual programmers. All
Delphi 2.0 versions combine a high-performance 32-bit native-code
compiler, scalable database programming tools, and a library of drag-
and-drop visual components in a robust object-oriented development
environment.
        First introduced in February 1995, Delphi 1.0 was the first
Windows development tool to combine a high performance optimizing
compiler together with a visual two-way development environment
and a scalable database architecture.  Today, hundreds of corporations
worldwide are recognizing greater returns on their IT investments and
reporting significant competitive advantages by using Delphi to build
powerful applications in shorter amounts of time.

        The new Delphi 2.0 versions fully support all of the new
operating system features of Windows 95 and Windows NT.  A new
32-bit optimized native code compiler provides a 300 to 400 percent
increase in performance, and developers can reuse existing code with a
native code compiler that is now 15 to 50 times faster than P-code
interpreters.  New object-oriented capabilities for supporting
sophisticated client/server development include a centralized Object
Repository and new Visual Form Inheritance.
        "In just one year, Delphi has rapidly gained customer
acceptance because of its unique ability to combine high performance
native code compiler technology with a visual development
environment," said Richard Gorman, vice president of Product
Marketing and Product Management for Borland.  "With the new
versions, we are extending Delphi#s market reach to provide the wide
range of desktop, LAN-based, and client/server developers with new
state-of-the-art compiler and object-oriented programming technology
for Windows 95 and NT application development."
        "Delphi users are the fastest growing developer group in the
market today," said Mark Allen Hanner, program director of
application development strategies at META Group.  "Borland has
made a significant contribution to the industry by raising standards of
performance for rapid application development tools; as a result, many
developers are migrating to the Borland camp."

Three Versions of Delphi 2.0
        All  Delphi 2.0 products adhere to an open strategy which fully
supports OLE automation controllers and servers, Microsoft OLE
Controls (OCXs), open database connectivity (ODBC), in addition to
Microsoft#s Remote Automation technology and forthcoming
Network OLE.  All versions allow the developer to take advantage of
all the enhancements of Windows 95 and NT, including multi-
threading, Unicode and MAPI.  To assist developers migrating from
16-bit to 32-bit, each version of Delphi 2.0 will include the 16-bit
version of Delphi 1.0 for Windows.

Delphi Client/Server Suite 2.0
        Delphi Client/Server Suite 2.0 was developed for organizations
building high-performance, scalable applications that access data
stored in Oracle, Sybase, Informix, InterBase, and Microsoft SQL
Server databases.  The Delphi Client/Server Suite is the only product
of its kind to include both high performance client tools and a wide
range of server management tools.  For customers building on-line
transaction processing systems, executive information systems, or
decision support systems, Delphi 2.0 shortens every stage of the
application development life cycle and makes developers and
client/server solutions more successful.
        Some of the new features in Delphi Client/Server Suite 2.0
include:
*  A Suite of New Client/Server Tools -- A central Object
Repository for storing reusable applications, forms and database
information, and tools for testing and fine-tuning client/server
application performance, are built-in to the Delphi Client/Server Suite.
With Delphi#s new SQL Monitor, client/server applications can easily
be optimized for peak performance.  The new SQL Explorer acts as
the information center for all database development including browsing
server specific meta data such as stored procedures, triggers and event
alerters; and Delphi#s Datapump Expert provides rapid upsizing and
application scaling.  New 32-bit SQL Link native drivers come with an
unlimited deployment license, offering substantial savings for
connecting users to corporate data.
*  Team Development Tools -- Delphi 2.0 takes a object-oriented
approach to client/server development through data modules, an object
repository, and a scalable data dictionary.  To enable team members to
easily share and integrate their work, Delphi Client/Server Suite
includes a tightly integrated industry standard Intersolv PVCS version
control system for file management, check-in, check-out, and
branching.  The Open Tools API provides integration with third-party
tools such as CASE, Object Oriented Analysis and Design, and
Transaction Process Monitors.

*  Integration with InterBase and ReportSmith -- Delphi
Client/Server Suite 2.0 is the only application development package to
include high performance client and scalable server technology in one
box.  An InterBase NT two developer license is provided with each
copy of the Delphi Client/Server Suite 2.0.  InterBase, Borland#s high
performance, cross platform SQL relational database management
system, enables developers to build and test true client/server
applications on just one machine.  Borland#s ReportSmith 3.0 is tightly
integrated with Delphi data sources to provide comprehensive, high
volume reporting capabilities and live data access.  ReportSmith also
supports PC and SQL applications for easy access to Delphi data sets.
        "With Delphi Client/Server Suite 2.0 we expect to dramatically
reduce the time it takes to deliver commercial-quality applications,"
said Chris Moreau, client/server development manager at Sara Lee
Knit Products, Inc.  "Delphi has the programming power of C++,
combined with superior performance and unparalleled ease-of-
learning.  It is the fastest and most versatile development tool on the
market today.  It#s object-oriented architecture allows us to reuse code
and integrate our standards in the most efficient way possible."

Delphi Developer 2.0
        Delphi Developer 2.0 is an advanced professional product that
provides features most sought by network LAN-based developers for
fast application development.  Some of the new features in Delphi
Developer 2.0 include:
n Visual Development Tools -- Like the client/server version, Delphi
Developer 2.0 offers the Object Repository for creating shared and
reusable forms and data modules.  Developers can define and reuse
extended field attributes through a scalable Data Dictionary with
named attribute sets, while a new Multi-Object Grid now allows for
more flexible database applications.  The Visual Form Inheritance
centralizes changes and makes code easier to maintain.  Additionally,
Delphi 2.0 includes 100 drag and drop components in the Visual
Component Library; InstallShield Express deployment expert; sample
OCX controls; the Database Explorer for graphically managing
databases; and a new math library with advanced statistical and
financial functions.

*  Integration with InterBase and ReportSmith -- Delphi
Developer 2.0 includes a single user license for the local InterBase
server and a copy of ReportSmith 3.0.  InterBase comes with an
exceptional Windows 95 GUI interface, native 32-bit tools and
complete documentation.
        "After an exhaustive look at the development tools in the
market place, Delphi was the one object-oriented development
environment that could build a complete interactive multi-media and
business solution," said Brian Turford, Vice President of Touchpoint,
a division of ANATEC.
        "We have built the most advanced graphical interface in our
industry after using Delphi only eight months," said Louis Parks,
President of Data Systems Support.  "Our speed to market is two to
three times faster than most of our competition and has resulted in a
direct revenue increase this year.  Delphi 2.0 will clearly set new RAD
development tool standards in the coming year and give us a strong
competitive advantage in the 32-bit marketplace.  It is clear Borland
will continue to deliver everything a software developer could ask for
in a partner."

Delphi Desktop 2.0
        Delphi Desktop 2.0 corresponds most closely to Delphi 1.0 for
Windows and targets the individual programmer.  In addition to
offering a broad range of support for Windows 95 and NT
development, Delphi provides true 32-bit development, full code
compatibility, and easier code sharing with other Windows
applications.  Some of the new features in Delphi Desktop 2.0 and the
other Delphi packages include:
*  Sophisticated Windows 95 and NT Development -- With the
new Windows 95 components, users can design sophisticated
Windows 95 logo-compliant applications.  In addition to 32-bit
support for long file names, multi-threading and the Win95 API,
Delphi includes a complete suite of Windows 95 controls.  Full
support for Windows 95 OLE controls (OCXs) and OLE Automation
controllers and servers is also provided.

*  Fast 32-Bit Development -- Delphi 2.0#s new native code 32-bit
compiler is the world#s fastest optimizing native code compiler,
compiling at over 350,000 lines per minute.  Delphi applications can
now run 15 to 50 times faster compared to interpreted P-code, and
Delphi#s new optimized linker makes .EXEs up to 20 to 25 percent
smaller than before.  Developers can declare arrays, strings, records
and other data structures up to 2 gigabytes in size.
*  Full Code Compatibility -- Delphi affords developers the
flexibility of staying with Windows 3.1 or migrating to a high powered
32-bit development environment on Windows 95 or NT.  Delphi#s
code compatibility from 16-bit to 32-bit protects developers#
application investments while they move to new operating systems.
*  Easier Code Sharing -- Delphi#s native code compiler lets users
create reusable DLLs that work with Borland C++, dBASE, Paradox,
Microsoft#s Visual Basic, and PowerSoft#s PowerBuilder, and other
Windows applications.  DLLs and OLE Automation controllers and
servers can be seamlessly integrated into Windows programs, such as
Microsoft Excel, Microsoft Word, Borland C++ and Paradox, among
others.  Borland C++ developers can leverage their existing work since
Delphi 2.0 is built around the same high performance back-end
compiler technology as Borland C++.

Pricing
*  Delphi Desktop 2.0 -- The Competitive Upgrade for Delphi
Desktop 2.0 will be available for an estimated street price of $199.95,
and the New User license for $499.95.  Through a $50 rebate, existing
Delphi customers may upgrade to Delphi 2.0 for $149.95.
n  Delphi Developer 2.0 -- The Competitive Upgrade for Delphi
Developer 2.0 will be available for an estimated street price of
$299.95, and the New User license for $799.95.  Existing Delphi
customers may use the $50 rebate to upgrade to Delphi 2.0 for
$249.95.

*  Delphi Client/Server Suite 2.0 -- The New User license will be
available for an estimated street price of $1,999.95.  Existing Delphi
Client/Server customers may upgrade to Delphi Client/Server Suite 2.0
for at estimated street price of $999.95, and Delphi 1.0 customers may
upgrade for $1,699.95.  Delphi Client/Server Suite 2.0 is free to
customers in the Delphi Client/Server Team Solutions maintenance
program.  For more information, customers can call (800) 233-2444,
extension 1350.  All estimated prices are in U.S. dollars and apply only
in the United States and Canada.  Dealer prices may vary.

Borland: Making Development Easier
        Borland International Inc. (NASDAQ:BORL) is a leading
provider of products and services targeted to software developers.
Borland is distinguished for its high-quality software development
tools, which include Delphi, Delphi Client/Server, Borland C++,
Visual dBASE, Paradox and InterBase.  Borland#s award-winning
products are supported through comprehensive programs for small-
and large-sized software developers, corporate developers, value
added resellers and systems integrators. Founded in 1983, Borland is
headquartered in Scotts Valley, California.

NOTE TO EDITORS:  Copies of previous Borland press releases and
additional corporate and product information are available on
Borland#s  Internet World Wide Web (WWW) site, at
http://www.borland.com.



Mail me:
- if you find this file useful
- if you want make some suggestions




=============================================================================

 Contents

 1. Setting the active window
 2. Quickie DB searcher
 3. DBGRID saving the user configuration
 4. Updating Cursor immediately
 5. EncodeDate
 6. How to retrieve the path from an Alias or TDatabase
 7. Value of TDBLookupCombo
 8. System Ram / CMOS
 9. Listbox with graphic
10. Masked Find in TStringList
11. Disk Serial Numbers
12. Creating a form with a width < 102
13. Dual list box
14. Coping of the files

=============================================================================

1. Setting the active window
Q:
I am using a TTimer object to wait for an event and when that event occurs, I
want to display a dialog box to the user (probably something more elaborate
than MessageBox). But if my app is minimized or not the active window (for
example, if MS Word is the active app), my dialog box (or message box) does
not display.  I know my TTimer event procedure is working because I hear the
MessageBeep(0) that I put in there before I show my dialog box.

A:
I have tried this using a form of my own design, and it pops up in
front of the running application without having to resort to any API
stuff. Here's my timer event; as you can see it's not anything
special:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  MyDialog.ShowModal;
end;

It shows me the dialog no matter the state of my application
(not focused, minimized, whatever).

[Eric Nielsen, htrsoft@midwest.net]

-----------------------------------------------------------------------------

2. Quickie DB searcher
A:
Here's a quickie DB search utility.  It does its work by finding a string
inside the field (it converts everything to an uppercase string, even floats).  
This may be the slowest way to search, but it seems to work faster 
than the other solutions I've found on the Net.  And it'll hit just 
about anything.  For ex. say you have float field that has the
number 4.509375354, and you search for 7, you'll hit it.  Also, It'll
search on more than one field at a time - handy if you have two address fields.
    I'm posting this little unit because when I first started in
Delphi, one of my biggest troubles was finding a search utility and I 
didn't know enough to write my own (fear struck deep into my bones).  
So I hope this will help those of you who need it like I did.
     It's fairly easy to understand, but if you need to know exactly 
how to use it, just e-mail me personally and I'll be glad to help.  
Look at the case statement to find out which field types are 
supported (easy to add more).  If anyone finds a bug or adds
some functionality to this code, please send it to me, I'd really
appreciate it.  Thanks.

Ryan

{<<<<begin code>>>>>}
unit Finder;

interface

uses DB, DBTables, SysUtils;

function GrabMemoFieldAsPChar(TheField : TMemoField): PChar;
function DoFindIn(TheField : TField; SFor : String): Boolean;
function FindIt(TheTable : TDataSet; TheFields : array of integer; 
  SearchBackward : Boolean; FromBeginning : Boolean; SFor : String): Boolean;
{ex. of FindIt -
         if FindIt(NotesSearchT,
         [NotesSearchT.FieldByName('Leadman').Index],
           False, True, SearchText.Text) then DoSomething; }

implementation

function GrabMemoFieldAsPChar(TheField : TMemoField): PChar;
begin
with TBlobStream.Create(TheField, bmRead) do
  begin
    GetMem(Result, Size + 1);
    FillChar(Result^, Size + 1, #0);
    Read(Result^, Size);
    Free;
  end;
end;

function DoFindIn(TheField : TField; SFor : String): Boolean;
var
  PChForMemo : PChar;
begin
Result := False;
case TheField.DataType of
  ftString :
    begin
      if (Pos(SFor, UpperCase(TheField.AsString)) > 0) then
        Result := True;
    end;
  ftInteger :
    begin
      if (Pos(SFor, TheField.AsString) > 0) then Result := True;
    end;
  ftBoolean :
    begin
      if SFor = UpperCase(TheField.AsString) then
        Result := True;
    end;
  ftFloat :
    begin
      if (Pos(SFor, TheField.AsString) > 0) then Result := True;
    end;
  ftCurrency :
    begin
      if (Pos(SFor, TheField.AsString) > 0) then Result := True;
    end;
  ftDate .. ftDateTime :
    begin
      if (Pos(SFor, TheField.AsString) > 0) then Result := True;
    end;
  ftMemo :
    begin
      SFor[Ord(SFor[0]) + 1] := #0;
      PChForMemo := GrabMemoFieldAsPChar(TMemoField(TheField));
      StrUpper(PChForMemo);
      if not (StrPos( PChForMemo, @SFor[1] ) = nil) then Result :=
      True; FreeMem(PChForMemo, StrLen(PChForMemo + 1));
    end;
  end;
end;

function FindIt(TheTable : TDataSet; TheFields : array of integer;
  SearchBackward : Boolean; FromBeginning : Boolean; SFor : String): Boolean;
var
 i, HighTheFields, LowTheFields : integer;
 BM : TBookmark;
begin
TheTable.DisableControls;
BM := TheTable.GetBookmark;
try
LowTheFields := Low(TheFields);
HighTheFields := High(TheFields);
SFor := UpperCase(SFor);
Result := False;
if FromBeginning then TheTable.First;
if SearchBackward then
  begin
    TheTable.Prior;
    while not TheTable.BOF do
      begin
        for i := LowTheFields to HighTheFields do
          begin
            if DoFindIn(TheTable.Fields[TheFields[i]], SFor) then
              begin
                Result := True;
                Break;
              end;
          end;
        if Result then Break else TheTable.Prior;
      end;
  end else
  begin
    TheTable.Next;
    while not TheTable.EOF do
      begin
        for i := LowTheFields to HighTheFields do
          begin
            if DoFindIn(TheTable.Fields[TheFields[i]], SFor) then
              begin
                Result := True;
                Break;
              end;
          end;
        if Result then Break else TheTable.Next;
      end;
  end;
finally
TheTable.EnableControls;
if not Result then
  TheTable.GotoBookmark(BM);
TheTable.FreeBookmark(BM);
end;

end;

end.

[Ryan Peterson, rpetersn@use.usit.net]

-----------------------------------------------------------------------------

3. DBGRID saving the user configuration
Q:
Is their a way to save the column order of a grid after the user
reorders the columns via drag n drop.

A:
I resolved this problem time ago for my one application. Following code is
adapted for you, not tested, but I think it works fine. It create, save and
load configuration's file for order AND SIZE too of fields. I'm at your
disposal for further into something.

procedure TMainForm.NewIni(const NomeIni: string);
var F: System.Text;
    i: Byte;
begin
  System.Assign(F, NomeIni);
  System.ReWrite(F);
  System.WriteLn(F, '[Campi_Ordine]');
  for i:=1 to Table1.FieldCount do
    System.WriteLn(F, 'Campo',i,'=',Table1.Fields[i-1].FieldName);
  System.WriteLn(F, '');
  System.WriteLn(F, '[Campi_Size]');
  for i:=1 to Table1.FieldCount do
    System.WriteLn(F, 'Campo',i,'=',Table1.Fields[i-1].DisplayWidth);
  System.Close(F);
end;

procedure TMainForm.SaveIni(const FN: String);
var Ini: TIniFile;
    i: Integer;
begin
  NewIni(FN);
  Ini := TIniFile.Create(FN);
  with Ini do
  begin
    for i:=1 to Table1.FieldCount do
    begin
      S:= Table1.Fields[i-1].FieldName;
      WriteString('Campi_Ordine', 'Campo'+IntToStr(i), 
        Table1.Fields[i-1].FieldName);
      WriteInteger('Campi_Size', 'Campo'+IntToStr(i),
        Table1.Fields[i-1].DisplayWidth);
    end;
  end;
  Ini.Free;
end;

procedure TMainForm.LoadIni(const FN: String);
var Ini: TIniFile;
    i: Integer;
    j: Longint;
    S: String;

    function MyReadInteger(const Section, Ident: string): Longint;
    begin
      result := Ini.ReadInteger(Section, Ident, -1);
      if result=-1 then
        raise Exception.Create('Errore nel file di configurazione.');
    end;

    function MyReadString(const Section, Ident: string): String;
    begin
      result := Ini.ReadString(Section, Ident, '');
      if result='' then
        raise Exception.Create('Errore nel file di configurazione.');
    end;

begin
  Ini := TIniFile.Create(FN);
  try
    with Ini do
    begin
      for i:=1 to Table1.FieldCount do
      begin
        S:= MyReadString('Campi_Ordine', 'Campo'+IntToStr(i));
        j:= MyReadInteger('Campi_Size', 'Campo'+IntToStr(i));
        Table1.FieldByName(S).Index := i-1;
        Table1.FieldByName(S).DisplayWidth := j;
      end;
    end;
  finally
    Ini.Free;
  end;
end;

[Cosimo Laddomada, mimmoladd@mail.clio.it]

-----------------------------------------------------------------------------

4. Updating Cursor immediately
Q:
For example, if I change my cursor to a waiting clock cursor before
some time-consuming operations is executed, why isn't my waiting clock
cursor activated immediately? It's only activated after the event!

A:
Begin
   Try
      Screen.Cursor:=crHourGlass;
      ReportForm := TReportForm.Create(Application);
      Screen.Cursor:=crDefault;
      ReportForm.ShowModal;
      ReportForm.Free;
    Finally
      Screen.Cursor:=crDefault;
    end;
end;

[Phil Ferro, Phil.Ferro@ademco.com]

-----------------------------------------------------------------------------

5. EncodeDate
Q:
Could anyone give me the syntax for converting text to and
from a Paradox Date field value? EncodeDate(xx,xx,xx)?

A:
TheDateField.AsString := TheDateString;
TheDateString := TheDateField.AsString;

this will do a convert just like DateToStr and StrToDate.  Similar to

TheDateField.AsDateTime := StrToDate(TheDateString);
TheDateString := DateToStr(TheDateField.AsDateTime);

[Ryan Peterson, rpetersn@use.usit.net]

-----------------------------------------------------------------------------

6. How to retrieve the path from an Alias or TDatabase
Q:
I need help in determining the path of the database programmatically
so that I can put an .INI file there with it.

A:
Here's a quick demo to demonstrate how to get info about aliases in Delphi.
First, create a new project with a listbox and 3 labels (called ListBox1, 
Label1, Label2, and Label3).  Then add an OnCreate event handler for the form 
with this code in it:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Session.GetAliasNames(ListBox1.Items);
end;

Now add an OnClick event for the list box:

procedure TForm1.ListBox1Click(Sender: TObject);
var
  tStr: array[0..100] of char;
  Desc: DBDesc;
begin
  if ListBox1.Items.Count = 0 then
    exit;
  StrPLCopy(tStr, ListBox1.Items.Strings[ListBox1.ItemIndex], High(tStr));
  DbiGetDatabaseDesc(tStr, @Desc);
  with Desc do
  begin
    Label1.Caption := StrPas(Desc.szName);
    Label2.Caption := StrPas(Desc.szPhyName);
    Label3.Caption := StrPas(Desc.szDbType);
  end;
end;

Now add the following to the 'uses' clause at the top of the unit:

DB, DBTables, DBITypes, DBIProcs;

You'll see that this gets the path from all of your STANDARD aliases (Paradox 
and dBase).

[Dan Butler, Dan_Butler@msn.com]

-----------------------------------------------------------------------------

7.
Q:
I am trying to use the TDBLookupCombo on a dialog box that will display the
value of a database field. I then take that value returned from the
TDBLookUpcombo value and store it in a StringList of a ListBox.

A:
I think I have what you want, um, heres some source code I wrote
awhile to accomplish much the same thing.  When you reference the
LookUpValue property you get the field that was .... looked up.

I hope this is what you're after,.....  I havn't seen anyone else post
anything here for this so I guess no else thought of this..

unit clookup;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, DB, DBLookup;

type
  TDBJustLookupCombo = class(TDBLookupCombo)
  private
    { Private declarations }
  protected
    { Protected declarations }
    function GetLValue: TField;
  public
    { Public declarations }
    property LookUpValue: TField read GetLValue;
  published
    { Published declarations }
  end;

  TDBJustLookupList = class(TDBLookupList)
  private
    { Private declarations }
  protected
    { Protected declarations }
    function GetLValue: TField;
  public
    { Public declarations }
    property LookUpValue: TField read GetLValue;
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Data Controls', [TDBJustLookupList,
TDBJustLookupCombo]);
end;

function TDBJustLookupCombo.GetLValue: TField;
begin
  Result := LookupSource.DataSet.FieldByName(LookUpField);
end;

function TDBJustLookupList.GetLValue: TField;
begin
  Result := LookupSource.DataSet.FieldByName(LookUpField);
end;

end.

[Mark Derricutt, naked@voyager.co.nz]

-----------------------------------------------------------------------------

8. System Ram / CMOS
Q:
Does anyone have any source code for extracting from the BIOS or any
other way the amount of RAM fitted to a system.

A:
You can try this... It will return the amount of extended mem from
the CMOS (Total K's minus the first Mb).

  Function MyGetExt: Integer; Assembler;
  asm
    Mov  AX,$3031;
    Out  $70,AL;
    NOP;
    IN   AL,$71;
    XCHG AH,AL;
    Out  $70,AL;
    NOP;
    IN   AL,$71;
  end;

[Leif Hellstroem, Leif @ aivo.se]

A:
Attention CMOS-busters:

Here's what's happening for those not so sharp on their assembly language
directives.

To read from CMOS do the following:

        write to port $70 with the address value to read or write.
        write to port $71 with the new value or read the value of interest
from port $71.

CMOS is reasnably generic in some locations.  Most noteable are the
locations $0-$F, (the time,date and timer settings) and the locations from
$10-$1F, (general system settings).  The locations above $20 are usually
more subject to the whims of mfg's than the others which are reasonably
standard.

My example will be in C as ASM was just represented!  I'll get to Delphi in
a minute.

write to port $70 (hex) with the address value of the CMOS memory location
that you are interested

outp(0x70,0x31);     { tells CMOS we want to 'talk' to CMOS location 31hex }

next, read the desired value at port $71 or write a new value to the port.

outp(0x71, 0x10);      { this writes the value 10 hex (16
dec) to CMOS location 31as previously defined }

                        OR

x = inp(0x71);             { this reads the hex value from
CMOS location 31 as previously declared }

it is also good form to include a delay between the write to
port 70 and the read or write at port 71.  This is more important in
assembly routines and maybe real fast cpu's then in higher level languages.
That's the purpose of the NOP in Leif's code example and also generally
recommended.

You will note that in Leif's ASM code two locations are stuffed into the
AX, 30 and 31.  This is to allow for a quick load to search two addresses.
This code contains two instances, both CMOS reads.  The memory values are
stored in two consecutive locations but I believe it's a case of most
significant byte last.  And they also only concern the amount of memory
beyond 1 Mb as also stated below.

OK, ok, I know this is supposed to be Delphi but I'm a C programmer
reasonably new to Delphi and Pascal so to do this in Delphi probably
involves using Port or PortW but I haven't tried it yet so don't know exact
syntax.  Probably pretty similar to C style though.  Would be interested in
hearing from anyone that has done it that way.  Couldn't really find an
example yet and haven't had time for exploring.

Of a rather important note, it should be pointed out that this method will
only read so much memory.  Back in the old days, no one considered the vast
amounts of RAM available today system-wise and I believe that certain large
sizes of RAM will not be correctly loaded into CMOS.  Therefore this is not
a cure-all concept.  Some of this is caused by BIOS
shortcomings/short-sightings.  Also, you will need a CMOS map to show what
locations are loaded for which system parameters.  Some differences can
exist between different mfg's.  This can be a rather messy job...

Here's the most important thing for budding CMOS editors to remember:

       IF you edit a location between $10 and $2F then you WILL NEED to
calculate the NEW checksum by adding together all the location values from
$10-$2F and THEN WRITE the new value to $3E, $3F or YOU WILL GET A CMOS
CHECKSUM ERROR WHEN YOU REBOOT!  GUARANTEED!!!  THIS should concern you... 

        Also, don't try to test the values $0 - $1F.  Time marches on, don't
you know...

[Monte Saager, kidvolt@teleport.com]

-----------------------------------------------------------------------------

9. Listbox with graphic
Q:
Has anyone done something like putting a .BMP graphic besides text within a
listbox?  something you see when you click on "Options"-"Environment"->
"Palette".

A:
This is a sample code. You need to set the ListBox property
Style to lbOwnerDrawFixed. Then you draw the bitmap on the event
DrawItem (see OwnerDraw at the Delphi Help File).

unit Listemas;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TLTemas = class(TForm)
    ListBox1: TListBox;
    procedure FormActivate(Sender: TObject);
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  LTemas: TLTemas;

implementation

{$R *.DFM}

procedure TLTemas.FormActivate(Sender: TObject);
var
   Dibujo: TIcon;
begin
     with ListBox1.Items do
     begin
          Dibujo := TIcon.create;
          Dibujo.LoadFromFile('.\ICO\justic.ico');
          AddObject('Poder Legislativo y Partidos Politicos',Dibujo);
          Dibujo := TIcon.create;
          Dibujo.LoadFromFile('.\ICO\justic.ico');
          AddObject('Poder Ejecutivo Nacional',Dibujo);
     end;
end;

procedure TLTemas.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  Icon: TIcon;
  Offset: Integer;	{ text offset width }
begin
  with (Control as TListBox).Canvas do	{ draw on the control canvas, not on the form }
  begin
    FillRect(Rect);	{ clear the rectangle }
    Offset := 2;	{ provide default offset }
    Icon := TIcon((Control as TListBox).Items.Objects[Index]);	{ get the Icon for this item }
    if Icon <> nil then
    begin
         Draw(Rect.Left+1,Rect.Top+2,TIcon((Control as ListBox).Items.Objects[Index]));

      Offset := Icon.width + 9;	{ add four pixels between Icon and text }
    end;
    TextOut(Rect.Left + Offset, Rect.Top+7, (Control as TListBox).Items[Index])	{ display the text }
  end;
end;

end.

[Javier Esteban Acuna, jacuna@datamar.com.ar]

A:
Check out the OnDrawItem event for the listbox (or combobox etc).
There you will see that drawing graphics is as easy as writing text.
(Once you are comfortable with that check out OnMeasureItem event)

procedure ListDrawItem(Control: TWinControl; Index:
Integer;
  Rect: TRect; State: TOwnerDrawState);
var
 BitMap : TBitMap;
begin
{Initialize Bitmap here.... i.e. load a graphic onto it}

     With (Control as TListBox).Canvas do
       begin
         FillRect(Rect);
         Draw(Rect.Left, Rect.Top, BitMap);
         TextOut(Rect.Left + 2 + BitMap.Width, Rect.Top,
         DstList.items.strings[index]);  {DstList is the name of the 
list}
       end;

end;

[Sajan Thomas, thomas@warp.msoe.edu]

-----------------------------------------------------------------------------

10. Masked Find in TStringList
Q:
I am trying to do a masked find or search in a TStringList Object. Something
like MyList.Find('LeftPelvic*') to find all strings that start with LeftPelvic
and have it return a TStringList or find the first and have a findnext method.

A:
   list : tStringList;   { the tStringList to search }
   target: string;       { the string to search for, eg. 'LeftPelvic' }

   { set start to where you want to start from, eg. 0 to start at the top
     or some integer to start within the list, eg. the last value of i + 1 }
   { following is case insensitive, to make it case sensitive remove the calls
     to ansiUpperCase }

   target := ansiUpperCase (target);
   for i := start to list.count-1 do
      if ansiUpperCase(copy(list.item[i], 1, length(target))) = target then
         found it!

If you want to do a looser search, eg. find 'LeftPelvic' anywhere in the
list item rather than just at the beginning, change the if statement to:

   if pos (target, ansiUpperCase(list.item[i])) > 0 then found it;

[Sid Gudes, cougar@roadrunner.com]

-----------------------------------------------------------------------------

11. Disk Serial Numbers
Q:
It is a C++ Class for reading/writing disk volume labels and serial numbers.
Any C++ gurus out there that can convert to DELPHI?

A:
This is not a conversion, but here's a Delphi unit with a function
that reads them. To write them,  you can change the AX value to $6901
and fill the buffer with your values before calling the interrupt.  
DOS 4.00+ required.



unit Sernumu;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TMediaID = Record
    InfoLevel : Word;
    SerialNumber : LongInt;
    VolumeLabel : Array[0..10] of Char;
    SysName : Array[0..7] of Char;
    End;
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    MediaID : TMediaID;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  DPMIRegisters =
    record
      DI : LongInt;
      SI : LongInt;
      BP : LongInt;
      Reserved : LongInt;
      BX : LongInt;
      DX : LongInt;
      CX : LongInt;
      AX : LongInt;
      Flags : Word;
      ES : Word;
      DS : Word;
      FS : Word;
      GS : Word;
      IP : Word;
      CS : Word;
      SP : Word;
      SS : Word;
    end;


  function RealIntr(IntNo : Byte; var Regs : DPMIRegisters) : Word; Assembler;
  asm
    xor     bx,bx
    mov     bl,IntNo
    xor     cx,cx        {StackWords = 0}
    les     di,Regs
    mov     ax,0300h
    int     31h
    jc      @@ExitPoint
    xor     ax,ax
  @@ExitPoint:
  end;


function GetDiskInfo(Drive : Word; var MediaID : TMediaID) : Boolean;
type
  tLong = Record
    LoWord, HiWord : Word;
    End;
var
  Regs : DPMIRegisters;
  dwAddress : LongInt;
  Address : tLong absolute dwAddress;
begin
  Result := False;
  FillChar(MediaID, SizeOf(MediaID), 0);
  dwAddress := GlobalDosAlloc(SizeOf(MediaID)); { two paragraphs of DOS memory }
  if dwAddress = 0
    then            { address is zero if error occurred }
      exit;

  With Regs do
    begin
      bx := Drive;
      cx := $66;
      ds := Address.HiWord;
      ax := $6900;
      dx := 0;
      es := 0;
      flags := 0;
    end;
  If RealIntr($21, Regs) <> 0
    Then
      Exit;
  Move(ptr(Address.LoWord, 0)^, MediaID, SizeOf(MediaID));
  GlobalDosFree(Address.LoWord)     { free DOS memory block }
  Result := True;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  GetDiskInfo(1, MediaID);
  With MediaID do
    Begin
      Label1.Caption := IntToHex(SerialNumber, 8);
      Label2.Caption := VolumeLabel;
      Label3.Caption := SysName;
    End;
end;

end.

[Eric Nielsen, htrsoft@midwest.net]

-----------------------------------------------------------------------------

12. Creating a form with a width < 102
Q:
Does anybody know how to stop Delphi from resetting a form's width to 102
pixels whenever you set the width to anything less than that?

A:
Add this definition to intarface section of your form,
  procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
            message WM_GETMINMAXINFO;

and add this to implementaion section.
  procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
  begin
    with message do begin
      MinMaxInfo^.ptMinTrackSize.x := 20;
    end;
  end;

[Ataru NAKATA, anakata@vector.co.jp]

A:
I havn't figured anyway to do it from the IDE but you can do at
run-time with

procedure TForm1.Form1OnCreate(Sender: TObject);
begin
  Width := 50;
end;

[Mark Derricutt, naked@voyager.co.nz]

-----------------------------------------------------------------------------

13. Dual list box
Q:
Could anyone give me some hints on how to create a dual list box (add
and remove items betweem 2 listboxes) with the items of the src list come
from a table.
I have tried the dual list box template, but it is a listbox with
pre-entered items. I want to hv the items from a table instead. Which one
(ListBox, DBListBox or ...) should I use?

A:
I placed two listboxes on the screen and used the following code to fill one
of them
with data from a table.

tableName.Refresh;  {this may or may not be necessary in your case}
tableName.First;    {Make sure you are looking at the first record}
while not tableName.Eof do {loop through table}
begin
  listbox1.items.add(tableName.FieldByName('USRID').AsString); {add the item
to the listbox1}
  tableName.Next; {go to the next record}
end;

this is an actual procedure from some code that I am using to accomplish the
same thing.
I pass it a tablename and listbox1 name and listbox2 name.  I use several
tables that
have the same type of fields that is why I use this routine:

procedure TTemplateFrm.buildList(tableName: TTable; SelBox, AvailBox: TListBox);
begin
  {we are going to add data to listboxes in this procedure}
  {pick up any new data}
  tableName.Refresh;
  {make sure we are looking at the first record}
  tableName.First;
  {Now clear the list boxes}
  SelBox.Clear;
  AvailBox.Clear;
  {Now add the Stations}
  while not tableName.EOF do
  begin
    AvailBox.Items.Add(tableName.fieldByName('USRID').AsString +
       ' ' + tableName.fieldByName('DESCRIPTION').AsString);
    tableName.Next;
  end;
end;


How do you want to move data between the two boxes? If you want to drag and
drop then
use begindrag in your mousedown event of the source table like this:

  if Button = mbLeft then
    Tlistbox(sender).BeginDrag(false);

Then in your other listbox, the one receiving the data you type in the
follow code in DragOver event:

  if Source = ListBox1 then
    Accept := true
  else
    Accept := false;

Do not use "Accept := (Source is TListbox)" as most examples show, because
you have two list boxes
you need to refer to the name of the object and not the type or you will
confuse your program.

Finally in your dragDrop you can use the following code to add the data to
listbox2 and remove it from list
box1.

  Listbox2.Items.Add(Listbox1.Items[Listbox1.ItemIndex]);
  Listbox1.Items.Delete(Listbox1.ItemIndex);

Finally add a save button if you want to loop through the listbox2 and save
it to a database.

I hope this is what you were looking for and that you find this useful. If
you want to be able to move
data from listbox2 to listbox1 as well then use the same code but REVERSE
which boxes you place them in 
and make sure you reference the correct boxes in the code.

[Ken Smith, kensmith@airmail.net]

-----------------------------------------------------------------------------

14. Coping of the files
Q:
I have diffculties with coping the files. Delphi don't want to compile
LZCopy command.

this way it work very slow

pbBuf := PChar( LocalAlloc(LMEM_FIXED, 1) );

FileSeek(source,0,0);
FileSeek(dest,0,0);
repeat
    cbRead := Fileread(source, pbBuf, 1);
    FileWrite(dest, pbBuf, cbRead);
until (cbRead = 0);

A:
{  You must add LZExpand to your uses clause  ea. USES LZExpand; }
function CopyFile(SrcF,DestF : string) : boolean;
var
  SFile,
  DFile : integer;
  Res   : longint;
  Msg   : string;

begin
  SFile := FileOpen(SrcF,0);        { Open ReadOnly = 0, Write=1, Readwrite=2}
  DFile := FileCreate(DestF);
  Res := LZCopy(SFile,DFile);
  FileClose(SFile);
  FileClose(DFile);
  if Res < 0 then
  begin
    Msg := 'Unknown error';
    case Res of
      LZERROR_BADINHANDLE   : Msg := 'Invalid Source file handle';
      LZERROR_BADOUTHANDLE  : Msg := 'Invalid Destination file handle';
      LZERROR_BADVALUE      : Msg := 'Input parameter is out of range';
      LZERROR_GLOBALLOC     : Msg := 'Insufficient memory for the required buffers';
      LZERROR_GLOBLOCK      : Msg := 'Internal data structure handle invalid';
      LZERROR_READ          : Msg := 'Source file format is not valid';
      LZERROR_UNKNOWNALG    : Msg := 'The Source file was compressed with an unrecognized compression algorithm';
      LZERROR_WRITE         : Msg := 'There is insufficient space for the output file';
    end;
    MessageDlg(Msg,mtERROR,[mbOK],0);
    result := FALSE
  end else
    result := TRUE;
end;

[Niel Calitz, omremcon@iafrica.com]

A:
I'll bet it's slow! It's reading the file one character at a time... Try
allocating 8192 bytes and reading 8192 bytes at a time. That should speed
it up a bit...

[Sid Gudes, cougar@roadrunner.com]

A:
The simplest way to copy files is this:

                VAR
                         sI,dI:Longint;
                        sD,sS:TFilename;

                USES LZExpand;
                        ............
                  sI := FileOpen(sS,fmShareDenyWrite);
                 dI := FileCreate(sD);
                  { Copy file }
                   CopyLZFile(sI,dI);
                  {close files}
                 FileClose(sI);
                 FileClose(dI);
                        ............

[Tadas Vizbaras, tavizb@rc.lrs.lt]

-----------------------------------------------------------------------------
