TI1617D.txt Getting Version Information From Your Program
Category :Application Interop
Platform :All
Product :Delphi All
Description:
This sample project demonstrates how to get at the version info in executables.
1. Launch Delphi 3.
2. In a new project, drop a TMemo and a TButton on the form (make sure they're called Memo1 and Button1). Double click on Button1.
Now you can go ahead and directly replace the code for the Button1Click procedure (see below).
--------------------------
The Button1Click procedure
--------------------------
procedure TForm1.Button1Click(Sender: TObject);
const
InfoNum = 10;
InfoStr : array [1..InfoNum] of String =
('CompanyName', 'FileDescription', 'FileVersion', 'InternalName',
'LegalCopyright', 'LegalTradeMarks', 'OriginalFilename',
'ProductName', 'ProductVersion', 'Comments');
var
S : String;
n, Len, i : Integer;
Buf : PChar;
Value : PChar;
begin
S := Application.ExeName;
n := GetFileVersionInfoSize(PChar(S),n);
if n > 0 then begin
Buf := AllocMem(n);
Memo1.Lines.Add('FileVersionInfoSize='+IntToStr(n));
GetFileVersionInfo(PChar(S),0,n,Buf);
for i:=1 to InfoNum do
if VerQueryValue(Buf,PChar('StringFileInfo\040904E4\'+
InfoStr[i]),Pointer(Value),Len) then
Memo1.Lines.Add(InfoStr[i]+'='+Value);
FreeMem(Buf,n);
end else
Memo1.Lines.Add('No FileVersionInfo found');
end;
TI986D.txt How to determine the current record number.
Category :Database Programming
Platform :All
Product :Delphi All
Description:
Q: "How can I determine the current record number for a dataset?"
A: If the dataset is based upon a Paradox or dBASE table then the record number can be determined with a couple of calls to
the BDE (as shown below). The BDE doesn't support record numbering for datasets based upon SQL tables, so if your server
supports record numbering you will need to refer to its documentation.
The following function is given as part of a whole unit and takes as its parameter any component derived from TDataset
(i.e. TTable, TQuery, TStoredProc) and returns the current record number (greater than zero) if it is a Paradox or dBASE
table. Otherwise, the function returns zero.
NOTE: for dBASE tables the record number returned is always the physical record number. So, if your dataset is a TQuery or
you have a range set on your dataset then the number returned won't necessarily be relative to the dataset being viewed,
rather it will be based on the record's physical position in the underlying dBASE table.
uses
DB, DBTables, DbiProcs, DbiTypes, DbiErrs;
function GetRecordNumber(Dataset: TDataset): Longint;
var
CursorProps: CurProps;
RecordProps: RECProps;
begin
{ Return 0 if dataset is not Paradox or dBASE }
Result := 0;
with Dataset do
begin
{ Is the dataset active? }
if State = dsInactive then raise EDatabaseError.Create('Cannot perform this operation '+ 'on a closed dataset');
{ We need to make this call to grab the cursor's iSeqNums }
Check(DbiGetCursorProps(Handle, CursorProps));
{ Synchronize the BDE cursor with the Dataset's cursor } UpdateCursorPos;
{ Fill RecordProps with the current record's properties }
Check(DbiGetRecord(Handle, dbiNOLOCK, nil,
RecordProps));
{ What kind of dataset are we looking at? }
case CursorProps.iSeqNums of
0: Result := RecordProps.iPhyRecNum; { dBASE }
1: Result := RecordProps.iSeqNum; { Paradox }
end;
end;
end;
end.
TI576D.txt A VERY short primer on dynamic memory allocation.
Category :General Programming
Platform :All
Product :Delphi 1.0
Description:
Q: How do I reduce the amount of memory taken from the data segment? (or How do I allocate memory dynamically?)
A:
Let's say your data structure looks like this:
type
TMyStructure = record
Name: String[40];
Data: array[0..4095] of Integer;
end;
That's too large to be allocated globally, so instead of declaring a global variable,
var
MyData: TMyStructure;
you declare a pointer type,
type
PMyStructure = ^TMyStructure;
and a variable of that type,
var
MyDataPtr: PMyStructure;
Such a pointer consumes only four bytes of the data segment.
Before you can use the data structure, you have to allocate it
on the heap:
New(MyDataPtr);
and now you can access it just like you would global data. The only difference is that you have to use the caret operator to
dereference the pointer:
MyDataPtr^.Name := 'Lloyd Linklater';
MyDataPtr^.Data[0] := 12345;
Finally, after you're done using the memory, you deallocate it:
Dispose(MyDataPtr);
Technical Information Database
TI506D.txt Unknown runtime errors. What's error 163?
Category :General Programming
Platform :All
Product :Pascal All
Description:
Pascal sometimes returns runtime errors that aren't listed in the manuals. If you ever get an IORESULT code in the range
150-199, just subtract 131 from it and the look in your DOS reference manual (or in the list presented below) for the
relevant critical errors. One error that users see quite often is number 163, which is
a sharing violation. It occurs when two users try to access the same file at the same time.
Here's a list of critical errors. The first column has the error number in decimal format, the second has the number in hex,
and the third provides an explanation of the error:
DEC HEX EXPLANATION
===============================================
01 -- 01 Invalid function number
02 -- 02 File not found
03 -- 03 Path not found
04 -- 04 Too many open files (no handles left)
05 -- 05 Access denied
06 -- 06 Invalid handle
07 -- 07 Memory control blocks destroyed
08 -- 08 Insufficient memory
09 -- 09 Invalid memory block address
10 -- 0A Invalid environment
11 -- 0B Invalid format
12 -- 0C Invalid access mode (open mode is invalid)
13 -- 0D Invalid data
14 -- 0E Reserved
15 -- 0F Invalid drive specified
16 -- 10 Attempt to remove current directory
17 -- 11 Not same device
18 -- 12 No more files
19 -- 13 Attempt to write on a write-protected diskette
20 -- 14 Unknown unit
21 -- 15 Drive not ready
22 -- 16 Unknown command
23 -- 17 CRC error
24 -- 18 Bad request structure length
25 -- 19 Seek error
26 -- 1A Unknown media type
27 -- 1B Sector not found
28 -- 1C Printer out of paper
29 -- 1D Write fault
30 -- 1E Read fault
31 -- 1F General failure
32 -- 20 Sharing violation
33 -- 21 Lock violation
34 -- 22 Invalid disk change
35 -- 23 FCB unavailable
36 -- 24 Sharing buffer overflow
37 -- 25 Reserved
38 -- 26 Unable to complete file operation (DOS 4.x)
39-49 -- 27-31 Reserved
50 -- 32 Network request not supported
51 -- 33 Remote computer not listening
52 -- 34 Duplicate name on network
53 -- 35 Network name not found
54 -- 36 Network busy
55 -- 37 Network device no longer exists
56 -- 38 NetBIOS command limit exceeded
57 -- 39 Network adapter error
58 -- 3A Incorrect network response
59 -- 3B Unexpected network error
60 -- 3C Incompatible remote adapter
61 -- 3D Print queue full
62 -- 3E No space for print file
63 -- 3F Print file deleted
64 -- 40 Network name deleted
65 -- 41 Access denied
66 -- 42 Network device type incorrect
67 -- 43 Network name not found
68 -- 44 Network name limit exceeded
69 -- 45 NetBIOS session limit exceeded
70 -- 46 Temporarily paused
71 -- 47 Network request not accepted
72 -- 48 Print or disk redirection is paused
73 -- 49-4F Reserved
80 -- 50 File already exists
81 -- 51 Reserved
82 -- 52 Cannot make directory entry
83 -- 53 Fail on INT 24
84 -- 54 Too many redirections
85 -- 55 Duplicate redirection
86 -- 56 Invalid password
87 -- 57 Invalid parameter
88 -- 58 Network device fault
89 -- 59 Function not supported by network (DOS 4.x)
90 -- 5A Required system component not installed (DOS 4.x)
Technical Information Database
TI904D.txt Managing disk volume labels in Delphi
Category :General Programming
Platform :All
Product :Delphi 1.0
Description:
This document contains the source code for a unit that is useful for
getting, setting, and deleting volume labels from a floppy or hard disk.
The code for getting a volume label uses the Delphi FindFirst function,
and the code for setting and deleting volume labels involves calling DOS
interrupt 21h, functions 16h and 13h respectively. Since function 16h
isn't supported by Windows, it must be called through DPMI interrupt 31h,
function 300h.
{ *** BEGIN CODE FOR VOLLABEL UNIT *** }
unit VolLabel;
interface
uses Classes, SysUtils, WinProcs;
type
EInterruptError = class(Exception);
EDPMIError = class(EInterruptError);
Str11 = String[11];
procedure SetVolumeLabel(NewLabel: Str11; Drive: Char);
function GetVolumeLabel(Drive: Char): Str11;
procedure DeleteVolumeLabel(Drv: Char);
implementation
type
PRealModeRegs = ^TRealModeRegs;
TRealModeRegs = record
case Integer of
0: (
EDI, ESI, EBP, EXX, EBX, EDX, ECX, EAX: Longint;
Flags, ES, DS, FS, GS, IP, CS, SP, SS: Word);
1: (
DI, DIH, SI, SIH, BP, BPH, XX, XXH: Word;
case Integer of
0: (
BX, BXH, DX, DXH, CX, CXH, AX, AXH: Word);
1: (
BL, BH, BLH, BHH, DL, DH, DLH, DHH,
CL, CH, CLH, CHH, AL, AH, ALH, AHH: Byte));
end;
PExtendedFCB = ^TExtendedFCB;
TExtendedFCB = Record
ExtendedFCBflag : Byte;
Reserved1 : array[1..5] of Byte;
Attr : Byte;
DriveID : Byte;
FileName : array[1..8] of Char;
FileExt : array[1..3] of Char;
CurrentBlockNum : Word;
RecordSize : Word;
FileSize : LongInt;
PackedDate : Word;
PackedTime : Word;
Reserved2 : array[1..8] of Byte;
CurrentRecNum : Byte;
RandomRecNum : LongInt;
end;
procedure RealModeInt(Int: Byte; var Regs: TRealModeRegs);
{ procedure invokes int 31h function 0300h to simulate a real mode }
{ interrupt from protected mode. }
var
ErrorFlag: Boolean;
begin
asm
mov ErrorFlag, 0 { assume success }
mov ax, 0300h { function 300h }
mov bl, Int { real mode interrupt to execute }
mov bh, 0 { required }
mov cx, 0 { stack words to copy, assume zero }
les di, Regs { es:di = Regs }
int 31h { DPMI int 31h }
jnc
End { carry flag set on error }
Error:
mov ErrorFlag, 1 { return false on error }
End:
end;
if ErrorFlag then
raise EDPMIError.Create('Failed to execute DPMI interrupt');
end;
function DriveLetterToNumber(DriveLet: Char): Byte;
{ function converts a character drive letter into its numerical equiv. }
begin
if DriveLet in ['a'..'z'] then
DriveLet := Chr(Ord(DriveLet) -32);
if not (DriveLet in ['A'..'Z']) then
raise EConvertError.CreateFmt('Cannot convert %s to drive number',
[DriveLet]);
Result := Ord(DriveLet) - 64;
end;
procedure PadVolumeLabel(var Name: Str11);
{ procedure pads Volume Label string with spaces }
var
i: integer;
begin
for i := Length(Name) + 1 to 11 do
Name := Name + ' ';
end;
function GetVolumeLabel(Drive: Char): Str11;
{ function returns volume label of a disk }
var
SR: TSearchRec;
DriveLetter: Char;
SearchString: String[7];
P: Byte;
begin
SearchString := Drive + ':\*.*';
{ find vol label }
if FindFirst(SearchString, faVolumeID, SR) = 0 then begin
P := Pos('.', SR.Name);
if P > 0 then begin { if it has a dot... }
Result := ' '; { pad spaces between name }
Move(SR.Name[1], Result[1], P - 1); { and extension }
Move(SR.Name[P + 1], Result[9], 3);
end
else begin
Result := SR.Name; { otherwise, pad to end }
PadVolumeLabel(Result);
end;
end
else
Result := '';
end;
procedure DeleteVolumeLabel(Drv: Char);
{ procedure deletes volume label from given drive }
var
CurName: Str11;
FCB: TExtendedFCB;
ErrorFlag: WordBool;
begin
ErrorFlag := False;
CurName := GetVolumeLabel(Drv); { get current volume label }
FillChar(FCB, SizeOf(FCB), 0); { initialize FCB with zeros }
with FCB do begin
ExtendedFCBflag := $FF; { always }
Attr := faVolumeID; { Volume ID attribute }
DriveID := DriveLetterToNumber(Drv); { Drive number }
Move(CurName[1], FileName, 8); { must enter volume label }
Move(CurName[9], FileExt, 3);
end;
asm
push ds { preserve ds }
mov ax, ss { put seg of FCB (ss) in ds }
mov ds, ax
lea dx, FCB { put offset of FCB in dx }
mov ax, 1300h { function 13h }
Call DOS3Call { invoke int 21h }
pop ds { restore ds }
cmp al, 00h { check for success }
je
End
Error: { set flag on error }
mov ErrorFlag, 1
End:
end;
if ErrorFlag then
raise EInterruptError.Create('Failed to delete volume name');
end;
procedure SetVolumeLabel(NewLabel: Str11; Drive: Char);
{ procedure sets volume label of a disk. Note that this procedure }
{ deletes the current label before setting the new one. This is }
{ required for the set function to work. }
var
Regs: TRealModeRegs;
FCB: PExtendedFCB;
Buf: Longint;
begin
PadVolumeLabel(NewLabel);
if GetVolumeLabel(Drive) <> '' then { if has label... }
DeleteVolumeLabel(Drive); { delete label }
Buf := GlobalDOSAlloc(SizeOf(PExtendedFCB)); { allocate real buffer }
FCB := Ptr(LoWord(Buf), 0);
FillChar(FCB^, SizeOf(FCB), 0); { init FCB with zeros }
with FCB^ do begin
ExtendedFCBflag := $FF; { required }
Attr := faVolumeID; { Volume ID attribute }
DriveID := DriveLetterToNumber(Drive); { Drive number }
Move(NewLabel[1], FileName, 8); { set new label }
Move(NewLabel[9], FileExt, 3);
end;
FillChar(Regs, SizeOf(Regs), 0);
with Regs do begin { SEGMENT of FCB }
ds := HiWord(Buf); { offset = zero }
dx := 0;
ax := $1600; { function 16h }
end;
RealModeInt($21, Regs); { create file }
if (Regs.al <> 0) then { check for success }
raise EInterruptError.Create('Failed to create volume label');
end;
end.
{ *** END CODE FOR VOLLABEL UNIT *** }
Technical Information Database
TI1427D.txt Create a new file with the .wav extension.
Category :General Programming
Platform :All
Product :Delphi All
Description:
This document describes the process for creating added
functionality ,that many Delphi users have requested,
to the TMediaPlayer. The new functionality is the ability
to create a new file with the .wav format when recording.
The procedure "SaveMedia" creates a record type that is
passed to the MCISend command. There is an appexception
that calls close media if any error occurs while attempting
to open the specified file. The application consists two
buttons. Button1 calls the OpenMedia and RecordMedia
procedures in that order.The CloseMedia procedure is called
whenever an exception is generated in this application.
Button2 calls the StopMedia,SaveMedia, and CloseMedia
procedures.
unit utestrec;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,MPlayer,MMSystem,StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure AppException(Sender: TObject; E: Exception);
private
FDeviceID: Word;
{ Private declarations }
public
procedure OpenMedia;
procedure RecordMedia;
procedure StopMedia;
procedure SaveMedia;
procedure CloseMedia;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
var
MyError,Flags: Longint;
procedure TForm1.OpenMedia;
var
MyOpenParms: TMCI_Open_Parms;
MyPChar: PChar;
TextLen: Longint;
begin
Flags:=mci_Wait or mci_Open_Element or mci_Open_Type;
with MyOpenParms do
begin
dwCallback:=Handle; // TForm1.Handle
lpstrDeviceType:=PChar('WaveAudio');
lpstrElementName:=PChar('');
end;
MyError:=mciSendCommand(0, mci_Open, Flags,
Longint(
MyOpenParms));
if MyError = 0 then
FDeviceID:=MyOpenParms.wDeviceID;
end;
procedure TForm1.RecordMedia;
var
MyRecordParms: TMCI_Record_Parms;
TextLen: Longint;
begin
Flags:=mci_Notify;
with MyRecordParms do
begin
dwCallback:=Handle; // TForm1.Handle
dwFrom:=0;
dwTo:=10000;
end;
MyError:=mciSendCommand(FDeviceID, mci_Record, Flags,
Longint(
MyRecordParms));
end;
procedure TForm1.StopMedia;
var
MyGenParms: TMCI_Generic_Parms;
begin
if FDeviceID <> 0 then
begin
Flags:=mci_Wait;
MyGenParms.dwCallback:=Handle; // TForm1.Handle
MyError:=mciSendCommand(FDeviceID, mci_Stop, Flags,
Longint(
MyGenParms));
end;
end;
procedure TForm1.SaveMedia;
type // not implemented by Delphi
PMCI_Save_Parms = ^TMCI_Save_Parms;
TMCI_Save_Parms = record
dwCallback: DWord;
lpstrFileName: PAnsiChar; // name of file to save
end;
var
MySaveParms: TMCI_Save_Parms;
begin
if FDeviceID <> 0 then
begin
// save the file...
Flags:=mci_Save_File or mci_Wait;
with MySaveParms do
begin
dwCallback:=Handle;
lpstrFileName:=PChar('c:\message.wav');
end;
MyError:=mciSendCommand(FDeviceID, mci_Save, Flags,
Longint(
MySaveParms));
end;
end;
procedure TForm1.CloseMedia;
var
MyGenParms: TMCI_Generic_Parms;
begin
if FDeviceID <> 0 then
begin
Flags:=0;
MyGenParms.dwCallback:=Handle; // TForm1.Handle
MyError:=mciSendCommand(FDeviceID, mci_Close, Flags,
Longint(
MyGenParms));
if MyError = 0 then
FDeviceID:=0;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenMedia;
RecordMedia;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
StopMedia;
SaveMedia;
CloseMedia;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnException := AppException;
end;
procedure TForm1.AppException(Sender: TObject; E: Exception);
begin
CloseMedia;
end;
end.
Reference:
Technical Information Database
TI1562D.txt - An example of drag and drop between DBGrids
Category :General Programming
Platform :All Windows
Product :All32Bit,
Description:
Title: An example of drag and drop between DBGrids
This sample component and sample project demonstrates an easy way
of enabling drag and drop of an arbitrary field in one data aware
grid onto an arbitrary field in another data aware grid.
1. Launch Delphi x.xx (the code will work in 1 and 2 as well with some
minor changes).
2. Do a File|New|Unit. Take the MyDBGrid unit (below) and paste it
in the newly created unit. Do a File|Save As. Save the unit as
MyDBGrid.pas.
3. Do a Component|Install Component. Switch to the Info New Package
tab. Put MyDBGrid.pas in the Unit file name box. Call the package
MyPackage.dpk. Hit Yes when Delphi tells you that the package
will be built and installed. Hit OK when Delphi tells you that
VCLxx.DPL is needed. The package will now be rebuilt and installed.
You will now find the TMyDBGrid component on your Samples tab on
your component palette. Close the package editor and save the
package.
4. Do a File|New Application. Right click on the form (Form1) and
select View As Text. Take the GridU1 form source (below) and paste
it in Form1. Right click on the form and select View As Form. This
may take a few moments since it's opening up the tables for you.
Take the GridU1 unit (below) and paste it in the unit (Unit1).
5. Do a File|Save Project As. Save the unit as GridU1.pas. Save the
project as GridProj.dpr.
6. Now, run the project and enjoy the dragging and dropping of fields
inbetween or with the two grids.
-----------------
The MyDBGrid unit
-----------------
unit MyDBGrid;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids;
type
TMyDBGrid = class(TDBGrid)
private
{ Private declarations }
FOnMouseDown: TMouseEvent;
protected
{ Protected declarations }
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
published
{ Published declarations }
property Row;
property OnMouseDown read FOnMouseDown write FOnMouseDown;
end;
procedure Register;
implementation
procedure TMyDBGrid.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FOnMouseDown) then
FOnMouseDown(Self, Button, Shift, X, Y);
inherited MouseDown(Button, Shift, X, Y);
end;
procedure Register;
begin
RegisterComponents('Samples', [TMyDBGrid]);
end;
end.
---------------
The GridU1 unit
---------------
unit GridU1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Db, DBTables, Grids, DBGrids, MyDBGrid, StdCtrls;
type
TForm1 = class(TForm)
MyDBGrid1: TMyDBGrid;
Table1: TTable;
DataSource1: TDataSource;
Table2: TTable;
DataSource2: TDataSource;
MyDBGrid2: TMyDBGrid;
procedure MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
var
SGC : TGridCoord;
procedure TForm1.MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
DG : TMyDBGrid;
begin
DG := Sender as TMyDBGrid;
SGC := DG.MouseCoord(X,Y);
if (SGC.X > 0) and (SGC.Y > 0) then
(Sender as TMyDBGrid).BeginDrag(False);
end;
procedure TForm1.MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
var
GC : TGridCoord;
begin
GC := (Sender as TMyDBGrid).MouseCoord(X,Y);
Accept := Source is TMyDBGrid and (GC.X > 0) and (GC.Y > 0);
end;
procedure TForm1.MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
var
DG : TMyDBGrid;
GC : TGridCoord;
CurRow : Integer;
begin
DG := Sender as TMyDBGrid;
GC := DG.MouseCoord(X,Y);
with DG.DataSource.DataSet do begin
with (Source as TMyDBGrid).DataSource.DataSet do
Caption := 'You dragged "'+Fields[SGC.X-1].AsString+'"';
DisableControls;
CurRow := DG.Row;
MoveBy(GC.Y-CurRow);
Caption := Caption+' to "'+Fields[GC.X-1].AsString+'"';
MoveBy(CurRow-GC.Y);
EnableControls;
end;
end;
end.
---------------
The GridU1 form
---------------
object Form1: TForm1
Left = 200
Top = 108
Width = 544
Height = 437
Caption = 'Form1'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
PixelsPerInch = 96
TextHeight = 13
object MyDBGrid1: TMyDBGrid
Left = 8
Top = 8
Width = 521
Height = 193
DataSource = DataSource1
Row = 1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
OnDragDrop = MyDBGrid1DragDrop
OnDragOver = MyDBGrid1DragOver
OnMouseDown = MyDBGrid1MouseDown
end
object MyDBGrid2: TMyDBGrid
Left = 7
Top = 208
Width = 521
Height = 193
DataSource = DataSource2
Row = 1
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
OnDragDrop = MyDBGrid1DragDrop
OnDragOver = MyDBGrid1DragOver
OnMouseDown = MyDBGrid1MouseDown
end
object Table1: TTable
Active = True
DatabaseName = 'DBDEMOS'
TableName = 'ORDERS'
Left = 104
Top = 48
end
object DataSource1: TDataSource
DataSet = Table1
Left = 136
Top = 48
end
object Table2: TTable
Active = True
DatabaseName = 'DBDEMOS'
TableName = 'CUSTOMER'
Left = 104
Top = 240
end
object DataSource2: TDataSource
DataSet = Table2
Left = 136
Top = 240
end
end
Reference: