Jump to content

Gary

Members
  • Content Count

    139
  • Joined

  • Last visited

Posts posted by Gary


  1. @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

  2. 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


  3. @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


  4. 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. 


  5. 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.


  6. 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.

     


  7. 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 🙂 ).


  8. I just got all cross platforms working the other day. XCode had an update today and I think the Simulator was updated to 17.2? Anyway now I can no longer deploy to it. PAServer is working as I can still deploy to MacOS. Anyone else have same problem?

     

    Both versions

    Delphi 11.3 Windows 11

    Delphi 12 Windows 11 Virtualbox

     

    [PAClient Error] Error: E6664 /Users/sheltons/PAServer/scratch-dir/gshel-MacMini/Project1.launchscreen/Assets: error: The operation couldn’t be completed. Failed to locate any simulator runtime matching options: {[PAClient Error] Error: E6664     BuildVersionString = 21C52;
    [PAClient Error] Error: E6664     Platforms =     (
    [PAClient Error] Error: E6664         "com.apple.platform.iphonesimulator"
    [PAClient Error] Error: E6664     );
    [PAClient Error] Error: E6664     VersionString = "17.2";
    [PAClient Error] Error: E6664 }
    [PAClient Error] Error: E6664     Failure Reason: Failed to locate any simulator runtime matching options: {
    [PAClient Error] Error: E6664     BuildVersionString = 21C52;
    [PAClient Error] Error: E6664     Platforms =     (
    [PAClient Error] Error: E6664         "com.apple.platform.iphonesimulator"
    [PAClient Error] Error: E6664     );
    [PAClient Error] Error: E6664     VersionString = "17.2";
    [PAClient Error] Error: E6664 }


  9. @Columbo

    FWIW Listen to Remy! He's been around for a while, even part of the old Team 'B' I believe. He's one of the few experienced programmers that actually help newbies, and that takes patience. He helped me some time ago with some Interbase deployment issues that looking back were so simple yet at the time I just couldn't get it.

    Weirdo12 seems to be experienced with Database's especially Firebird, FireDac and Zeos so read his posts closely as well. I've learned a lot just reading them 🙂

     

    The Database landscape has changed drastically since DBase and the Borland Database Engine. Everything is in the cloud, 3 Tier and Rest and it is good to embrace this change for Enterprise applications, but for the kind of Home and friend use that you and I do, Delphi offers much simpler 2 Tier or even direct access solutions. For example, you can use a DBEdit instead of a plain edit and connect it to the "Name" field in your Query and never have to worry about 'Loading data' into controls. There are several Data Aware controls that you just set their DataSource, or additionally a particular field and the data just display's. 

     

    You can right click on the TFDQuery in your designed and if you have your connection active you can use the 'Parameters' tab to set a value and see the result at design time, and more..

     

    Much of what you are doing looks like a console application. Everything is Visual now. Like Remy said set up your UI in the Object inspector, look for properties, there is a WindowState property set it in the designer to wsMaximized not in code (Check out the Position property of the form). In the last projects you posted what you are trying to do can be done in the designer and only 1 or 2 lines of actual code. While that may not sound exciting if you want to write code, you can whip out a simple Home use DB application that way in a matter of minutes, very exciting! 

     

    BTW online help for Delphi 11 can be found here: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Main_Page


  10. @Columbo  Glad you did not give up!

     

    The control that is selected (Focused) when your app runs is determined by it's TabOrder. You can see this as a property in the Object Inspector. To reorder them you can change them manually or right click the edit box and select TabOrder... to arrange all components.

     

     


  11. I would agree with Stano! However, this means you need to install 3rd party packages.

    You will need Data Access components. Zeos is popular. 

    You will need to install and learn Firebird.

    Firebird and Interbase have the same roots. They were forked from same source some time ago. Embarcadero continues to develop it as commercial software, even if the community edition lets you build with IBLite, you will need to pay a license to use it outside the IDE. Firebird.org continues on the open source version. I believe they just released version 5? 

     

    I did some projects with Firebird. They still work, but I personally find it difficult to work with. No doubt it is my lack of experience.

     

    I'm sure there is freeware that can at least export your old data to a .csv file, then as Stano said you can use FireDac BatchMove component to import into your Database of choice. I just added this feature to the one and only commercial app I have. It downloads GPS data in .csv format from the company's vehicle tracking service and imports it into a MYSQL Database.


  12. What version of Delphi are you using? I have Pro + Devart Data Access components. Pro edition supports SQLite & Interbase Lite with Firedac out of the box, but not client/server (MySQL, Oracle..), not sure if the community edition supports any Databases. If you are using a trial edition Database support will end.

     

    If community edition supports SQLite I wouldn't discount it so fast, especially if you want to do any mobile apps. I'm trying to decide to use it or IBLite that comes with Pro on my next app since I want to support mobile.

     

    You can use Devart UniDac (commercial), or Zeos Database components (Open Source) for Database access with the community edition as long as your not making >5K annually from it. Both allow you to connect to many Databases.

     

    Firebird is a favorite of many Delphi developers, and has a client/server but also what is considered an embedded version. You just distribute a few files with your exe. This works well for small hobbyist apps. Firebird is actively supported. I used it in my last 2 small apps that will run from a USB drive.

     

    Another option is an older Database, "Advantage". SAP discontinued support a few years back at version 12, but the source is still available. It allowed you to use the local (embedded) version with up to 5 users before having to purchase the client/server version. It only works on Windows, but you just deploy 2 dll's minimum. The good thing with it is it has it's own data access components, just like the FD ones you just used. It has it's own GUI for creating and testing your databases. I just installed it on Delphi 12 and it still works just fine.

     

     

     

     


  13. @ColumboYour 2 hours ahead I'm in California

     

    You definitely need to figure out the SQL. If the tool you use doesn't let you test SQL statements, try DB Browser for SQLite (sqlitebrowser.org) Free/Donate.

    Now that you know it works with the table, you can try experimenting in the FDQuery editor. Right click FDQuery select Query Editor, enter your SQL and press Execute. 

    The Delphi sample data retrieves the employees table with any of these 3 statements:

    SELECT * FROM employees

    SELECT * FROM 'employees'

    SELECT * FROM 'employees'; 

    Can't help but think your table name being all uppercase is the problem. Try putting it in single quotes like above. I don't use SQLite so maybe someone else knows the problem for sure.

     

    Cool thing about Delphi is there is always "more than one way to skin a cat". In the Object Inspector for the Table set the Filter property to hyear = '1942', you only need the quotes around 1942 if it's a string, if the field is a number their are not needed, and the Filtered property to true.

    DB Browser.png


  14. If the Active property is checked as true your good!!!

     

    You can try hooking up a DBGrid just to give yourself an extra boost. Drop a TDataSource on the form, set it's DataSet property to your table. Now a DBGrid and set it's DataSource property to the DataSource. If the Table is active you'll see the data


  15. You can also try adding a FDTable instead of a FDQuery. Drop it on the form, make sure it's connection property is set to your connection, make sure the connection is set to connected. With the FDTable selected, In the object inspector  look for the TableName property. There will be a dropdown listing all tables in the DataBase. Select your table, then set the FDTable Active property to true. If no errors you are connected


  16. Yahoo! So no problem connecting. Now on to the Query. Make sure the connection property of the FDQuery Component is set to your connection then right click and select Query editor, enter your SQL statement. See my previous image. Then click Execute. What happens?

×