Jump to content

Kryvich

Members
  • Content Count

    402
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by Kryvich


  1. @Rollo62 Nothing will change. Delphi allows implicit conversions between different types spawned from one common type (String, Integer, Double etc.). 

     

    In fact, I wrote about this even 10 years (or so) ago in the old Delphi.Non-Tech forum. Unfortunately, no new warnings or compiler hints have been added since.

     

    Strong typing worth nothing while we can write it as

    miles := meters * Pi + Application.MainForm.Width;
    // Another example with a comparison
    miles := TDistanceMiles(100);
    meters := TDistanceMeters(100);
    if miles = meters then
      ShowMessage('Hi, it is your compiler!');

    without any warning or hint from the compiler.


  2. Slides 74-76. Strongly-Typed Pascal !!! 

    Someone in Embarcadero should hear programmers request and help to make the implicit explicit in such situations:

    program TestMetersToMiles;
    {$APPTYPE CONSOLE}
    type
      TDistanceMeters = type Double;
      TDistanceMiles = type Double;
    
    function ConvertMetersToMiles(Distance: TDistanceMeters): TDistanceMiles;
    begin
      Result := TDistanceMiles(Double(Distance) / 100000 * 62.14);
    end;
    
    var
      meters: TDistanceMeters;
      miles: TDistanceMiles;
    begin
      miles := 100; // No syntax error, no warning, no hint
      meters := ConvertMetersToMiles(miles); // No syntax error, no warning, no hint
    end.

    I've complained already about this here.


  3. Regarding the naming of units. It makes sense to name a unit like this: ProjectName.UnitName.pas. ProjectName can be the abbreviated name of your project. And if the project is really big (like Delphi) - add the name of the subproject instead, for ex.: System.Types, Vcl.Forms, FMX.Forms etc. An even Subproject.Subproject.UnitName.pas: FMX.Forms.Border.pas, FMX.ListView.Appearances.pas... 


  4. Each of us was in such a situation. See, this is a ready-made working example. You can use it as a basis:

    program TestPostRequest;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils, SynCrtSock;
    
    const
      RequestHeaderTemplate =
        'SOAPAction: http://tempuri.org/IConsultaCFDIService/Consulta';
      RequestDataTemplate =
        '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">'
        + '   <soapenv:Header/>'
        + '   <soapenv:Body>'
        + '      <tem:Consulta>'
        + '         <!--Optional:-->'
        + '         <tem:expresionImpresa><![CDATA[%expresionImpresa%]]></tem:expresionImpresa>'
        + '      </tem:Consulta>'
        + '   </soapenv:Body>'
        + '</soapenv:Envelope>';
    
    function SendCommand(Request: THttpRequest; const ExpresionImpresa: string): SockString;
    var
      outHeaders: SockString;
    begin
      Result := '';
      try
        Request.Request('ConsultaCFDIService.svc?wsdl', 'POST', 20000,
          RequestHeaderTemplate,
          SockString(StringReplace(RequestDataTemplate, '%expresionImpresa%',
            ExpresionImpresa, [])),
          'text/xml;charset="utf-8"', outHeaders, Result);
      except
        on E: Exception do begin
          Writeln('Error: ', E.Message);
          Exit;
        end;
      end;
    end;
    
    var
      Request: THttpRequest;
      Answer: SockString;
    begin
      try
        Request := TWinHTTP.Create('consultaqr.facturaelectronica.sat.gob.mx', '', True);
        try
          Answer := SendCommand(Request,
            '?re=LSO1306189R5&rr=GACJ940911ASA&tt=4999.99&id=e7df3047-f8de-425d-b469-37abe5b4dabb');
          Writeln('Answer:');
          Writeln('----------------');
          Writeln(Answer);
          Writeln('----------------');
          // Next requests go here ...
        finally
          Request.Free;
        end;
        Writeln('Press Enter to continue.');
        Readln;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.

     

    • Thanks 1

  5. @Mr. E Have you tried my SoapClient attached to the previous post? UseWSDL = False.

    But you can use other third-party library, or prepare and call HttpSendRequest manually, it is in WinApi.WinInet. I can recommend THttpRequest class from SynCrtSock.pas, mORMot. Something like this:

    fHttpRequest.Request(
      'https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc?wsdl',
      'POST', 20000, InHeader, inData, ' text/xml;charset="utf-8"', outHeaders, outData);

    P.S. Oh, you wrote "has been doing changes". Well then you always can use THttpRequest class and modify the request as you need.


  6. For those who have installed this plugin: today, 11.11, KFH has been updated to version 1.1. Now you no longer need to convert the characters back to the #nnnn format before saving the changes.

     

    And yes, the Forms Humanizer supports not only VCL and FireMonkey forms and frames, but also data modules.

    • Thanks 1

  7. @Mr. E You have to import the WSDL scheme, and Delphi generate necessary code for you.

    1. Create New VCL Form Application.
    2. File | New | Other | Delphi Projects | WebServices | WSDL Importer
    3. Location of WSDL file: https://pruebacfdiconsultaqr.cloudapp.net/ConsultaCFDIService.svc?singleWsdl
    4. In the generated unit ConsultaCFDIService replace all "https://pruebacfdiconsultaqr.cloudapp.net/ConsultaCFDIService.svc" to "https://consultaqr.facturaelectronica.sat.gob.mx/ConsultaCFDIService.svc"
    5. Use function GetIConsultaCFDIService to obtain IConsultaCFDIService in the generated unit.

    Demo application is attached. Tested in Delphi 10.2.3 Community edition.SimpleSoapClient.jpg.be5890c262bf45dc9159bdc3069a1d34.jpg

     

    SoapClient.ZIP


  8. It seems there is no simple solution for 1). Need to learn more.

    As for 2) yes, I thought about notifiers. Then I need to know

    1. When an user opens a form and creates a new one, to set notifiers for this form.
    2. When an user toggles between design mode and text mode of the form.

    Creating plugins for IDE is an interesting thing. Thank you for articles, I have to study it more deeply!


  9. In the right pascal way it would be like this:

    type
      TUrl = type string;
      TProto = type string;
      THost = type string;
      TPath = type string;
    
    TConnector = class
      public
        procedure SetupBridge(const url1, url2: TUrl); overload;
        procedure SetupBridge(const url1: TUrl;
          const proto2: TProto; const host2: THost; path2: TPath); overload;
        procedure SetupBridge(const proto1: TProto; const host1: THost; path1: TPath;
          proto2: TProto; const host2: THost; path2: TPath); overload;
        procedure SetupBridge(const proto1: TProto; const host1: THost; path1: TPath;
          url2: TUrl); overload;
      end;

    The type in "TUrl = type string" means that TUrl is a new different string type. Then you would need to specify the type of the parameter when calling:

        Connector.SetupBridge(TUrl('http://www.thedelphigeek.com/index.html'),
          TUrl('http://bad.horse/'));
        Connector.SetupBridge(TUrl('http://www.thedelphigeek.com/index.html'),
          TProto('http'), THost('bad.horse'), TPath(''));

    So are we safe? No! Unfortunately, Delphi allows assignments between custom string types.

    Connector.SetupBridge('http://www.thedelphigeek.com/index.html', 'http://bad.horse/');
    Connector.SetupBridge(TProto('http://www.thedelphigeek.com/index.html'), TProto('http://bad.horse/'));

    There is no overloaded methods like "procedure SetupBridge(const url1, url2: TProto);". But the compiler will not give any warning or hint.

    I would like the compiler developers to add a hint in such situations, not only for the types generated from string, but also for any other types (Integer, Byte etc.)

    • Confused 2
    • Sad 1

  10. When you are viewing the contents of a form, Delphi substitutes Unicode characters with the corresponding codes in #nnnn format. (This is valid for Delphi 10.2.3 and earlier, I do not know how it will be in 10.3). Therefore, manual editing of text strings of form elements is very difficult.

    After installing the Kryvich's Forms Humanizer package in your IDE, you can use a simple keyboard shortcut Ctrl-Alt-H to "humanize" all the text strings in your form's editor. This means that codes like #nnnn will be replaced with the corresponding Unicode characters.

    FormTextAfter.jpg.2e26409d6f6e002acb5d57f6c5a05727.jpg

    You can download and test the plugin for free here: https://sites.google.com/site/kryvich/kryvichs-form-humanizer.

    Enjoy!

    • Like 3
    • Thanks 1

  11. I am trying to write a small plug-in to the Delphi IDE using ToolsAPI. (If I succeed, it will be distributed free of charge.)

     

    1. Is it possible to reset the status of a file in editor after changes via IOTAEditWriter? Here is IOTAEditor.Modified but It's readonly. Or somehow make him think that the file has already been saved.

    IDEEditor.jpg.4ba5cbdb58e97dfc63b655e7c1c349de.jpg

     

    2. Is it possible to hook view mode switchings for opened DFM/FMX forms (View as Form / View as Text), using ToolsAPI only?


  12. Can someone suggests a really big open source project with plenty forms and units to test it on my Delphi 10.2.3 SE? Because I never seen no one exception in IDE after installing the Community Edition this summer. Though my projects not so big, a few hundred of thousand lines max.

    OK I opened JVCL package in my IDE, opened a few dozen files via Project Manager. I tried to compile, switch to form designer and back to code, type text. No problems. Even ErrorInsight works as expected. Bds.exe ate 370 megabytes of memory, but the IDE is still responsive. So far so good...


  13. @Zacherl If a runtime exception occurs it means that you forgot to put an assertion somewhere. :) 

    OK madExcept is a great tool, as well as 100% test coverage is very desirable. I just want to say that exceptions are probably the easiest and least time-consuming way to deal with bugs.

     

    Another point is the use of custom enumerated types instead of general types Integer, Byte, Char etc. We, Delphi programmers, love strong typing. (And do not love the Variant type :) ).


  14. @Jacek Laskowski To improve clarity it is better to use enumerated types instead of generic types such as Boolean, Byte, Integer.

    // In library:
    type TOwnsObjects = (No, Yes);
    // User code:
    fRecipients := TCollections.CreateList<TRecipient>(TOwnsObjects.Yes);

    This will require changes in a framework code, but will not require complicating a syntax of the language.


  15. @dados The right side of assignment can be any statement of a type that has members. Of course it can be the function call that returns an object or a record as well. This extended with statement should prompt the compiler to create a temporary readonly variable cr, without increasing the count of references, for optimization purposes.

     

    Note: it's just my suggestion how to make a with statement more convenient and useful for a programmer and Delphi compiler. I am not participating in Delphi Beta testing, and I don’t know if they made any changes to this statement.


  16. The best way to fix a bug is to identify it as early as possible. I use asserts to validate the input parameters of subroutines, to verify the result of a function, and sometimes inside a subroutine if needed. Asserts always enabled during development, at alpha and beta testing stages. After release, they can be disabled if they noticeably affect the speed of the application.

×