Jump to content

Pat Foley

Members
  • Content Count

    367
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Pat Foley


  1. I never had good luck with Frames...  With custom component development the issue is the IDE needs a restart after an "improvement" to the control.  Or uninstall the control and reinstall once you have a project group set up. to rebuild the control. 

     

    In the IDE control X and control V the control to reflect the improvements. 

     

    For a complex control I simply use a form that keeps all the controls events assigned.  By wrapping the form create with owner and parent and Event arguments the "Parent form" is not added to uses clause.  

    rule 1 Do not use ShowModal that is the only danger I have found.

        constructor NewAux(const aName:string; bossForm: TForm;
                          APanel: TWinControl; aEM: TEventBoss;
                                            Headings: Tstrings;
                                          aClick: TnotifyEvent; 
                              Settings: TWindowFormSettingSet);

     

    Example code.

      

     


  2. 2 hours ago, dkjMusic said:

    Pat, I have  FamilyCurve.ClickableLine := False;  for each line series.

    Could you set all the Teecharts.visible to False, then measure the effects of showing each Teechart in Runtime. Or switch the data source in IDE and measure that to determine if data is being cached in the IDE.  You could use a client data set to help cache the data into the executable, so you don't need to reload.   


  3. If the runtime chart has clickable points perhaps its binding them at runtime.  I run 6 Teecharts with 6 to 8 Lines 400 points or more plus legend updating with latency ~ 5ms. 

     

    What's interesting for a real time teechart when made visible, the memory size as the app increases to 1.5 megs 32bit and to 3 megs for 64 bit so 6 Teecharts if each is shown increase a 12 meg program to 40 ish. So there must be some lazy loading of UI parts going on.   On win11 the app reported size shrinks in twenty or so minutes.


  4.  

    Serge_G listbox coding is very nice example.  Serge's "Introduction to FireMonkey XE4 Styles" is good start about differences between FMX and VCL and in text!  His A.F.R.O may help you with the disappearing.  

     

    Here's a one liner that brings up the opendialog and returns the directory or folder selected. 

       if not SelectDirectory('Dirs, Folders','', FilePath) then exit;
        DirArray := TDirectory.GetFiles(FilePath,'*.*',TSearchOption.soTopDirectoryOnly);
        ...

     


  5. On 9/25/2022 at 1:28 PM, Pat Foley said:

    FMX does have TListView. 

    So discard old ListBox and use TListView component.  

    Also add a memo1 and this 

    procedure TForm9.ListView1Change(Sender: TObject);
    var
      fn: string;
    begin
      fn := Listview1.items[ListView1.ItemIndex].Text;
      if Pos('.txt',Fn) > 0 then
         memo1.Lines.LoadFromFile(fn);
    end;

  6. Sorry about that I had a showmessage('') in my test letting the code call itself.     Plus split out the if tests to reflect the condition and the !.   

    procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin 
      //
      CanClose := enlightenedCanClose;
      SendMessage(Handle, EM_SETMODIFY, WPARAM(True), 0); //or have a MS product open that needs saved 
      // 
      if not CanClose then 
      begin
        
    	if (GetSystemMetrics (SM_SHUTTINGDOWN) > 0) and 
    	{not} dmC.DBC1.Connected
           	then 
    	      closeDB('Workstation shut down');  // app is being closed by workstation shutdown
        
    	if dmC.DBC1.Connected then closeDB('DB still Open?');   
    	 
    	
    	enlightenedCanClose := True;
    	
        //Close;
      end;
    end;

     


  7. const
    DBcommandstrs = ('Workstation shut down', 'Auto Close');
    //  i :=   IndexText('Workstation shut down', DBcommandstrs);
    
    
    var  enlightenedCanClose: Boolean = False;
    
    // called by timer 
    procedure autocloseWorkStationSession(Sender: Tobject);
    begin
      if Time > 17/24 then
      begin
        CloseDB('Auto Close');
    	//Close;
      end;
    end;
    
    
    
    procedure CloseDB(const ditto: string);
    
    var
      TS: TTimeSpan;
      StartDateTime, FinishDateTime: TDateTime;
      lUsersLogWritten: Boolean;
    
      if dmC.DBC1.Connected then
      begin
      
    {$IF  Defined(ELogging) or Defined(Codesite)}
        LogMessage(IndexText[0]);
        LogMessage('DBC1 is connected att.');
    {$ENDIF}
        //
    	////' check savepoints or cache status?
        CancelEditsInsertsInDatamodules;
        CancelEditsInsertsInOpenForms;
        //end;
        //
        ///CloseOpenForms; ///Pat says Boo!
        //
        dmC.DBC1.CloseDataSets;
        //
        dmC.UsersLog.IndexName := 'SessionKey';
        dmC.UsersLog.Open;
        //
        if dmC.UsersLog.FindKey([sSessionKey]) then
        begin
          dmC.UsersLog.Edit;
          //
          //case iTerminateAction of
          dmC.UsersLog.FieldByName('Action').AsString := ditto;
          dmC.UsersLog.FieldByName('FinishDateTime').AsDateTime := now;
          StartDateTime := dmC.UsersLog.FieldByName('StartDateTime').AsDateTime;
          FinishDateTime := dmC.UsersLog.FieldByName('FinishDateTime').AsDateTime;
          TS := TTimeSpan.Subtract(FinishDateTime, StartDateTime);
          dmC.UsersLog.FieldByName('Duration').AsString := Format('%.3d:%.2d:%.2d:%.2d', [TS.Days, TS.Hours, TS.Minutes, TS.Seconds]);
          dmC.UsersLog.Post;
          //
          lUsersLogWritten := True;
          //
        end;
      //
      dmC.UsersLog.Close;
      //
      DBWReg.WriteString('Session Key', 'DBiWorkflow', '');
      //
      dmC.DBC1.Close;
      dmC.DBS1.Close;
      dmC.DBE1.Close;
      //
      if iTerminateAction = 0 then
      begin
        //
        if not lUsersLogWritten then
          TaskMessageDlg('Workflow Closing error!', 'Note:- The Users Log was NOT updated.  Workflow will now close..', mtError, [mbOK], 0);
        //
      end;
      enlightenedCanClose := True;
      close;
    end;
    
    
    procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    begin 
      //
      CanClose := enlightenedCanClose;
      SendMessage(Handle, EM_SETMODIFY, WPARAM(True), 0); //or have a MS product open that needs saved 
      // 
      if not CanClose then 
      begin
        if (GetSystemMetrics (SM_SHUTTINGDOWN) > 0)
           and not dmC.DBC1.Connected	then 
    	      closeDB('Workstation shut down');  // app is being closed by workstation shutdown
        
    	enlightenedCanClose := True;
        Close;
      end;
    end;

    That should work in Win11. (In fair weather 🙂 )   

    Pat


  8. There may be a CommandType to select what the commandText does with its string. 

     

    I would use SQL perhaps to check if the newusername is already used ("spoken for" as we say here), then do the insert.  But that may be the crew in charge of new user account to check for duplicate users.  


  9. 11 hours ago, Rrodd said:

    one white and another with the inverted color (this is the only I want to be drawn), looking bad.

     

    Overdraw the control.    Here's two workarounds. The second uses the centering text of Panel.caption. 

     

     

    procedure ComputeBarCenter(control: TControl; var x, y : Integer);
    begin
      with Control do begin
        x := Left + width div 2;
        y := Top + Height div 2;
      end;
      //self.Left := 10;
    end;
    
    
    procedure TForm9.Button1Click(Sender: TObject);
    var
      textX, textY: Integer;
    begin
      gauge1.ShowText := False;
      computeBarcenter(gauge1, textX, textY);
      self.Canvas.TextOut(textX-5,textY-3,'50%');
    end;
    
    procedure PutlabelControlAroundGraphic(panel, graphic: TControl);
    begin
      with graphic do
      panel.SetBounds(Left-3, Top-3, Width+3, Height+3);
    end;
    
    procedure TForm9.Button2Click(Sender: TObject);
    begin
      Gauge2.ShowText := False;
      panel1.Caption := 'Working hard Boss';
      PutLabelControlAroundGraphic(panel1, Gauge2);
    end;

     


  10. So with (48 - 1) half hour INTERVALS in each day using Combos do this 
    
    
    
             comboBoxStart.items.add(00:00)
    
            ...
    
            comboBoxStart.items.add(12:00)
    
            ...
    
           comboxBoxstart.items.add(23:30)
    
          comboxBoxStart.items.add('Tomorrow');
    
    
           
    
         or 
    
          comboboxStart.items.add('yesterday')
    
          comboBoxStart.items.add(00:30)
    
            ...
    
           comboBoxStart.items.add(12:00)
    
            ...
    
           comboxBoxstart.items.add(24:00)
    
    
    
    Do same for comboBoxStop 
    
           ...
            
    
          StartHour :=  (combobox.selectedIndex / (24 * 2)) * 1{full day fraction that is 48/48}  
    
          ...

     


  11. FMX does have TListView.   

    procedure TForm9.Button1Click(Sender: TObject);
    var
      Lvi : TListViewItem;
      I : Integer;
      DirArray : TStringDynArray;
    begin
      Lvi := ListView1.Items.Add;
      Lvi.Text := 'Hello';
      Lvi := ListView1.Items.Add;
      Lvi.Text := 'FMX';
      Lvi := ListView1.Items.Add;
    
      Lvi.Text := Tdirectory.GetCurrentDirectory;
      DirArray := TDirectory.GetFiles(Lvi.Text);
      var Filename: string;
      for I := 0 to High(DirArray) do
      begin
        Filename := DirArray[I];
        Lvi := ListView1.Items.Add;
        Lvi.Text := fileName;
      end;
    end;

     


  12. The clues did not include that Memo1.Lines  equates  to crL: StringList  using ctL[0] for caption.  The ctL.commatext is used for the subitems. 

    again viewstyle is vsReport set with F11 object injector.  

      


  13. 33 minutes ago, robertjohns said:

    Need to add these 2 Memo lines into Listview

     

    Listview Caption = Memo1 lines

    Listview SubItem = Memo2 lines

    Be sure View is report 

     

    Here's 11.1 vintage clues on a project I am working on Allistair has a video on strUtils that showed similar stuff. 

    procedure TForm3.Button3Click(Sender: TObject);
    var
      tvCol: TListColumn;
      Vi: TListView;
      li: TListItem;
    begin
      var
      SL := TStringList.Create;
      var
      ctL := TStringList.Create;
      SL.LoadFromFile('Logger11.csv');
      LV.Clear;
      for var R := 0 to SL.Count - 1 do
      begin
        ctL.CommaText := SL.Strings[R];
    
        if R = 0 then
          for var K := 0 to ctL.Count - 1 do
          begin
            tvCol := LV.Columns.add;
            tvCol.Caption := ctL[K];
            tvCol.Width := 120;
          end
    
        else
          begin
            li := LV.items.add;
            li.Caption := ctL[0];
            ctL.Delete(0);
            li.SubItems.CommaText := (ctL.CommaText);
          end;
      end;
      SL.Free;
      ctL.Free;
    
    end;

     


  14. On 9/20/2022 at 5:22 AM, David Schwartz said:

    The bottom-line is ... Management sticks with what they know.

     

    "No one ever got fired" for buying IBM was an adage from 80's when trying to sell a local solution.  I spent most of my life operating machines at small power plant.  Only during blackouts operators discussed restart. Otherwise it was being a snipe (swiper of bilge tanks) on Navy flagship.  I was able to get "insight" into how the thing worked by using excel models.  Later I developed an EAP not Employee Assistance Program but an Emergency Action Plan when at beginning of each shift discussing the actions to do when something happened to avoid blackout or injury. Which didn't sell to Manager who mentioned "many operators uncomfortable running in manual."  I been working on generic simulator, using Delphi coding to build app with scenarios passing on how to handle events system wide or locally.   

     

    The Delphi maintenance fee is like buying insurance to keep the language current to new advances and maintain good will by promoting Delphi.  

     

    I am thinking to buy TMS web core and try on both D and L

     

    MSEdge has some tools to help Lazarus JSscript builds.  This is debugging the  Asyncdemo in Lazarus pastojs/Demos. Invoked by simply right clicking in browser F12 helps. 

        

    UsingMSEdge.png


  15. The idea is code in English, then use Tool tip comment in local dialect as mnemonic.

     

    /// <summary>
    ///  ateB + aplA = ammaG
    /// </summary>
    procedure TForm18.AddABtoC;
    begin
      var a := 1;
      var b := 2;
      var c := -1;
      c := a + b;
    end;

     


  16. 54 minutes ago, KMarb said:

    I know that is not proper design, and that anything that makes the UI unresponsive should be run outside the main thread,

    The UI needs to communicate that the program is computing or updating... In the past the mouse cursor was changed to hour glass and spinner is used in Android.   MS XL and Edge use spinners why wouldn't you?

     

    The following completes the for..loop emulation and set timer1.interval to 200. 

     

    //   if FthinkerIndex = 0 then
    //   with timer1 do Enabled := not Enabled;

     

    the Example needed a button click to break out of loop.    

     

     

     


  17. 5 minutes ago, KMarb said:

    Can you elaborate and explain how a timer fits in with this loop, to make the label update every .2 seconds?

    The timer events allow the UI to update. The for loop cannot without Application.Processmessages inside the loop.  Plus using a sleep is a reason not to use a loop.   

×