⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 delsec06.txt

📁 《Delphi开发人员指南》配书原码
💻 TXT
📖 第 1 页 / 共 2 页
字号:
             rslt := DbiSetProp(hDBIObj(oTable.Handle), curSOFTDELETEON,
             LongInt(Value));
             if rslt <> DBIERR_NONE then
               begin
                 DbiGetErrorString(rslt, szErrMsg);
                 raise Exception.Create(StrPas(szErrMsg));
               end;
           except
             on E: EDBEngineError do ShowMessage(E.Message);
             on E: Exception do ShowMessage(E.Message);
           end;
       finally
         oTable.Refresh;
         oTable.EnableControls;
       end;
     end;

--------------------------------------------------------------------------------
Q:   "How can I create a column in the grid to which records in a dBASE table
     are marked for deletion?"

A:   Create a calculated field, then for the OnCalcField event of the table
     replace the calculated field you've created like so:

     procedure TForm1.Table1CalcFields(DataSet: TDataset);
     var
       RCProps : RecProps;
       Result : DBIResult;
     begin
       Result := DbiGetRecord(Table1.Handle, dbiNoLock, Nil, @RCProps);
       If RCProps.bDeleteFlag then Table1Del.Value := 'X' else
       Table1Del.Value := '';
     end;

     Note: You must first call the SetDelete(TTable,TRUE) function from the
     previous FAQ:

--------------------------------------------------------------------------------
Q:   "How can I determine the actual size of a blob field as stored in
     the table?"

A:   Here is a function GetBlobSize that returns the size of a given blob, memo,
     or graphic field.  An example of calling it follows.

     Function GetBlobSize(Field: TBlobField): Longint;
     begin
       with TBlobStream.Create(Field, bmRead) do
       try
         Result := Seek(0, 2);
       finally
         Free;
       end;
     end;

     procedure TForm1.Button1Click(Sender: TObject);
     begin
       { This sets the Edit1 edit box to display the size of }
       { a memo field named Notes.                           }
       Edit1.Text := IntToStr(GetBlobSize(Notes));
     end;

--------------------------------------------------------------------------------
Q:  "How do I show the contents of a memo field in a DBGrid?"

