Jump to content

Pat Foley

Members
  • Content Count

    432
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Pat Foley


  1. /*----In EventModule---*/
    	  
        Edits: Tlist<TtextPair>;
    	  
    	  // business logic here 
    
    	  
    	/*----elsewhere in UI realm--*/
    	
            EB.Edits.add(TtextPair.create(uf.Edit2,uf.lbleditErrors));
            //uf ~ TForm

       //source Remu Lebeau response https://stackoverflow.com/questions/64145742/cannot-change-tedit-text-in-delphi.

      TtextPair = Tpair<TComponent, TComponent>; //edit
     

     

    Timer scans the cached edits length and does stuff. 

     

    OT I been running some JS thanks for those posts on TMS and TypeScript.       
        

    • Like 1

  2. Looks like a good start 🙂

     

    Here's my stab at it.  I viewed some JavaScript source and looked at the shader code in older Emba' blog article.  What is your target and what video card... That is your business.  Another approach is taking aircraft ground school classes about 5/8 weather plus the instructor can provide a flight to point what various clouds look like. 

     

    This has Southern Oscillation Index SOI plus NOI drawn on the bitmap. Remember spherical triangle angles add to more than Euclidean triangle.        

    patGlobe.png


  3. var  Sform, RForm: TfrmView;
    
    procedure TfrmMain.btnPutMemoClick(Sender: TObject);
    begin
      TfrmView.ianShowMessage(SForm, Messages.Lines, Formclick);
      LogForm(Sender);
    end;
    
    procedure TfrmMain.btnPutListClick(Sender: TObject);
    begin
      TfrmView.ianShowMessage(RForm, listbox1.Items, LogForm);
    end;
    
    ///    showmessage only
    procedure TfrmMain.Button2Click(Sender: TObject);
    begin
      TfrmView.ianShowMessage(RForm, listbox1.Items, nil);
    end;
    
    ///   singleton
    procedure TfrmMain.Button4Click(Sender: TObject);
    begin
      TfrmView.ianShowMessageSI(Messages.Lines,button3click)
    end;

       I noticed that prefacing var for the form argument helps out.  This code also shows a "callback" being passed,

       Adding a FMX style list box and a que should make nice media player.

             

     

    class procedure TfrmView.ianShowMessage(var auxForm: TfrmView;
                                     Strs: TStrings; CallBacK: TnotifyEvent);
    begin
      if not assigned(callBack) then
         begin
          ShowMessage(Strs.text + #13#10);
          exit;
        end;
    
      if not assigned(auxForm) then
        begin
          auxForm := TfrmView.Create(Application); //
          auxform.cursor := crCross;
          auxform.Button1.onClick := CallBack;
        end;
    
      with auxForm do
        begin
          Memo1.Lines.SetStrings(Strs);
          {
            Enhanced ShowMessage gives console operators a 'log view'
             case
               xxx: sms Ian please open old DB for
               xxx: note this report only covers today
               xxx: note that xxxx again
               xxx: Showmodal;
              }
          Show;
        end;
    end;
    
    var SMlogger: TfrmView;
    class procedure TfrmView.ianShowMessageSI(Strs: TStrings;
      CallBacK: TnotifyEvent);
    begin
      ianShowMessage(SMlogger, Strs, CallBacK);
    end;

      


  4. On paper.

    draw a line Left to right on middle You cut your troubles in half.

    draw a line Top to bottom down the center you made a quadrant. 

    draw circle holding pencil with smaller fingers put thumbnail at 0.0 and rotate paper with other hand. 

    draw in the 45's 30's 60s.  gets you one full sized circle. 

     

    Rotate the paper on edge to "transform" it to side view. Notice how original circle flattens to be as thin as a shadow.  You should be able to make your own procedures! Once you get the fundamentals down on paper. 🙂         

       

     


  5. consider Pi~22/7

     Let the circumference of circle ~  2 * 22/7 

    'Convert quarter turn to degree 0.25 round * 44/7   ::  0.25 round    360 degree/1 round = 

     

    ' Cross out 0.25 round/1 * 360 degree/1 round = 90 degree  

     

    'Do same transformation on spin axis. 

     

    'Either use law of tangents 13th century spherical triangle work or the newer haversine 1835 to plot x,y I know only a few magic triangles (1,1,sqt(2) = gives 45)   (1, sqt(3), 2 = 30,60) to give you a start.      

     

    sqt(2) /2 ~ .707x .707y  Draw out on paper each quadrant to determine signs.      

     

     

     

     

     

     

        

    USpress.png


  6.  

    On 10/23/2022 at 2:43 PM, Pat Foley said:

    RotateBitmapRads(image1.Picture.Bitmap,2/57, False true, Self.Color);

    That will center it.  Darby has examples like this at his DelphiforFun site.   you try Ansus Johnsons Image32 for newer methods.  

     

    Image of FMX

    FMXed.png


  7. 1 hour ago, Kurt G said:

    Yes, but it's in FMX and I have a hard time doing without the VCL panel at the top

    Ok FMX has TControls where in VCL windows has TgraphicControls no windows handle and TWinControls. In short FMX controls don't work in VCL. 

     

    To show palette on menu right click on menu and select components.

     

    To install a control into the VCL Palette be in 32 bit mode the IDE is 32 bit and needs any component to be 32 bit and to be made into a DCP so that control can used in the IDE.  It's easy to stick the IDE if control is not well tested.  You could load one control into the dslusr.bpl to get a feel for operation. Under component install existing and select dslusr.bpl. Save the projectgroup somewhere. 

     

    Here's some code to try until you get that package loaded.

    procedure RotateBitmapRads(Bmp: TBitmap; Rads: Single; AdjustSize: Boolean;
      BkColor: TColor = clNone);
    var
      C: Single;
      S: Single;
      Tmp: TBitmap;
      OffsetX: Single;
      OffsetY: Single;
      Points: array[0..2] of TPoint;
    begin
      C := Cos(Rads);
      S := Sin(Rads);
      Tmp := TBitmap.Create;
      try
        Tmp.TransparentColor := Bmp.TransparentColor;
        Tmp.TransparentMode := Bmp.TransparentMode;
        Tmp.Transparent := Bmp.Transparent;
        Tmp.Canvas.Brush.Color := BkColor;
        if AdjustSize then
        begin
          Tmp.Width := Round(Bmp.Width * Abs(C) + Bmp.Height * Abs(S));
          Tmp.Height := Round(Bmp.Width * Abs(S) + Bmp.Height * Abs(C));
          OffsetX := (Tmp.Width - Bmp.Width * C + Bmp.Height * S) / 2;
          OffsetY := (Tmp.Height - Bmp.Width * S - Bmp.Height * C) / 2;
        end
        else
        begin
          Tmp.Width := Bmp.Width;
          Tmp.Height := Bmp.Height;
          OffsetX := (Bmp.Width - Bmp.Width * C + Bmp.Height * S) / 2;
          OffsetY := (Bmp.Height - Bmp.Width * S - Bmp.Height * C) / 2;
        end;
        Points[0].X := Round(OffsetX);
        Points[0].Y := Round(OffsetY);
        Points[1].X := Round(OffsetX + Bmp.Width * C);
        Points[1].Y := Round(OffsetY + Bmp.Width * S);
        Points[2].X := Round(OffsetX - Bmp.Height * S);
        Points[2].Y := Round(OffsetY + Bmp.Height * C);
        PlgBlt(Tmp.Canvas.Handle, Points, Bmp.Canvas.Handle, 0, 0, Bmp.Width,
          Bmp.Height, 0, 0, 0);
        Bmp.Assign(Tmp);
      finally
        Tmp.Free;
      end;
    end;
    
    procedure TForm20.Button1Click(Sender: TObject);
    begin
      RotateBitmapRads(image1.Picture.Bitmap,2/57,true, Self.Color);
    end;

     

     

     

     

     

       

     

     

    • Thanks 1

  8. Since FMX is multi-device platform Windows specific rotation schemes are not usable.  

    You simply use the rotation angle in the object inspector.

     

    In samples there's some animation examples that should be helpful. 

     

    procedure TForm19.Button1Click(Sender: TObject);
    var
      btn : TButton;
    begin
      btn := Sender as TButton;
      with btn do RotationAngle := RotationAngle + 2;
    
      btn.Position.X := Width / 2 - btn.Width / 2;   //workaround the rotationcenter business
      btn.Position.Y := Height / 2 - btn.Height / 2;
    end;

     


  9. 20 minutes ago, Vandrovnik said:

    Sin and Cos in Delphi take argument in radians (not in degrees).

    Important to know. as is the unit circle!  

     

    But let's not use theta or alpha Greek for angle today.

     

    The first argument is x offset set it to Width div 2

    Second argument is y offset set it to Height div 2

    third and fourth arguments if the same draw a circle otherwise draws ellipse 

     Canvas.Ellipse(100,100,50,75);


  10. 2 hours ago, PeterBelow said:

    Mh, never had a problem with those, but my projects are small to medium since i'm retired and use no 3rd party controls.

    You can still use CPU view to get 'the iron' as the Late Danny Thorpe would say.  

     

    This stuck my f7 and f8 Keying in CPU view stepping through Tee chart update without source.
     

     000000000040C1E5 F3AA             rep stosb 
    :000000000040C1E5 @FillChar + $105

    F9 rolls over it


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

      

     


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


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


  14.  

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

     


  15. 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;

  16. 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;

     


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


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


  19. 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;

     


  20. 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}  
    
          ...

     

×