Jump to content

Gary

Members
  • Content Count

    128
  • Joined

  • Last visited

Posts posted by Gary


  1. +1 for JonRobertson & ertank

    I use UniDac as well and you use the "AddField" Menu selection not the "NewField" Menu. I am always forgetting to set the Options.KeepDesignConnected property as well. 


  2. @Shrinavat Looks great! Years ago I used X-Data and one thing I miss is the master Detail in grid. Looks like Steema has this, and at an affordable price.

     

    While the Rosinsky DBGrid is very capable the show stopper for me are the Dialogs that he has produced. Your end users can customize the grid at runtime as much as you can at design time. Extremely impressive.


  3. From FastMM

     


    --------------------------------2023/12/28 22:32:03--------------------------------
    A memory block has been leaked. The size is: 84

    This block was allocated by thread 0x6A4, and the stack trace (return addresses) at the time was:
    9371E6 [System.pas][System][@GetMem$qqri][4960]
    938957 [System.pas][System][TObject.NewInstance][18324]
    93905A [System.pas][System][@ClassCreate$qqrpvzc][19654]
    9F9C30 [System.Classes.pas][System.Classes][Classes.TStringList.Create][8121]
    94C231 [FastMM4.pas][FastMM4][UpdateHeaderAndFooterCheckSums$qqrp29Fastmm4.TFullDebugBlockHeader][9153]
    94D214 [FastMM4.pas][FastMM4][DebugGetMem$qqri][9731]
    EA116F [int.PsFNCTaskDialogUIListener.pas][Int.PsFNCTaskDialogUIListener][Psfnctaskdialoguilistener.TTaskDialogParams._op_Initialize][66]
    108E6E5 [PsFNCTaskDialogUIListener.pas][PsFNCTaskDialogUIListener][TPsFNCTaskDialogUIListener.SetDialogParams][32]
    108E827 [PsFNCTaskDialogUIListener.pas][PsFNCTaskDialogUIListener][TPsFNCTaskDialogUIListener.ExecuteDialog][47]
    108F3C9 [USender.pas][USender][TfrmSender.tbtnTaskDialogClick][77]
    C0CF34 [FMX.Controls.pas][FMX.Controls][Controls.TControl.GetHeight][5512]

    The block is currently used for an object of class: System.Classes.TStringList

    The allocation number is: 296325

    Current memory dump of 256 bytes starting at pointer address 7E6DB770:
    20 B9 9C 00 00 00 00 00 50 B9 30 7F 6C E3 1B 7F 00 00 00 00 00 00 00 00 2C 00 22 00 3D 00 0E 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 00 00 16 8C AF 78 80 80 80 80 80 80 80 80 00 00 00 00 51 BB 6D 7E
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 88 85 04 00 9F A8 93 00 3C AD 93 00 A2 CC 93 00
    F2 E6 08 01 27 E8 08 01 C9 F3 08 01 34 CF C0 00 9D AB C0 00 77 D6 CB 00 F4 B2 C0 00 D4 65 E8 00
    A4 06 00 00 A4 06 00 00 02 72 93 00 59 A9 93 00 28 C5 93 00 E2 D3 C0 00 39 8B 93 00 6E 89 93 00
    A5 90 93 00 2E 9A CB 00 B3 57 E5 00 ED 92 93 00 45 C0 E8 00 48 00 00 00 B0 04 02 00 CB 3D A4 8E
    8C 7C 0C 01 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
             .  .  .  .  .  P     0    l     .    .  .  .  .  .  .  .  .  ,  .  "  .  =  .  .  .
    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
    .  .  .  .  .  .  .  .  .  .  .  .  .        x                          .  .  .  .  Q     m  ~
    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .        .  .           .  <        .           .
          .  .  '     .  .        .  .  4        .           .  w        .           .     e     .
       .  .  .     .  .  .  .  r     .  Y        .  (        .           .  9        .  n        .
             .  .        .     W     .           .  E        .  H  .  .  .     .  .  .     =      
       |  .  .                                                                                    

    --------------------------------2023/12/28 22:32:03--------------------------------
    A memory block has been leaked. The size is: 20

    This block was allocated by thread 0x6A4, and the stack trace (return addresses) at the time was:
    9371E6 [System.pas][System][@GetMem$qqri][4960]
    93A89F [System.pas][System][@NewUnicodeString$qqri][26024]
    93AD3C [System.pas][System][@UStrAsg$qqrr20System.UnicodeStringx20System.UnicodeString][26946]
    9F6F30 [System.Classes.pas][System.Classes][Classes.TStrings.Create][6729]
    9F9C3D [System.Classes.pas][System.Classes][Classes.TStringList.Create][8122]
    94D214 [FastMM4.pas][FastMM4][DebugGetMem$qqri][9731]
    EA116F [int.PsFNCTaskDialogUIListener.pas][Int.PsFNCTaskDialogUIListener][Psfnctaskdialoguilistener.TTaskDialogParams._op_Initialize][66]
    108E6E5 [PsFNCTaskDialogUIListener.pas][PsFNCTaskDialogUIListener][TPsFNCTaskDialogUIListener.SetDialogParams][32]
    108E827 [PsFNCTaskDialogUIListener.pas][PsFNCTaskDialogUIListener][TPsFNCTaskDialogUIListener.ExecuteDialog][47]
    108F3C9 [USender.pas][USender][TfrmSender.tbtnTaskDialogClick][77]
    C0CF34 [FMX.Controls.pas][FMX.Controls][Controls.TControl.GetHeight][5512]

    The block is currently used for an object of class: UnicodeString

    The allocation number is: 296326

    Current memory dump of 256 bytes starting at pointer address 7F1BE360:
    B0 04 02 00 01 00 00 00 02 00 00 00 0D 00 0A 00 00 00 AA 4B E7 F7 80 80 00 00 00 00 A1 FF 1B 7F
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5F BF 04 00 E6 71 93 00 57 89 93 00 5A 90 93 00
    7F 21 E8 00 12 EE E8 00 31 8A E8 00 1F 40 E8 00 63 40 E8 00 6E EE E8 00 62 DF A0 00 6B 8A 93 00
    A4 06 00 00 A4 06 00 00 02 72 93 00 75 89 93 00 A5 90 93 00 E5 21 E8 00 6B 8A 93 00 35 38 E8 00
    02 72 93 00 75 89 93 00 A5 90 93 00 F7 10 A8 00 6B 8A 93 00 14 00 00 00 DC E2 E6 00 4C 29 7E 8F
    8C 7C 0C 01 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 B3 D6 81 70 00 00 00 00 C1 E9 1B 7F
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9F BF 04 00 E6 71 93 00 57 89 93 00 5A 90 93 00
    73 35 E3 00 1B 35 E3 00 51 C4 E2 00 13 C5 E2 00 3E 3F E8 00 D1 F1 E8 00 0A 3A E8 00 02 72 93 00
       .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .     K              .  .  .  .        .  
    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  _     .  .     q     .  W        .  Z        .
     !     .  .        .  1        .  .  @     .  c  @     .  n        .  b        .  k        .
       .  .  .     .  .  .  .  r     .  u        .           .     !     .  k        .  5  8     .
    .  r     .  u        .           .     .     .  k        .  .  .  .  .           .  L  )  ~   
       |  .  .                                                           p  .  .  .  .        .  
    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .        .  .     q     .  W        .  Z        .
    s  5     .  .  5     .  Q        .  .        .  >  ?     .           .  .  :     .  .  r     .

    --------------------------------2023/12/28 22:32:03--------------------------------
    This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):

    13 - 20 bytes: UnicodeString x 1
    69 - 84 bytes: System.Classes.TStringList x 1

    Note: Memory leak detail is logged to a text file in the same folder as this application. To disable this memory leak check, undefine "EnableMemoryLeakReporting".


  4. Sorry copied same block twice Here is the other part

    procedure TPsFNCTaskDialogUIListener.SetDialogParams(Params: TTaskDialogParams);
    begin
      ClearDialog;
    
      FTaskDialog.Title := Params.Title;
      FTaskDialog.Instruction := Params.Instruction;
      FTaskDialog.Icon := TTMSFNCTaskDialogIcon(Params.Icon);
      FTaskDialog.Options := TTMSFNCTaskDialogOptions(params.Options);
      for var s : String in params.CustomButtons do
        FTaskDialog.CustomButtons.Add(s);
    
    end;

     


  5. Hello all,

     

    I am trying to separate my UI from the rest of my application. I want to use an interfaced listener on my main form and pass a reference to it around to parts of the application that need input from the user. I have no problem with the InputBox or MsgDialog as they don't take too many parameters, however I want to use TMSTaskDialog as well (Different listener since requires 3rd party). The problem I am having is that the TaskDialog has so many options that I want to pass a record with all the parameters. I only have a problem with TStrings. I get memory leak on close. 

    Work in progress but here are the relevant parts.

    TTaskDialogParams = record
        DisplayedButtons : TPsTaskDialogDisplayedButtons;
        Title: String;
        Instruction: string;
        Content: string;
        Options: TPsTaskDialogOptions;
        CustomButtons : TStringList;
    
        Icon: TPsTaskDialogIcon;
    
        FResultCallBack: TProc<TTaskDialogReturnParams>;
        procedure Clear;
        class operator Initialize (out Dest: TTaskDialogParams);
        class operator Finalize (var Dest: TTaskDialogParams);
      end;
    
      IPsFNCTaskDialogUIListener = interface
        ['{BA6ABA84-F3EE-4421-856F-42E76C878D3B}']
        procedure ExecuteDialog(const Params : TTaskDialogParams);
      end;
          
      procedure TTaskDialogParams.Clear;
    begin
      CustomButtons.Clear;
      CustomButtons.Free;
    end;
    
    class operator TTaskDialogParams.Finalize(var Dest: TTaskDialogParams);
    begin
    //  Dest.CustomButtons.Free;
    end;
    
    class operator TTaskDialogParams.Initialize(out Dest: TTaskDialogParams);
    begin
      Dest.CustomButtons := TStringList.Create;
    end;
    
    In listener I set string params by enumerating through the recordsStringList.
    procedure TPsFNCTaskDialogUIListener.ExecuteDialog(const Params :
        TTaskDialogParams);
    begin
      SetDialogParams(Params);
      FTaskDialog.Execute;
      Params.Clear;
    //  FTaskDialog.CustomButtons.Clear;
    end;
          
    Then show it
    procedure TPsFNCTaskDialogUIListener.ExecuteDialog(const Params :
        TTaskDialogParams);
    begin
      SetDialogParams(Params);
      FTaskDialog.Execute;
      Params.Clear;
    //  FTaskDialog.CustomButtons.Clear;
    end;      
          

    Some code in there is things I have tried to no avail. Any help would be appreciated. I tried this before and gave up and used an Interfaced  Class instead.


  6. @Columbo  This is such a great sample app! Fine the way it is but simple enough that you can use it to experiment as you move forward.

    How about letting your users see your Dino's in the order they want?

     

    procedure TfrmDino.Reorder;
    begin
      tblPLife.Close;
      if rgSort.ItemIndex = 0 then
        tblPLife.SQL[1] := 'ORDER BY record;'
      else
        tblPLife.SQL[1] := 'ORDER BY name;';
    
      tblPLife.Open;
      LoadList;
      LoadImages;
    end;

    OrderBy.png

    • Like 1

  7. Hello all,

     

    How do you test if a FDConnection using SQLite is connected to an actual Database? 

    If I drop a FDConnection on a form, set it's DriverName SQLite, leave the Params->Database property empty and connect there is no error. This code shows the "Connected' Message

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      if FDConnection1.Connected then
        ShowMessage('Connected');
    end;

     


  8. Setting designtime components can be very helpful, try this:

     

    Open the connection and table.

    Right click table and select FieldsEditor...

    Right Click FieldsEditor and select AddAllFields

    Notice the field objects are added to the form definition (tblPLifename)

    Click the dropdown of the FieldName on your DBEdits and notice you have a list to choose from, no typing in the field name where simple typo can derail you. Also you can now do this:

    Quote

    procedure TfrmDino.LoadImages;
    begin
      dinoImage.Picture.LoadFromFile('dino_images\' + tblPLifename.AsString + '.jpg');
      dinoSize.Picture.LoadFromFile('dino_size\' + tblPLifename.AsString + '_size' + '.jpg');
    end;

    No more tblPLife.FieldByName('name').AsString


  9. BTW Congratulations on your first project, and I have to say it's a beauty. Most first projects are dull and boring. However....

     

    Your final project crashes on my computer, it will only run on your system! Reason is a common mistake that has bitten me many times. Your Database path is still hard coded to your system. If you proudly load it on a flash drive (as you should) and show it, it will crash(very embarrassing). See the procedure OpenConnection in my earlier post. You still need it hard coded to work with it in design mode, so the habit I have gotten into is to always set Connected to False and Database to an empty string first thing in the OnCreate event. Then make sure to use runtime function to get Database location before connecting.

     

     


  10. First param is a string so name needs quotes 'name'

    You can leave the last param empty, but then they have to match exactly. That works here where you are selecting from a list, however I like to be more forgiving as to case as it can frustrate users if values are capitalized and they just type lowercase.

    You can eliminate both iSelect and sName and the assignment calls like this:

    tblPLife.Locate('name', lbxData.Items[lbxData.ItemIndex], [loCaseInsensitive]);

    Link is for 12.0 change Athens to Alexandria, but in this case no different

    Data.DB.TDataSet.Locate - RAD Studio API Documentation (embarcadero.com)

    Data.DB.TLocateOptions - RAD Studio API Documentation (embarcadero.com)


  11. @Uwe Raabe  That sounds good, but it simply is not the case unless something has changed. Some time ago I decided after having paid for the Pro version as a hobbyist, that I would be satisfied with the version I was running and did not renew my subscription. 2 months later I changed my computer name from the default Desktopxxx to a more recognizable name. That invalidated my license, and I needed an install bump. I could not get Embarcadero to do it no matter who I talked to. They eventually allowed me to renew the license at the renew rate instead of full price, even though I was outside the grace period. Of course they backdated it 2 months as well. I consider Delphi ransomware, at least the renewal (Ransom) is not that high.

     

    I prefer Delphi to anything else I have tried. It's far easier for someone without a formal computer science education, at least the connection between code and UI. 

     

    Embarcadero's policy on this is reprehensible and probably illegal. Any company with an install limit policy should be required to allow their users to deactivate/reactivate installs. I have several other software programs that do just that, and even when I have forgotten to do that, a simple email to support to move the license gets a quick response, with a reminder to remember to do it myself 🙂 I even have an original Delphi 2009 Pro CD in the case with Codegear serial numbers on it that I cannot register.

    • Like 1

  12. I added a panel to the top image set align to all right width to 50 Caption -- font color clCream Panel color to your label's font color $0000023F (keep trying for exact match to your brown) and got rid of all borders. Add code to Panel OnClick

    Quote
    
    procedure TfrmDino.pnlMinimizeClick(Sender: TObject);
    begin
      Self.WindowState := wsMinimized;
    end;

     

    JonRobertson's suggestion may be better to minimize the form but I don't have experience either.

     

    Add to top image OnMouseDown event for dragging

    procedure TfrmDino.Image1MouseDown(Sender: TObject; Button: TMouseButton;
        Shift: TShiftState; X, Y: Integer);
    const
      SC_DRAGMOVE = $F012;
    begin
      if Button = mbLeft then
      begin
        ReleaseCapture;
        Perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0);
      end;
    end;

     

    Screenshot 2023-12-22 214024.png


  13. @Columbo My 2 cents:

    Beautiful UI BTW.

    I don't like to do anything in a form's OnCreate event that I don't have to, it has caused me trouble in the past as things may not always be created before I use them. Nor do I ever open Databases there, use the OnShow if you must, even better have a dedicated button. Break things down into separate procedures and assign them to events. I added a combobox for the search and implemented the search with a simple RecNo assignment.

     

    Things I changed it the Object inspector:

    Form

      WindowState = wsNormal 

      Position = poScreenCenter

    CustomTitleBar = False // You cannot move it around or Min Max with this set true

    ComboBox

      DropDownCount = 15 //However many you want

     

    
    unit Dinobase_u;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Imaging.jpeg, Vcl.ExtCtrls,
      Vcl.StdCtrls, Vcl.ComCtrls, System.ImageList, Vcl.ImgList, FireDAC.Stan.Intf,
      FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
      FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
      FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs,
      FireDAC.Phys.SQLiteWrapper.Stat, FireDAC.VCLUI.Wait, FireDAC.Stan.Param,
      FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt, FireDAC.Comp.Client, Data.DB,
      FireDAC.Comp.DataSet, Vcl.DBCtrls, Vcl.Mask, Vcl.Buttons;
    
    
    type
      TfrmDino = class(TForm)
        pnlTitlebar: TPanel;
        Image1: TImage;
        pnlHeader: TPanel;
        Image2: TImage;
        lblName: TLabel;
        lblMeaning: TLabel;
        lblPronounce: TLabel;
        lblPeriod: TLabel;
        lblMainGroup: TLabel;
        pnlFooter: TPanel;
        Footer: TImage;
        lblSize: TLabel;
        lblLived: TLabel;
        lblDiet: TLabel;
        lblFossils: TLabel;
        PLTabSheet: TPageControl;
        TabSheet1: TTabSheet;
        SizeComp: TTabSheet;
        dinoImage: TImage;
        dinoSize: TImage;
        conPLife: TFDConnection;
        tblPLife: TFDTable;
        Datasource1: TDataSource;
        lblRecno: TLabel;
        btnExit: TBitBtn;
        dbeName: TDBEdit;
        dbeMeaning: TDBEdit;
        dbePronounciation: TDBEdit;
        dbePeriod: TDBEdit;
        dbeMainGroup: TDBEdit;
        dbeSize: TDBEdit;
        dbeLived: TDBEdit;
        dbeDiet: TDBEdit;
        dbeFossils: TDBEdit;
        dbmFactfile: TDBMemo;
        dbeRecno: TDBEdit;
        DBNavigator1: TDBNavigator;
        cbxSearch: TComboBox;
        procedure btnExitClick(Sender: TObject);
        procedure cbxSearchClick(Sender: TObject);
        procedure FormShow(Sender: TObject);
        procedure tblPLifeAfterScroll(DataSet: TDataSet);
      private
        { Private declarations }
        procedure OpenConnection;
        procedure OpenTable;
        procedure LoadList;
        procedure LoadImages;
      public
        { Public declarations }
      end;
    
    var
      frmDino: TfrmDino;
    
    implementation
    
    {$R *.dfm}
    
    uses
      System.IOUtils,
      VCL.Dialogs;
    
    const
      DINO_DB = 'dino.db';
    
    procedure TfrmDino.btnExitClick(Sender: TObject);  //Exit Button
    begin
      Close;
    end;
    
    procedure TfrmDino.cbxSearchClick(Sender: TObject);
    begin
      //Search... is at ItemIndex[0] and we load the list from the table so
      //a 1 for 1 on the count so nop searching needs to be done just
      //set the Tables RecNo it is write as well as read property
      tblPLife.RecNo := cbxSearch.ItemIndex;
      //Set combobox back to Search...
      cbxSearch.ItemIndex := 0;
      //if you do not like the search box selected set focus to any control
      dbeName.SetFocus;
    end;
    
    procedure TfrmDino.FormShow(Sender: TObject);
    begin
      OpenConnection;
      OpenTable;
      LoadList;
      //Images will be loaded when record changes after this
      LoadImages;
    end;
    
    procedure TfrmDino.LoadImages;
    var
      lName : String;
    begin
      lName := tblPLife.FieldByName('name').AsString;
    
      // Load the dino image and display it
      dinoImage.Picture.LoadFromFile('dino_images\' + lName + '.jpg');
      // Load the size image and display it
      dinoSize.Picture.LoadFromFile('dino_size\' + lName + '_size' + '.jpg');
    end;
    
    procedure TfrmDino.LoadList;
    begin
      cbxSearch.Items.Clear;
      cbxSearch.Items.Add('Search...');
      //Disable all data aware controls so the UI does not repaint
      //as we load the list
      tblPLife.DisableControls;
      try
        tblPLife.First;
        while not tblPLife.Eof do
        begin
          cbxSearch.Items.Add(tblPLife.FieldByName('name').AsString);
          tblPLife.Next;
        end;
      finally
        tblPLife.First;
        tblPLife.EnableControls;
      end;
    end;
    
    procedure TfrmDino.OpenConnection;
    begin
      conPLife.Params.Database := ExtractFilePath(Application.ExeName) + DINO_DB;
      try
        conPLife.Connected := True;
      Except
        on E: EDatabaseError do
        begin
          ShowMessage('Error connecting to: ' + conPLife.Params.Database + ': ' +
            E.Message);
        end;
      end;
    end;
    
    procedure TfrmDino.OpenTable;
    begin
      try
        tblPLife.Open
      Except
        on E: EDatabaseError do
        begin
          ShowMessage('Error opening table with: ' + E.Message);
        end;
      end;
    end;
    
    procedure TfrmDino.tblPLifeAfterScroll(DataSet: TDataSet);
    begin
      //if Controls are disabled we are loading the list and don't want
      //to load images
      if not tblPLife.ControlsDisabled then
        LoadImages;
    end;
    
    end.

     

    Dino.png


  14. I think JonRobertson has identified the problem. In his post he recommends you use one dataset and one datasource. Do you have multiple dataset's? If you are still using the FDQuery with parameters, as well as a table that could be the problem. They have different use cases and mixing them will cause you frustration!

     

    The Parameterized query will only ever return one record. You cannot use a DBNavigator since there is only one record, there is no prior or next record, the one record is the first as well as the last. This is fine for searching a table. When your user presses the search button you can update your query from the edit and load the data as well as your images. However, with an interface like this how will your users see any other entries unless they know, and as you mentioned can spell the name they are looking for? You cannot navigate your database table with a parameterized query. If you managed to get this working with the query you have much more going on.

     

    For what you want you should use a Table or "Select *" in your query. Now your dataset will have all the records from the table and you can hook up a DBNavigator. As you use the buttons to move from one record to another the Dataset's (Table or Query since they both descend from TDataset) AfterScroll event will be fired, you can load your images or any other custom data display you have here.

     

    To search for a particular record, you use the Locate method of the dataset passing the value from your search edit.

    if not
      DataSetName.Locate('name', Edit.Text, [loCaseInsensitive]);
    then
      ShowMessage(Edit.Text + ' not found.');

    Locate returns true or false so you can check it. If successful the dataset will move to the record, your data aware controls will display the data and the Dataset's AfterScroll event will be called and the images will be loaded.

    You should post your code with your questions, at least the procedure you are working on. 


  15. Yes, I would like to see the data. As Stano said, there is another way to accomplish your objective, always is in Delphi.

    Using the Query is always better in a Client/Server environment. In your use case your data is local and I don't think with the small amount of data the performance would suffer. It is muck easier in this case to use DB controls and a Table. No SQL at all. You use the Locate method of the DataSet to search for specific items, and that allows you to hook up the navigator and just scroll through the table.


  16. Couple of things to check. Is the dbEdit field set properly? Are you still using the parameterized query? If so there will only be one record in your dataset, so no records for the navigator to move to, in fact if you are using the parameterized query the navigator is pointless it only works on a set of records.

     


  17. Use the DataSource DataChange event, (Object Inspector Event tab) put your image loading procedure there. It will be called every time the record changes. Not sure how you get the record number into the edit as it's not a field? You can add code to update a label  in the DataChange event also, Label.Caption :='Record Number: " + Query.RecNo.ToString.

     

    If you want to get fancy with the names you can try iterating through the records and filling a comboBox with the names. Then use it's on change event to trigger your lookup. Your users will just select from a list (Have fun researching that 🙂 ).

×