A:  Use the following code for the OnDrawDataCell event of the DBGrid.  Note:
    before running create a TMemoField object for the memo field by double
    clicking on the TTable component and adding the memo field.

    procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
      Field: TField; State: TGridDrawState);
    var
      P  : array [0..50] of char;   {array size is number of characters needed}
      BS : tBlobStream;             {from the memo field}
      S  : String;
    begin
      If Field is TMemoField then begin
      with (Sender as TDBGrid).Canvas do
        begin
          {Table1Notes is the TMemoField}
          BS := tBlobStream.Create(Table1Notes, bmRead);
          FillChar(P,SizeOf(P),#0);               {terminate the null string}
          BS.Read(P, 50);           {read 50 chars from memo into blobStream}
          BS.Free;
          S := StrPas(P);
          while Pos(#13, S) > 0 do              {remove carriage returns and}
            S[Pos(#13, S)] := ' ';              {line feeds}
          While Pos(#10, S) > 0 do
            S[Pos(#10, S)] := ' ';
          FillRect(Rect);                          {clear the cell}
          TextOut(Rect.Left, Rect.Top, S);         {fill cell with memo data}
        end;
      end;
    end;

--------------------------------------------------------------------------------
Q:  "Is there a way to use the return key for data entry, instead of tab or the
    mouse?"

A:  Use this code for an Edit's OnKeyPress event.

    procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
    begin
      If Key = #13 Then
      Begin
        SelectNext(Sender as tWinControl, True, True );
        Key := #0;
      end;
    end;

    This causes Enter to behave like tab.  Now, select all controls on the form
    you'd like to exhibit this behavior (not Buttons) and go to the Object
    Inspector and set their OnKeyPress handler to EditKeyPress.  Now, each
    control you selected will process Enter as Tab.  If you'd like to handle
    this at the form (as opposed to control) level, reset all the controls
    OnKeyPress properties to blank, and set the _form_'s OnKeyPress property to
    EditKeyPress.  Then, change Sender to ActiveControl and set the form's
    KeyPreview property to true:

    procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
    begin
      If Key = #13 Then
      begin
        SelectNext(ActiveControl as tWinControl, True, True );
        Key := #0;
      end;
    end;

    This will cause each control on the form (that can) to process Enter as Tab.

--------------------------------------------------------------------------------
Q:  "How do I do a locate on a non-indexed field?"

A:  The following function can be added to your to your unit and called as
    follows:

      Locate(Table1, Table1LName, 'Beman');

    Table1 is your table component, Table1LName is TField you've add with the
    fields editor (double click on the table component) and 'Beman' is the name
    you want to find.

    (* Locate will find SValue in a non-indexed table *)
    Function Locate( const oTable: TTable; const oField: TField;
    const sValue: String): Boolean;
    var
      bmPos  : TBookMark;
      bFound : Boolean;
    begin
      Locate := False;
      bFound := False;
      If not oTable.Active then Exit;
      If oTable.FieldDefs.IndexOf( oField.FieldName ) < 0 then Exit;
      bmPos := oTable.GetBookMark;
      With oTable do
      begin
        DisableControls;
        First;
        While not EOF do
          if oField.AsString = sValue then
          begin
            Locate := True;
            bFound := True;
            Break;
          end
          else Next;
      end ;
      If (Not bFound) then oTable.GotoBookMark( bmPos);
      oTable.FreeBookMark( bmPos );
      oTable.EnableControls;
    end;

--------------------------------------------------------------------------------
Q:  "Why can't I use the ixUnique option when creating indexes for Paradox
    tables with the AddIndex method of the TTable component?"

A:  The index options used in the AddIndex method of the TTable component are
    table specific.  For example, the ixUnique option works with dBASE tables
    but not Paradox.  The following table shows how these options apply to dBASE
    and Paradox tables.

    Index Options         dBASE    Paradox
    ---------------------------------------
    ixUnique               *
    ixDescending           *        *
    ixNonMaintained        *        *
    ixPrimary                       *
    ixCaseInsensitive               *

--------------------------------------------------------------------------------
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 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 DbiProcs, DbiTypes, DBConsts;

    function RecordNumber(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 DBError(SDataSetClosed);

        { 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;

--------------------------------------------------------------------------------
Q:  "I am getting a DBEngine message when editing a record that says "Multiple
    records found but only one expected".  What does this mean?

A:  You may need to create a unique index on the table so that each row can be
    uniquely identified.  That *may* first require altering the table and adding
    a column to be populated with unique values.

--------------------------------------------------------------------------------
Q:  "I have had no success getting at Microsoft Access data using Delphi other
    than a simple TTable view.  Using TQuery I can get a read-only view to work,
    but I cannot a read/write view to work.  After the login screen I am
    presented with an exception message like 'Passthrough SQL connection must
    be shared'."

A:  Use the Database Engine Configuration to change the 'SQLPASSTHRU MODE'
    option in the alias associated with your Access database from its default
    blank value to 'SHARED AUTOCOMMIT' (without the quotes).

--------------------------------------------------------------------------------
Q:  "How can I determine when the current record in a dataset has changed?"

A:  Check the DataSource's State property in the OnDataChanged event.  The State
    property will be set to dsBrowse if the record position has changed.  The
    following example will display a message box every time the record position
    has changed in MyDataSource:

    procedure TMyForm.MyDataSourceDataChange(Sender: TObject; Field: TField);
    begin
      if (Sender as TDataSource).State = dsBrowse then
        ShowMessage('Record Position Changed');
    end;

--------------------------------------------------------------------------------
Q:  Why is it that when I create a table using the TTable component's
    CreateTable method it creates the fields correctly but does not create
    the indexes even though I do a

    NewTable.IndexDefs.Assign(Table1.IndexDefs)?

A:  This is the correct way to transfer the index definition to NewTable,
    however, the IndexDefs property of Table1 may not be up-to-date so
    you need to call the Update method of Table1's IndexDefs property prior
    to its assignment to NewTable like this example shows:

    with NewTable do begin
      Active := False;
      DatabaseName := 'DBDEMOS';
      TableName := 'Temp';
      TableType := ttParadox;
      FieldDefs.Assign(Table1.FieldDefs);
      Table1.IndexDefs.Update;             { Do an update first }
      IndexDefs.Assign(Table1.IndexDefs);
      CreateTable;
    end;

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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -