home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 March / Chip_1998-03_cd.bin / zkuste / delphi / ruzkomp / INMEMDEL.ZIP / main.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-10-01  |  12.3 KB  |  357 lines

  1. unit main;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, Grids, ExtCtrls, DBGrids, DB, DBTables, BDE, Win32Except, About;
  8.  
  9. type
  10.   TMainForm = class(TForm)
  11.     SourcePanel: TPanel;
  12.     InMemPanel: TPanel;
  13.     CopyTable: TButton;
  14.     InMemGrid: TStringGrid;
  15.     DemoTable: TTable;
  16.     DemoSource: TDataSource;
  17.     SourceGrid: TDBGrid;
  18.     DataLbl: TLabel;
  19.     LocalDatabase: TDatabase;
  20.     procedure CopyTableClick(Sender: TObject);
  21.     procedure FormShow(Sender: TObject);
  22.   private
  23.     { Private declarations }
  24.     hInMemCur: hDBICur;
  25.     function FieldAsString(hCur: hDBICur; pRecBuf: pBYTE; FieldNo: word;
  26.                   FieldType: word): string;
  27.   public
  28.     { Public declarations }
  29.   end;
  30.  
  31. var
  32.   MainForm: TMainForm;
  33.  
  34. implementation
  35.  
  36. {$R *.DFM}
  37.  
  38. procedure TMainForm.FormShow(Sender: TObject);
  39. var
  40.   A: TAboutBox;
  41.  
  42. begin
  43.   DemoTable.Open;
  44.   A := TAboutBox.Create(nil);
  45.   try
  46.     A.ShowModal;
  47.   finally
  48.     A.Free;
  49.   end;
  50. end;
  51.  
  52. procedure TMainForm.CopyTableClick(Sender: TObject);
  53. var
  54.   Fld: word;                              // For loop counter...
  55.   pfDesc: pFLDDesc;                       // Field Descriptor for In-Memory table...
  56.   hTmpCur, hInMemCur: hDBICur;            // Table cursors...
  57.   pFldBuf, pInMemRecBuf, pRecBuf: pBYTE;  // Buffers...
  58.   rslt: DBIResult;                        // Dbi Function results...
  59.   fldType: array[1..1024] of word;        // Field types...
  60.   Cols: array[1..1024] of word;           // Column sizes...
  61.   CurrentRow: longint;                    // Current row on string grid...
  62.   Props: CURProps;                        // In-Memory table properties...
  63.   Blank: BOOL;                            // Blank field?? ...
  64.   Len: TSize;                             // Length of string in string grid...
  65.  
  66. begin
  67.   screen.cursor := crHourGlass;
  68.   try
  69.     // Initialize pointers to nil...
  70.     pfDesc := nil; hTmpCur := nil; hInMemCur := nil; pFldBuf := nil;
  71.     pInMemRecBuf := nil; pRecBuf := nil;
  72.     // Initialize column widths to default...
  73.     for Fld := 1 to 1024 do
  74.       Cols[Fld] := InMemGrid.DefaultColWidth;
  75.     // Clone the cursor so that moving the cursor will not effect DBGrid...
  76.     Check(DbiCloneCursor(DemoTable.Handle, True, False, hTmpCur));
  77.     // Allocate memory for field descriptor...
  78.     pfDesc := AllocMem(DemoTable.FieldCount * sizeof(FLDDesc));
  79.     // Populate the field descriptor with the DemoTable information...
  80.     Check(DbiGetFieldDescs(hTmpCur, pfDesc));
  81.     // Create the In-Memory table with the same fields as the DemoTable...
  82.       Check(DbiCreateInMemTable(LocalDataBase.Handle, 'InMem_Table',
  83.                     DemoTable.FieldCount, pfDesc, hInMemCur));
  84.     // Get the table properties of the newly created In-Memory table...
  85.     Check(DbiGetCursorProps(hInMemCur, Props));
  86.     // The record buffer for the In-Memory table is slightly different than the
  87.     //  source table, so we need to re-evalluate the buffer size...
  88.     pInMemRecBuf := AllocMem(Props.iRecBufSize);
  89.     // Set the grid row and columns to the size of DemoTable...
  90.     InMemGrid.RowCount := DemoTable.RecordCount + 1;
  91.     InMemGrid.ColCount := DemoTable.FieldCount + 1;
  92.     // It is easier to use Dbi functions to retrieve information from the source
  93.     // table, because we need to use Dbi functions to put information into the
  94.     // In-Memory table...
  95.     pRecBuf := AllocMem(DemoTable.RecordSize);
  96.     // Generic Field buffer used for moveing field data from source to In-Mem...
  97.     pFldBuf := AllocMem(1024);
  98.     // Place the names of the fields in the string grid...
  99.     for Fld := 0 to DemoTable.FieldCount - 1 do
  100.     begin
  101.       InMemGrid.Cells[Fld + 1, 0] := pfDesc^.szName;
  102.       fldType[Fld + 1] := pfDesc^.iFldType;
  103.       Inc(pfDesc);
  104.     end;
  105.     Dec(pfDesc, DemoTable.FieldCount);
  106.  
  107.     // Set the cursor to the source table to the top...
  108.     Check(DbiSetToBegin(hTmpCur));
  109.     rslt := DBIERR_NONE;
  110.  
  111.     while rslt = DBIERR_NONE do
  112.     begin
  113.       // Clear the record buffer (always on an insert / append)...
  114.       Check(DbiInitRecord(hInMemCur, pinMemRecBuf));
  115.       // Fill the source record buffer with table information...
  116.       rslt :=  DbiGetNextRecord(hTmpCur, dbiNOLOCK, pRecBuf, nil);
  117.       if rslt <> DBIERR_EOF then
  118.       begin
  119.         // for every field in the record buffer...
  120.         for Fld := 1 to DemoTable.FieldCount do
  121.         begin
  122.           FillChar(pFldBuf^, 1024, #0);
  123.           // Extract the field from the source record buffer...
  124.           Check(DbiGetField(hTmpCur, Fld, pRecBuf, pFldBuf, Blank));
  125.           if Blank = true then
  126.             // If the source field is blank, put a nil in the destination record buffer...
  127.             Check(DbiPutField(hInMemCur, Fld, pInMemRecBuf, nil))
  128.           else
  129.             // Place the source field information into the record buffer...
  130.             Check(DbiPutField(hInMemCur, Fld, pInMemRecBuf, pFldBuf));
  131.         end;
  132.         // Once the record buffer is filled, add the record to the In-Memory table...
  133.         Check(DbiAppendRecord(hInMemCur, pInMemRecBuf));
  134.       end;
  135.     end;
  136.  
  137.     // Set the In-Memory table cursor to the top of the table...
  138.     Check(DbiSetToBegin(hInMemCur));
  139.     CurrentRow := 1;
  140.     rslt := DBIERR_NONE;
  141.     // Go through the entire table retreiving record information...
  142.     while rslt = DBIERR_NONE do
  143.     begin
  144.       // Place the next record into the record buffer...
  145.       rslt :=  DbiGetNextRecord(hInMemCur, dbiNOLOCK, pInMemRecBuf, nil);
  146.       // If we have not reached the end of the table...
  147.       if rslt <> DBIERR_EOF then
  148.       begin
  149.         // Set the current row number in the string grid...
  150.         InMemGrid.Cells[0, CurrentRow] := IntToStr(CurrentRow);
  151.         // Go through each field in the record buffer...
  152.         for Fld := 1 to DemoTable.FieldCount do
  153.         begin
  154.           // Call a function to send a translated string back and place the
  155.           // information in the specified cell...
  156.           InMemGrid.Cells[Fld, CurrentRow] :=
  157.                    FieldAsString(hinMemCur, pInMemRecBuf, Fld, fldType[Fld]);
  158.           // Determine the size of the returned string so we can extend the size
  159.           // of the current column to accomodate the string length...
  160.           Win32Chk(GetTextExtentPoint32(InMemGrid.Canvas.Handle, Pchar(InMemGrid.Cells[Fld, CurrentRow]),
  161.                     Length(InMemGrid.Cells[Fld, CurrentRow]), Len));
  162.           if Len.cx > Cols[Fld] then
  163.             Cols[Fld] := Len.cx;
  164.         end;
  165.         Inc(CurrentRow);
  166.       end;
  167.     end;
  168.     // Check the field names to make sure that they will fit into the string grid...
  169.     for Fld := 0 to DemoTable.FieldCount do
  170.     begin
  171.       Win32Chk(GetTextExtentPoint32(InMemGrid.Canvas.Handle, Pchar(InMemGrid.Cells[Fld, 0]),
  172.                 Length(InMemGrid.Cells[Fld, 0]), Len));
  173.       if Len.cx > Cols[Fld] then
  174.         Cols[Fld] := Len.cx;
  175.     end;
  176.  
  177.     // Set the string grid column widths...
  178.     for Fld := 1 to DemoTable.FieldCount do
  179.       InMemGrid.ColWidths[Fld] := Cols[Fld] + 8;
  180.  
  181.   finally
  182.     // Close the source table cursor...
  183.     if hTmpCur <> nil then
  184.       Check(DbiCloseCursor(hTmpCur));
  185.     // Close the In-Memory table cursor...
  186.     if hInMemCur <> nil then
  187.       Check(DbiCloseCursor(hInMemCur));
  188.     // Free memory for field, table descriptor, and record buffers...
  189.     if pfDesc <> nil then
  190.       FreeMem(pfDesc);
  191.     if pRecBuf <> nil then
  192.       FreeMem(pRecBuf);
  193.     if pInMemRecBuf <> nil then
  194.       FreeMem(pInMemRecBuf);
  195.     if pFldBuf <> nil then
  196.       FreeMem(pFldBuf);
  197.     screen.cursor := crDefault;
  198.   end;
  199. end;
  200.  
  201.  
  202. // This function returns logical data types that are supported by in-Memory tables
  203. //  in string form.  This is a good generic Dbi Field -> string function.
  204.  
  205. // NOTE: Checking the Blank parameter from DbiGetField to determine if a field
  206. // is actually blank, is not supported on In-Memory tables.  Results from
  207. // certain field types may need to be changed to fit your needs!
  208. function TMainForm.FieldAsString(hCur: hDBICur; pRecBuf: pBYTE; FieldNo: word;
  209.                   FieldType: word): string;
  210. var
  211.   S, AMPM, tmpString, TimeStr, TimeStampStr: string;
  212.   tmpInt16: smallint;
  213.   tmpInt32: longint;
  214.   tmpFloat: double;
  215.   tmpTime: BDE.time;
  216.   tmpDate: BDE.DbiDate;
  217.   tmpTimestamp: BDE.TimeStamp;
  218.   Blank: BOOL;
  219.   tmpPChar: pChar;
  220.   Hour, Minute, MSecond, Month, Day: word;
  221.   Year: SmallInt;
  222.  
  223. begin
  224.   Result := '';
  225.   TimeStr := '%d:%d:%d %s';
  226.   TimeStampStr := '%d/%d/%d @ %d:%d:%d %s';
  227.  
  228.   case FieldType of
  229.     // For character type fields...
  230.     fldZSTRING:
  231.     begin
  232.       tmpPChar := AllocMem(1024);
  233.       Check(DbiGetField(hCur, FieldNo, pRecBuf, tmpPChar, Blank));
  234.       tmpString := tmpPChar;
  235.       freemem(tmpPChar);
  236.       // This is where a blank field is determined...
  237.       if tmpString = '' then
  238.         result := '(Blank)'
  239.       else
  240.         result := tmpString;
  241.     end;
  242.     // For INT16 (SmallInt) type fields...
  243.     fldINT16:
  244.     begin
  245.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpInt16), Blank));
  246.       result := IntToStr(tmpInt16);
  247.     end;
  248.     // For INT32 (LongInt, Integer) type fields...
  249.     fldINT32:
  250.     begin
  251.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpInt32), Blank));
  252.       result := IntToStr(tmpInt32);
  253.     end;
  254.     // For FLOAT (Numeric, Decimal) type fields...
  255.     fldFLOAT:
  256.     begin
  257.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpFloat), Blank));
  258.       result := FloatToStr(tmpFloat);
  259.     end;
  260.     // For TIME type fields...
  261.     fldTIME:
  262.     begin
  263.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpTime), Blank));
  264.       // This is where a blank field is determined...
  265.       if tmpTime = 0 then
  266.         result := '(Blank)'
  267.       else
  268.       begin
  269.         Check(DbiTimeDecode(tmpTime, Hour, Minute, MSecond));
  270.         case Hour of
  271.           0:
  272.           begin
  273.             Hour := 12;
  274.             AMPM := 'AM';
  275.           end;
  276.           1..11:
  277.             AMPM := 'AM';
  278.           12:
  279.             AMPM := 'PM';
  280.           13..24:
  281.           begin
  282.             AMPM := 'PM';
  283.             Dec(Hour, 12);
  284.           end;
  285.         end;
  286.         if (Minute < 10) and ((MSecond div 1000) < 10) then
  287.           TimeStr := '%d:0%d:0%d %s'
  288.         else
  289.           if (Minute < 10) and ((MSecond div 1000) >= 10) then
  290.             TimeStr := '%d:0%d:%d %s'
  291.           else
  292.             if (Minute > 10) and ((MSecond div 1000) < 10) then
  293.               TimeStr := '%d:%d:0%d %s';
  294.         result := Format(TimeStr, [Hour, Minute, MSecond div 1000, AMPM]);
  295.       end;
  296.     end;
  297.     // For DATE type fields...
  298.     fldDATE:
  299.     begin
  300.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpDate), Blank));
  301.       // This is where a blank field is determined...
  302.       if tmpDate = 0 then
  303.         result := '(Blank)'
  304.       else
  305.       begin
  306.         Check(DbiDateDecode(tmpDate, Month, Day, Year));
  307.         result := Format('%d/%d/%d', [Month, Day, Year]);
  308.       end;
  309.     end;
  310.     // For TIMESTAMP (Date: InterBase) type fields...
  311.     fldTIMESTAMP:
  312.     begin
  313.       // This is where a blank field is determined...
  314.       Check(DbiGetField(hCur, FieldNo, pRecBuf, pBYTE(@tmpTimeStamp), Blank));
  315.       if tmpTimeStamp = 0 then
  316.         result := '(Blank)'
  317.       else
  318.       begin
  319.         Check(DbiTimeStampDecode(tmpTimeStamp, tmpDate, tmpTime));
  320.         Check(DbiTimeDecode(tmpTime, Hour, Minute, MSecond));
  321.         Check(DbiDateDecode(tmpDate, Month, Day, Year));
  322.         case Hour of
  323.           0:
  324.           begin
  325.             Hour := 12;
  326.             AMPM := 'AM';
  327.           end;
  328.           1..11:
  329.             AMPM := 'AM';
  330.           12:
  331.             AMPM := 'PM';
  332.           13..24:
  333.           begin
  334.             AMPM := 'PM';
  335.             Dec(Hour, 12);
  336.           end;
  337.         end;
  338.         if (Minute < 10) and ((MSecond div 1000) < 10) then
  339.           TimeStampStr := '%d/%d/%d @ %d:0%d:0%d %s'
  340.         else
  341.           if (Minute < 10) and ((MSecond div 1000) >= 10) then
  342.             TimeStampStr := '%d/%d/%d @ %d:0%d:%d %s'
  343.           else
  344.             if (Minute > 10) and ((MSecond div 1000) < 10) then
  345.               TimeStampStr := '%d/%d/%d @ %d:%d:0%d %s';
  346.  
  347.         result := Format(TimeStampStr, [Month, Day, Year, Hour,
  348.                                   Minute, MSecond div 1000, AMPM]);
  349.       end;
  350.     end;
  351.   else
  352.     result := 'Unknown';
  353.   end;
  354. end;
  355.  
  356. end.
  357.