Jump to content

vfbb

Members
  • Content Count

    281
  • Joined

  • Last visited

  • Days Won

    31

Posts posted by vfbb


  1. @Kryvich If they implement record inheritance, now or in the future, I would prefer it to be more like an object:

    type
      TMyRecord = record(TParentRecord)
        Value: Integer;
        constructor Create; override;
        destructor Destroy; override;
        procedure Assign (const [ref] Src: TMyRecord); override;
      end;

    In this case the record would be like a "class" arc in all platforms, like strings and dynamic arrays, but with support for operators and having the exact size of their fields. It would be incredible.

     

    But if they don't implement inheritance, syntax better resemble the record operators that already exist, as the embaradero proposed:

    type
      TMyRecord = record
        Value: Integer;
        class operator Initialize (out Dest: TMyRecord);
        class operator Finalize(var Dest: TMyRecord);
        class operator Assign (var Dest: TMyRecord; const [ref] Src: TMyRecord);
      end;

     


  2. The first 64-bit iphones were released 7 years ago (iPhone 5s), and today they are the vast majority (more than 98%), it is no wonder that Apple ended support for 32-bit iphones a long time ago. Apple has not even updated iOS 32-bit for more than 4 years, and Apple has not accepted 32-bit apps in its store for some years. I personally have not compiled anything for ios 32 bits for some years.

     

    In the beginning, the 64-bit iOS kept backwards compatibility with 32-bit apps, but that ended when Apple released iOS 11. A good way to find out how many users are running only 64-bit apps is to look at the graphics of the most used versions of iOS (11, 12 and 13 have support only for 64-bit apps).

    • Like 3

  3. 5 minutes ago, Dany Marmur said:

    Neat!

     

    But why "FMX"? At a quick glance it looks like it would work in a VCL project too. No?

    The native System.Sensors.TGeocoder does not have support for VCL because works only in Android, iOS and MacOS. And even in Android have some small devices that does not support. And in the iOS and MacOS the result can be different than the Android because the Apple use the TomTom maps. Then, if you want a full cross platform solution, VCL or FMX, to use in all devices, include linux, having the same result, the Google Maps Geocoding is the solution.

     

    In my case, my client have a Windows version, the System.Sensors.Geocoder not work, I should use just Google Maps Geocoding.

    • Like 1
    • Thanks 1

  4. 36 minutes ago, RDP1974 said:

    No, the canvas is inside the external frame.

     

    The solution in plain API is here:

    https://stackoverflow.com/questions/22165258/how-to-create-window-without-border-and-with-shadow-like-github-app/44489430#44489430

     

    1. Create window with WS_CAPTION style
    2. Call DwmExtendFrameIntoClientArea WDM API passing 1 pixel top margin
    3. Handle WM_NCCALCSIZE message, do not forward call to DefWindowProc while processing this message, but just return 0

     

    (https://stackoverflow.com/questions/43818022/borderless-window-with-drop-shadow)

    Roberto, now I undestand your question, but this solution not work for me.

    I don't know why this line is there, but if it helps you, the same is not happening in FMX applications. The possible solution may be in the units FMX.Platform.Win or FMX.Forms.Border.Win.

     


  5. @RDP1974, @Turan Can

    To get a beatiful shadow, use the DWM API.

     

    Shadow in borderless form in VCL:

    unit Unit3;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
    
    type
      TForm3 = class(TForm)
      private
        { Private declarations }
        function SetBordelessShadow: Boolean;
      protected
        procedure CreateParams(var AParams: TCreateParams); override;
        procedure CreateWindowHandle(const AParams: TCreateParams); override;
        procedure WndProc(var AMessage: TMessage); override;
      public
        { Public declarations }
      end;
    
    var
      Form3: TForm3;
    
    implementation
    
    uses
      Winapi.DwmApi, Winapi.UxTheme;
    
    {$R *.dfm}
    
    { TForm3 }
    
    procedure TForm3.CreateParams(var AParams: TCreateParams);
    begin
      inherited CreateParams(AParams);
      if TOSVersion.Major < 6 then
      begin
        AParams.Style := WS_POPUP;
        AParams.WindowClass.Style := AParams.WindowClass.Style or CS_DROPSHADOW;
      end;
    end;
    
    procedure TForm3.CreateWindowHandle(const AParams: TCreateParams);
    begin
      inherited;
      if TOSVersion.Major >= 6 then
        SetBordelessShadow;
    end;
    
    function TForm3.SetBordelessShadow: Boolean;
    var
      LMargins: TMargins;
      LPolicy: Integer;
    begin
      if TOSVersion.Major < 6 then
        Exit(False);
      LPolicy := DWMNCRP_ENABLED;
      Result := Succeeded(DwmSetWindowAttribute(Handle, DWMWA_NCRENDERING_POLICY, @LPolicy, SizeOf(Integer))) and DwmCompositionEnabled;
      if Result then
      begin
        LMargins.cxLeftWidth := 1;
        LMargins.cxRightWidth := 1;
        LMargins.cyTopHeight := 1;
        LMargins.cyBottomHeight := 1;
        Result := Succeeded(DwmExtendFrameIntoClientArea(Handle, LMargins));
      end;
    end;
    
    procedure TForm3.WndProc(var AMessage: TMessage);
    begin
      case AMessage.Msg of
        WM_DWMCOMPOSITIONCHANGED,
        WM_DWMNCRENDERINGCHANGED:
          if SetBordelessShadow then
          begin
            AMessage.Result := 0;
            Exit;
          end;
      else
      end;
      inherited;
    end;
    
    end.

    Note: You can do the same in FMX!

    See the difference in the images attached:

    Using_DWM.png

    Using_DropShadow.png

    • Like 1

  6. Because your stylelookup is empty and the default stylelookup of the TPanel is the 'panelstyle', and your new component don't have a default style.
    Just do this:

    procedure TForm1.InitSpeedPanel(sp: TSpeedPanelClass);
    var
      sb: TSpeedButton;
    begin
      sp.StyleLookup := 'panelstyle'; // <<<<<<<<<
      // ...

     

    • Like 1
    • Thanks 1

  7. You may be manipulating images without checking the scale of the screen. Because in Windows the scale is usually 1 so there are no problems. Try on your windows to adjust the scale to 150% and test your program.

    I have a delphi crossplataform app that works perfectly on Windows, iOS and Android. It is not a game but have some cool animations that execute with 60fps without any choking and is more fast then the most of the apps that I have on my phone.


  8. @Eric Bonilha

    I know you! You are Eric of Digifort. I am Vinícius, Paulo's brother. We started programming at the same time, about 15 years ago, at the time of intertruco, lncb, ydm. 😂😂😂. I send you my contact in private.

     

    Eric, this tutorial that I posted is just to detect which url opened your app, to parsing the URL. This is useful just when you have many Universal Links or wildcard in the Universal Link.

     

    I made today a tutorial explain how to configure the Universal Link, You can see here: https://github.com/viniciusfbb/fmx_tutorials/blob/master/delphi_ios_universal_links/README.md


  9. About Tasks there are infinite ways to do this, try to create a bitmap for each Task, you create from outside and destroy from outside the Task. You will cancel the current Task, and without WaitFor it, create a new one with a new bitmap, when closing the form or the application you check the TPair <TBitmap, TTask> list using Task.WaitFor and then Bitmap.Free.

     

    About the performance, I will disappoint you a little. The delphi TBitmap is meant to be used only on the main thread. Although it works in threads, it has a critical section that does not allow you to paint TBitmap and process Paint forms simultaneously. But, as I said, although it doesn't take full advantage of the computer's potential, the program will work, and it probably won't harm you.


  10. 4 hours ago, Rollo62 said:

    @vfbb

    Why do you think this is not threadsafe, because of the

    
    AIPV6.Replace(

    or because of the use of BigInteger at all ?

     

    When using local string copies of the first case, this should be OK,
    or are the BigInteger intrinsically not threadsafe (never used them yet) ?

    Because the used methods of the BigInteger changes a global variable.

    BigInteger.Hex;
    BigInteger.Decimal;

    But I was looking, it is possible to avoid these methods, so this new example will be safe:

    uses
      System.SysUtils, Velthuis.BigIntegers;
    
    function IPV6ToNumberDigits(const AIPV6: string): string;
    var
      LBigInteger: BigInteger;
    begin
      if not BigInteger.TryParse(AIPV6.Replace(':', '', [rfReplaceAll]), 16, LBigInteger) then
        Exit('');
      Result := LBigInteger.ToString;
    end;
    
    function NumberDigitsToIPV6(const ANumberDigits: string): string;
    var
      I: Integer;
    begin
      if ANumberDigits.IsEmpty then
        Exit('');
      Result := BigInteger(ANumberDigits).ToHexString.ToLower.PadLeft(32, '0');
      for I := 0 to 6 do
        Result := Result.Insert((4 * (I+1)) + I, ':');
    end;

     

    • Like 1

  11. uses
      System.SysUtils, VCL.Dialogs, Velthuis.BigIntegers;
    
    function IPV6ToNumberDigits(const AIPV6: string): string;
    var
      LBigInteger: BigInteger;
    begin
      BigInteger.Hex;
      LBigInteger := AIPV6.Replace(':', '', [rfReplaceAll]);
      BigInteger.Decimal;
      Result := string(LBigInteger);
    end;
    
    function NumberDigitsToIPV6(const ANumberDigits: string): string;
    var
      LBigInteger: BigInteger;
      I: Integer;
    begin
      LBigInteger := ANumberDigits;
      BigInteger.Hex;
      Result := string(LBigInteger).ToLower.PadLeft(32, '0');
      BigInteger.Decimal;
      for I := 0 to 6 do
        Result := Result.Insert((4 * (I+1)) + I, ':');
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    const
      IPV6_EXAMPLE = '2001:0db8:85a3:08d3:1319:8a2e:0370:7344';
    begin
      showmessage('Original: ' + IPV6_EXAMPLE + #13#10 +
        'Number digits: ' + IPV6ToNumberDigits(IPV6_EXAMPLE) + #13#10 +
        'IPV6 of the number digits: ' + NumberDigitsToIPV6(IPV6ToNumberDigits(IPV6_EXAMPLE)));
    end;

    Result:

    Original: 2001:0db8:85a3:08d3:1319:8a2e:0370:7344
    Number digits: 42540766452641195744311209248773141316
    IPV6 of the number digits: 2001:0db8:85a3:08d3:1319:8a2e:0370:7344

    Remarks: This solution is not thread-safe.

×