Jump to content

Alberto Fornés

Members
  • Content Count

    47
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Alberto Fornés


  1. 17 hours ago, JGMS said:

    Thanks for your reply @KoRif,

    I found out that my (VCL) programs use the installed version on the target machine, rather than the embedded version of Python in the program. The debug-version of the executable showed errors that libraries were missing. These libraries were included in the side-packages subfolder associated with the executable, but were absent in the Python folder of the machine. Apparently, there is no embedding!

    Thus the question remains: what do I wrong? I use the following code for the creation of the Python form:

     

    
    procedure TPyForm.FormCreate(Sender: TObject);
    begin
      MaskFPUExceptions(True);
      PythonEngine1              := TPythonEngine.Create(PyForm);
      PythonEngine1.RegVersion   := '3.10';
      PythonEngine1.DllName      := 'python310.dll';
      PythonEngine1.AutoLoad     := false;
      PythonEngine1.AutoFinalize := true;
      PythonEngine1.AutoUnload   := true;
      PythonEngine1.UseLastKnownVersion := false;
      PythonEngine1.RedirectIO   := false;
      PythonEngine1.loadDLL; 
      PyEmbeddedResEnvironment3101.pythonEngine := PythonEngine1;
      PyEmbeddedResEnvironment3101.Autoload     := True;
    end;

    When the project is compiled the folder 3.10 is created or updated, with all required libraries in it.

    An installation program copies everything that is needed to the target machine. So far so good, I'd presume.

    What more is needed? Anything specific in the registry settings, like "Environment Variables"?

     

      I don't know about Python, but if I understand correctly : is it possible to make an isolated installation of Python including libraries like matplotlib, pandas, etc and using it from Delphi?. Is it needed any user installation?. Thanks


  2. 11 minutes ago, PeterBelow said:

    What you see is due to rounding errors when scaling individual character widths, these accumulate over the text width. If you want true WYSIWYG display you have to basically place each character individually at positions calculated from the font information. The API offers a large group of functions for this purpose, see Font and Text Functions

    Thanks Peter, I will investigate in that direction. Do you have experience about the speed performance to calculate widths and drawing character individually?


  3. I am rewriting an editor where I am looking to display some text on the screen, to which I can zoom and therefore increase or decrease its size, and ensure that what I display on the screen corresponds to what I get when printing what has been drawn. From what I've been reading, GDI doesn't always respect these relationships in terms of text sizes, although when printing it can display the result well. As I show in tests I've done where I want to draw a 10mm high text, when I double the height to 20mm, the width of the text is not equal to double, as seen in the image. Is there a way to get the ratio to hold and equal to what we get in print, thanks.

     

    GDI_RENDERING_TEXT.thumb.png.4aba5d29cf1861af07c52ae29fa0f70f.png

     

    I use this code to draw the text:

     

    procedure TForm3.Button4Click(Sender: TObject);
    var
     h: integer;
     TextOutSize: TSize;
     NewFont, OldFont: HFont;     // holds the old and new fonts
    begin
     bmp:= TBitmap.Create(Image1.Width,Image1.Height);
     bmp.PixelFormat:= pf32bit;
     try
       bmp.Canvas.Brush.Color:= clWhite;
       bmp.Canvas.Brush.Style:= bsSolid;
       bmp.Canvas.FillRect(Rect(0,0,Image1.Width,Image1.Height));
       bmp.Canvas.Pen.Color:= clSilver;
       d:= 0;
       h:= 0;
       while d<= Image1.Width do
        begin
         if (h = 5) then
          begin
           bmp.Canvas.Pen.Color:= clGray;
           h:= 0;
          end else bmp.Canvas.Pen.Color:= clSilver;
         bmp.Canvas.MoveTo(d,0);
         bmp.Canvas.LineTo(d,Image1.Height);
         Inc(d,10);
         Inc(h);
        end;
       d:= 0;
       h:= 0;
       while d<= Image1.Height do
        begin
         if (h = 5) then
          begin
           bmp.Canvas.Pen.Color:= clGray;
           h:= 0;
          end else bmp.Canvas.Pen.Color:= clSilver;
    
         bmp.Canvas.MoveTo(0,d);
         bmp.Canvas.LineTo(Image1.Width,d);
         Inc(d,10);
         Inc(h);
        end;
       bmp.Canvas.Brush.Style:= bsClear;
       bmp.Canvas.Font.Color:= clBlack;
    
       SetMapMode(bmp.Canvas.Handle,MM_ISOTROPIC);
       SetViewportExtEx(bmp.Canvas.Handle,Image1.Width,Image1.Height,0);
       SetWindowExtEx(bmp.Canvas.Handle,Round(Image1.Width * 25.4 / GetDeviceCaps(bmp.Canvas.Handle, LOGPIXELSX)),Round(Image1.Height * 25.4 / GetDeviceCaps(bmp.Canvas.Handle, LOGPIXELSY)),0);
    
       // Create a 10 mm font 
       NewFont:= CreateFont(10, 0, 0, 0, FW_NORMAL, 0, 0, 0,
                               DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH or
                               FF_DONTCARE, 'Arial');
       OldFont := SelectObject(bmp.Canvas.Handle, NewFont);
    
       bmp.Canvas.Pen.Width:= 0;
       bmp.Canvas.Pen.Color:= clBlue;
    
       TextOut(bmp.Canvas.Handle,0,10,txt, Length(txt));
       MoveToEx(bmp.Canvas.Handle,0,10,nil);
       LineTo(bmp.Canvas.Handle,230,10);
       MoveToEx(bmp.Canvas.Handle,0,20,nil);
       LineTo(bmp.Canvas.Handle,230,20);
    
       GetTextExtentPoint32(bmp.Canvas.Handle, PWideChar(txt), Length(txt), TextOutSize);
    
       TextOut(bmp.Canvas.Handle,230,10,PWideChar('Width: ' + TextOutSize.cx.ToString), Length('Width: ' + TextOutSize.cx.ToString));
    
       SelectObject(bmp.Canvas.Handle, OldFont);
       DeleteObject(NewFont);
    
       //  Create a 20 mm font 
       NewFont:= CreateFont(20, 0, 0, 0, FW_NORMAL, 0, 0, 0,
                               DEFAULT_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH or
                               FF_DONTCARE, 'Arial');
    
       OldFont := SelectObject(bmp.Canvas.Handle, NewFont);
    
       bmp.Canvas.Pen.Width:= 0;
       bmp.Canvas.Pen.Color:= clBlue;
    
       TextOut(bmp.Canvas.Handle,0,30,txt, Length(txt));
       MoveToEx(bmp.Canvas.Handle,0,30,nil);
       LineTo(bmp.Canvas.Handle,230,30);
       MoveToEx(bmp.Canvas.Handle,0,50,nil);
       LineTo(bmp.Canvas.Handle,230,50);
    
       GetTextExtentPoint32(bmp.Canvas.Handle, PWideChar(txt), Length(txt), TextOutSize);
    
       TextOut(bmp.Canvas.Handle,230,30,PWideChar('Width: ' + TextOutSize.cx.ToString), Length('Width: ' + TextOutSize.cx.ToString));
    
       SelectObject(bmp.Canvas.Handle, OldFont);
       DeleteObject(NewFont);
    
       Image1.Picture.Assign(bmp);
     finally
      FreeAndNil(bmp);
     end;
    end;

     


  4. Hello, some time ago I thought of making a program that could be used by young programmers and students who need to write a project document and show them the possibilities of programs they could develop with Delphi. I have recently published the program and it is called TICdoc. The program also has a diagram editor and a code editor for saving code snippets that can be tagged for further searches. A project document is generated by uniting various types of sections (functional requirements, table of contents, Gantt charts, use cases, etc). Some of these sections have their own editor and the editable sections have a text editor (html) to which styles (css) can be applied. The program uses a SQLite database. It is free and does not have any usage restrictions. It is signed with an OV certificate, which I know shows some warning when downloading it in the browser.

     

    You can see it at TICdoc  , there is also a youtube channel (currently only in spanish) where you can watch short videos of program features

     

    Small task editor at intro page:

     

    tasks.thumb.png.001413f1bf66adbe26b8b0080bac50b4.png

     

    Code editor to save snippets (SynEdit component):

    code_editor.thumb.png.79638391b16798d6afa7ea9487de6f5f.png

     

    Diagram editor (TMS Diagram Studio), you can insert this diagrams into project document:

    editor_diagram.thumb.png.c00f5ecc067f0277eb644a5b16205afc.png

     

    Document editor (HTML component library):

     

    project_document.thumb.png.1f4294c6633f36deccd4310aa44ac692.png

     

    In the editable section you can insert images, formulas, tables, data-bound tables, editor diagrams or PlantUML diagrams:

    plantuml.thumb.png.66a33d9ba3f385b464e8f26cdd5b14e4.png

     

    By clicking on the active language in the lower bar we can change the language (it is in a json file, so it can be translated into other languages, it is currently in Spanish and English)

    change_language.png.295715df70902e6f4cf121b8400a37cc.png

    • Like 1
    • Thanks 5

  5. 1 hour ago, Lars Fosdal said:

    We create all these in code.  No visual components used.

    We have no sea of DB components floating in designers. It requires a bit more scaffolding code, but it can be generalized and made threadsafe.

    Yes, rapid development is not always the best solution for big projects.


  6. Hello, and thanks for your reply. The python  DLL 3.11 can be loaded because I can run basic scripts, but when try to execute scripts that imports modules like matplotlib, numpy, pandas, etc raises that errors.  I confirm that 3.10.9 runs ok without that errors.


  7. Hello, I have started working with Python4Delphi. I have installed Python 11, and in environment variables is set the path to the python exe folder and the scripts folder. I have installed with pip the modules of the examples of the webminar II of the tutorials (python4delphi/Tutorials/Webinar II at master · pyscripter/python4delphi · GitHub). I can't get to run the scripts without getting errors like: "no module named _ctypes", it's a required module for Pandas. I have also got this error with the unicodedata module, I installed with pip unicodedata2, but it doesn't work either. Any suggestions for things to check?


  8. I have an application developed with Delphi 10.4 where I use the Diamond vcl style. The app shows up fine, but when I run the same code with Delphi Alexandria it shows a strange result.

    The main window when the application starts (the same with Delphi 10.4 and Delpgi Alexandria):

     

    frame_window_1.thumb.png.41cbf3e1585a528bf52ff2dd3ef5b3b8.png

     

    If I open a second form created by code. The result with Delphi 10.4 is this:

    frame_editor_2.thumb.png.fe4c054acdc26e06a5e6e197380ddf51.png

     

    But when open with Delphi Alexandria it shows wrong rendering:

    frame_editor_1.thumb.png.c78a97940a2e74429e5149f63481c7d2.png

    As you can see the border icons have disappeared, after closing the window, the main screen is also displayed wrong with Alexandria:

    frame_window_2.thumb.png.e2394262cb07e6dda9c906a7330837d2.png

     

    Any suggestions of things to check?, thanks

     

    options.thumb.png.4c7c3e38a84352b33b8b9c3345053df0.png


  9. 3 hours ago, Hans J. Ellingsgaard said:

    Is there a reason why you can‘t use generators?

    Really is that there was no reason not to use it, finally it is what I have done and as Anders suggested it solves the problem. Thanks

    3 hours ago, Stano said:

    I don't think logic anymore. What happens if you have the same dates? Are the dates changing?
    The date itself is a unique number. Isn't that enough for you?

    In this case the date did not work because I need also assign a code from that number.

    2 hours ago, Anders Melander said:

    Wrong conclusion. What is more likely? That there is something wrong with transactions or that there is something wrong with what you're doing?

     

    Your method is flawed unless you can guarantee that there will never be more than one transaction active against the database at a time.

    Consider this:

    • A: Start transaction
    • A: select max(NUMBER) returns 1
    • B: Start transaction
    • A: Post new row with NUMBER=2
    • A: Commit
    • B: select max(NUMBER) returns [...drumroll..] 1
    • B: Post new row with NUMBER=2
    • B: Commit

    Like Hans suggested, use a generator. That's what they're there for.

     Thanks Anders, now works without repetitions using a generator.

    • Like 1

  10. Hello, I have a Firebird table (ORDEN) where I need to have a unique numbering in a field depending on the date. In the before insert of the table I define a trigger that basically does this:

     

    SELECT MAX(NUMBER) FROM ORDEN WHERE FECHAINT >= :FECHA INTO :NUM;
    IF (:NUM IS NULL) THEN NUM = 0;
    NUM = :NUM + 1;
    NEW.NUMBER = :NUM;

    Sometimes numbers are repeated in this table, so I deduce that something is wrong in the handling of transactions to cause this error. I work with Firedac, what are the properties of the connection or the write and read transactions supposed to be to avoid this problem?, thanks


  11. 36 minutes ago, borni69 said:

    Thanks, I can create it in a datamodule, but I still do not understand howto get this datamodule all the way down to the controller..

     

    FMVC.AddController(TCustomersController);

     

    Tcustomercontroller is a class created on request  ,and the dict is created at startup.

     

    I undestand that I can use/create a datamodule in the controller, but not howto use one created at startup, holding all the data,, normally I would send the dict to my class using a variable.

    
    procedure TMyController.GetCustomers ;
      var 
       lCustomersModule : TMyDataModule ; 
        begin 
         lCustomersModule := TMyDataModule . Create ( nil ) ; 
          try 
           lCustomersModule . QryCustomers . Open () ; 

     

    again thanks

     

      I will also try a few options myself...

    No , this datamodule should be created at start, and always alive, you reference it from your controller (add datamodule unit to controller), and access it through TMultiReadExclusiveWriteSynchronizer.


  12. Maybe if you don't have the human resources and / or time to do a good test and find bugs before releasing the product, and you hope that the customers will find and report them, maybe Embarcadero could offer that version at a lower price and establish a more honest relationship.

    • Like 3

  13. Finally I found how to solve the problem on the computer that was failing (only 24 days have passed!). Unchecking this option (in beta) from the regional settings. Does anyone know how the system identifies that a program is unicode or not? 

     

     

    check_utf8_beta_3.png


  14. 8 hours ago, Kas Ob. said:

    Don't have an answer, but some thoughts here

     

    1) You control these two devices, so why not log the problem input then compare, just log i,c and bd , this should give you a great insight.

    2) Where did the data come from ? is it same DB or by mistake you have two different DB, compare the source.

    3) "bd value is not the same in Delphi 10.3 as in Delphi 10.4" is not enough, does bd have meaningful data or something unreadable ? are bd value is from different fields ?

     

    Hope that helps.

     

     Hello Kas Ob, thanks for you reply. As I said in second message the problem is not related to Delphi version, is related to computer where I execute the program. The DB is the same, I attach a small demo with the esential part of code where I can verify the error. When I open the program a TFDMemTable with different fields defined is open, I add a record with some values and use the add image button to load a blob field (in this case bitmap image included in sample code, that you can see on picture) :

     

    create_table.thumb.png.c3759d8bc686b15e7d3df47807d20af0.png

     

     When Save Table button is pushed the data and some table metadata is used to fill a stream that can be saved in a file, although you can use de load table button to fill a second TFDMemTable with this stream, and assign the dataource to this dataset, in this case and in a certain computer the image is not readed correctly (in other blob cases this is an error):

     

    load_table.thumb.png.551b33e5fed7ab2f54a29e2da0119a06.png

     

     If you want to load the stream from saved file, push load stream button and then load table). The same program in other computer (it doesn't matter Delphi 10.3 or Delphi 10.4) works well, so I think it's a pc configuration that I can't guess.

     

    Stream_Sample_2.zip


  15.     I expand the information, doing more tests I have verified that it is not a problem associated with Delphi 10.3 vs Delphi 10.4, I made that statement because I have two computers, one with Delphi Rio and the other with Delphi Sydney, but installing Delphi 10.3 on the other computer I have verified that the problem is due to the computer (Windows 10 in both cases). Any suggestions on any pc configuration that might motivate this? 


  16.      Hello, in a data exchange between vcl clients and a REST server, I have implemented a method to save the data in a stream, that stream I send to the client and it loads the data in a reverse process. I do this to reduce the information to be sent as much as possible and I do not directly use a SaveToStream of the table, query or stored procedure. The information of the fields I read from the IFDDataSetReference interface, and I have a problem when saving the blob fields, the procedure worked with Delphi 10.3 but with Delphi 10.4 there is something different that I cannot guess (I have a professional version and I do not have access to the FireDac code ) . The abbreviated code for the procedure is: 

     

    //iData = IFDDataSetReference
    //FieldData = array of Fields
    ab: TArray<Byte>;
    bd: AnsiString;
    nl: Int64;
    
    var ADest:= TMemoryStream.Create;
    var wr:= TBinaryWriter.Create(ADest,TEncoding.UTF8,false);
     for i:= 0 to iData.DataView.Rows.Count - 1 do
      begin
       for c:= Low(FieldData) to High(FieldData) do
        begin
         //when blob field I do this
          begin
           //ValueI is a variant
           bd:= iData.DataView.Rows[i].ValueI[c]; //bd value is not the same in Delphi 10.3 as in Delphi 10.4
           ab:= TEncoding.ANSI.GetBytes(bd);
           nl:= Length(ab);
           wr.Write(nl);
           wr.Write(ab);
          end;
        end;  
      end;

     

    In client side I can read de stream with:

     

    ADest: TFDMemTable;
    
    nl:= sR.ReadInt64;
    if (nl = 0) then
     begin
      ADest.Fields[c].AsBytes:= nil;
     end else
     begin
      ADest.Fields[c].AsBytes:= sR.ReadBytes(nl);
     end; 

     


  17. 12 hours ago, Remy Lebeau said:

    No, they are not.  All you really need is Disconnect(), or at least Socket.Close() if closing the socket from another thread.

    That is not an Indy error message, or any OS error message I have ever seen.  So I am assuming you mean it is coming from the Barcoder Reader or Ethernet base (what is that supposed to be?) instead.  Does the reader/base only allow 1 connection at a time?  If you just yank out the network cable, it won't matter what you do on the client side, the connection will be lost on the server side and it will need time to process that loss, which may take awhile, depending on the server's implementation.

    Disconnect()/Close() will perform a graceful disconnect (send a FIN packet to notify the peer that the connection is being closed intentionally).  That should allow the reader/base to free up the used slot immediately.

     

    However, it won't matter what you do in the case of the connection being lost abnormally, like from a network outage.  All you can do in that case is wait for the reader/base to handle the loss on its end in its own time to make the slot available again.

     Thanks Remy, your words are greatly appreciated on this topic. That's right, the host only accepts one connection, and the message is sent by it. I will find a way to close the connection (maybe restart the device) so that I can connect again.


  18.          Hello, I have created a thread where there is a TIdTCPClient component that receives readings from a barcode reader connected through an ethernet base. The goal is for you to be in a connected service all day without stopping. The thread works, I can start and stop it several times, when I stop the thread I execute these steps to close the connection (FClient = TIdTCPClient):
     

    FClient.IOHandler.InputBuffer.Clear;
    FClient.IOHandler.CloseGracefully;
    FClient.Disconnect;
    FClient.Socket.Close;

     

           I don't know if they are all necessary, but I have tried to get the desired result. To test, I need to achieve a reconnection when a network failure is detected (for this I disconnect the cable from the pc), when I detect an error in the reading:


     

    try
     FData: = FClient.IOHandler.ReadLn;
    except on E: Exception do begin
     FClient.IOHandler.InputBuffer.Clear;
     FClient.IOHandler.CloseGracefully;
     FClient.Disconnect;
     FClient.Socket.Close;
     // Terminate thread
    end;

     

    In this second case, when I try to connect again, I get this message from the base: This channel is already in use, no slot is available. It seems that the old host-port socket remains active: how can I ensure that it is closed?


  19. On 1/28/2021 at 10:27 PM, Darian Miller said:

     

    On a diversionary whim, I tried installing 10.4 on XP and the installer presented a fatal error "This program does not support the version of Windows your computer is running."  I imagine you have to unpack, tweak the installer package, and then rebuild it to get it to work on XP, correct?

     

    On 3/11/2021 at 8:41 AM, dummzeuch said:

    I know that XE3 works fine on Windows XP.

     

    I started this topic to find out which was the last version that did. (Which does not mean that it's officially supported. So the documentation doesn't mean much unless it states a technical reason.)

     

    I'm still not sure that 10.2 doesn't work at all, it might still be an installation issue. Since the web page URL contains the word "tamper" it could be that it "detected" something in the installation it didn't like. The web page, that does not (no longer?) exist, might have contained information on the specific issue (but probably didn't).

     

    On the other hand ...

    ... that would mean a definite no.

     

    But then, there is:

     

      Hello, sorry for delay to respond, I was talking about executables generated with Delphi 10.3, not about installing Delphi 10.3 in a XP computer. I'm able to run the programs, except the problem with themes in some contros, as datatimepicker so I need to disable theme for that controls.


  20. 9 hours ago, Anders Melander said:

    Why do you think that?

    Years ago I was testing various possibilities to display points, lines, polygons, etc. on a map, with various libraries and OpenGL was the one who did it the fastest, perhaps showing text found worse performance.

×