Jump to content

XylemFlow

Members
  • Content Count

    75
  • Joined

  • Last visited

Posts posted by XylemFlow


  1. 16 hours ago, Mike Warren said:

    At this point I'm going to have to concede defeat. I couldn't even get TMessageManager to give me Windows messages. I traced it though FMX.Forms and FMX.Menus, but it seems that the Alt key triggering the menu happens somewhere else that I can't find.

    Thanks for trying. Accelerator keys using the Alt key are a Windows thing, so I had suspected that this may only be a Windows issue. I also traced the code in FMX.Forms that appears to handle accelerator keys, but temporarily commenting it out didn't solve the issue.

     

    I also wondered if this interface could be used to somehow unregister the menu from using the Alt key, but couldn't see how.

    https://docwiki.embarcadero.com/Libraries/Alexandria/en/FMX.AcceleratorKey.IFMXAcceleratorKeyRegistryService.UnregisterReceiver


  2. On 8/7/2023 at 4:17 AM, Mike Warren said:

    So many odd things with FireMonkey...

     

    I was forced to move to TMainMenu for the same reason. There have been several changes I've had to make to my application because I just couldn't get what I wanted without weird side effects.

     

    Have you put some thought into maybe redesigning the functionality that requires TMenuBar?

     

    Edit: Also, I couldn't get TMenuBar to play nicely with MacOS. Also also, even TMainMenu has a problem on MacOS that I haven't put any time into trying to solve yet. The Mac Menu doesn't show properly.

    I found a post of yours where you discussed a method to prevent a beep and also disable accelerator keys by editing FMX.Platform.Win. I've tried this but it doesn't work and the whole application locks up. I used a TTimer to set the flag back to false, but it never gets called. Did you use some other kind of timer perhaps?

     

     


  3. 58 minutes ago, Lars Fosdal said:

    That sounds like a bug?  There should be a MouseUp event?

    It's because of accelerator keys. Pressing Alt is normally used in Windows to select menu items. Alt+F will select File for example. This was also an issue for me in VCL, but as I said above, I solved that issue by resetting the key in the KeyDown event. There is a bug in FMX that means that these accelerator keys don't work. The reason this issue is so infuriating is that the thing that's causing the conflict doesn't even work!

     

    I've encountered many bugs in FMX while porting my application from VCL. In almost all cases I've found a solution, sometimes by overriding methods or in one case using a hack to write to a protected variable. I'm still confident that I may be able to find a solution for this issue.


  4. 2 minutes ago, Lars Fosdal said:

    One could measure the time between the events to decide if they should be coupled - but ... lots of extra work. IMO, the Alt should normally be pressed BEFORE the click, and released AFTER the click-release - although you could interpret it as the Alt status only being required/captured at the time of the initial click, and only use the click-release as completion event.

    The mouse up event is not triggered after the Alt key is pressed down, so the mouse gets stuck in a clicked down state after release. So there can be no completion event. That's the issue.


  5. On 8/7/2023 at 4:17 AM, Mike Warren said:

    So many odd things with FireMonkey...

     

    I was forced to move to TMainMenu for the same reason. There have been several changes I've had to make to my application because I just couldn't get what I wanted without weird side effects.

     

    Have you put some thought into maybe redesigning the functionality that requires TMenuBar?

     

    Edit: Also, I couldn't get TMenuBar to play nicely with MacOS. Also also, even TMainMenu has a problem on MacOS that I haven't put any time into trying to solve yet. The Mac Menu doesn't show properly.

    The main reason I use TMenuBar is because I have 2 forms with 2 different menus, and you can only have 1 TMainMenu in an application. The Alt+drag also needs to work on both forms. Also I had an issue with styles in TMainMenu, which I discussed here.

    I have seen people suggest to use a single TMainMenu and change the contents when the user changes active form, but this seems inefficient to me, especially as I don't think TMainMenu has a BeginUpdate method to prevent repainting while updating. Both menus contain a lot of items. The issue with styles would still be an issue anyway.

     

    I wonder if I can inherit a new class from TMenuBar and override some functionality to prevent the Alt key issue? Is a TMenuBar created by the Windows OS or is it created entirely by the application?


  6. 23 hours ago, Fr0sT.Brutal said:

    Hmm, IMHO click-then-press is pretty weird sequence. This doesn't work neither in text editors nor with graphical tools I ever used. No surprise the system is not ready to handle it as you want it to.

    Actually, you can see in my demo that it also happens when you press Alt before mouse down. The issue happens whenever the user releases Alt before the mouse, regardless of which is pressed down first. The issue then happens a lot because users will typically release both at around the same time when they finish dragging.


  7. Here's a demo project. Mouse down, move and up events are recorded with counters and shown in labels.

     

    Steps:

    - Hold down left mouse button on the canvas

    - Press and release the Alt key

    - Release the left mouse button

    - Mouse down and mouse up counters no longer match

    TMenuBar Alt Issue.zip


  8. I'm using the Alt key in my application in an unusual way. It's used to modify how an object is dragged around on a canvas. The issue is that when pressing the Alt key after clicking down on the mouse button, the mouse up event and key up events are not triggered. I assume that this has something to do with accelerator keys for the TMenuBar. However, I don't want accelerator keys for the menu and they don't work in FMX anyway.

     

    I had the same issue in a previous version of my application that was developed in VCL. That was solved easily with the following, which then prevents the menu from reacting to the Alt key. 

    procedure TForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    begin
      // Prevent Alt key selecting the menu
      if Shift = [ssAlt] then begin
        Key := 0;
        Exit;
      end;
    
      // Other key processing code
    end;

    However, the same doesn't work in FMX with TMenuBar. I've tried setting Key to 0 and KeyChar to #0 but the issue remains.

     

    Note that the same issue does not happen when using TMainMenu, but I'm forced to use TMenuBar for various reasons. Does anyone have a solution? I'm running in Windows 32-bit but would also want it to work for macOS.


  9. Here's a basic demo using TPath and TSelectionPoint (Tested for Windows 32-bit). Click and drag to draw the line. Then you can drag the control points to create a curve. Of course you can then add the path to a list of paths if you want to keep multiple drawn paths.

     

    image.thumb.png.16f5c45ddb5b566e8c1c981127111ecc.png

    PathDemo.zip

    • Thanks 1

  10. This is a rather complex issue that I need help resolving. TImage Mouse Move and Mouse Up events are not triggered after showing a modal window from a TMainMenu item, but only when a certain style is applied to the form. Attached is a project for replicating the issue. Mouse events are recorded with incrementing counters. Any help would be appreciated. I'm using Delphi 11.2 and running in Windows 10.

     

    Steps:

    1. Build for Windows 32-bit and run

    2. Select Dark mode with the check box, which will apply the style to the form

    3. Click Show 2nd Form in the File menu, which will show a 2nd form as a modal window

    4. Close the 2nd form. The main form will regain focus

    5. Move the cursor over the image and the counter won't increment

     

    Observations:

    1. The Mouse Down event is triggered after closing the 2nd window, but the Mouse Up event isn't. This causes a miss match in the counters.

    2. In the default light mode the menu items activate on mouse up, but in dark mode they activate on mouse down. Perhaps the main menu is still owning the mouse up and mouse move events somehow after closing the window because of this?

    3. A TMenuBar does not have the same issue, even though its items are activated on mouse down

    4. I can't find anything in the style editor for the dark style that I could edit to fix the issue.

    5. I could try putting something in the main form's OnActivate event to force the Image to regain ownership of the mouse events, but nothing I try seems to work.

     

    Dark Mode Demo.zip


  11. I guess that one issue will be that currently I think the message boxes show the text on the buttons in the user's own language according to their Windows regional settings.


  12. I use TDialogServiceSync.MessageDialog and TDialogServiceSync.ShowMessage in my Windows / mac OS application. However, I've added a dark mode to my application from a downloaded style and it doesn't seem possible to set the style of these message boxes. The only solution seems to be to create my own message dialog forms and call them using ShowModal. Firstly, will that give exactly the same behaviour? Secondly, does anyone have or know of any free code for message dialog forms? I'd like it to support the various button combination options (TMsgDlgButtons) and an icon depending on TMsgDlgType. If not I'll of course make them myself.


  13. I've had the same problem for months. Close and re-open, even restart Windows, doesn't fix them. Remove and re-add from customize toolbars doesn't fix them either. Ctrl+F12 does work, but I prefer to use the buttons. What else can I try?

     

    I also have several other issues with the Delphi 11.2 IDE. For example, in one of my longer units it seems always confused what lines things are on. If I search the file and click to go to a result it always goes to the wrong place (offset by a constant amount). Find Declaration (Ctrl+click) also never works in that file. Is this a bug with long units (almost 8000 lines) or does something need resetting? Again, restart doesn't help.


  14. 14 hours ago, programmerdelphi2k said:

    @XylemFlow

     

    Here I am RAD 11.3/FMX and using StyleBook 2:

    1. 1 StyleBook Default = Empty
    2. 1 StyleBook Dark = Win10ModernDark.Style

    Unfortunately, some components store their properties in Hexadecimal values, so it's not possible to see the values directly, you'll need to convert them. This usually happens for properties with "images", value trees, etc...
    The "WriteComponent" function is found in TStream subclasses such as TMemoryStream etc... as well as "ReadComponent".
    Here I will try to demonstrate a way to do it, note that using "MEMO" or any other class that makes use of "TStrings", together with "themes/skins/styles", will be very painful in general, because there is much more involved than just change the skin of the component!

     

    Thanks for sharing that. But your stylebookDefault shows nothing as I expected. That's my issue. I can see all the parameters of the dark style but not the parameters of the default style to compare against.


  15. On 6/1/2023 at 11:13 PM, programmerdelphi2k said:

    did you try save in disk using "WriteComponent" function?

    I'm not sure what you mean. The style object for my normal mode doesn't contain anything because only hard coded styles are used.

     

    Attached is a basic example of the issues I'm having. I build it in Delphi 11.2 for Windows 32-bit. When run you can click the checkbox to switch between styles. I have 2 issues when in Dark Mode.

    1. The borders of the form change. All the components on the form shift because of this. I'd like only the colours to change. I assume that I need to change some parameters in windowborderstyle in the Style Designer, but playing around with those parameters hasn't helped much.
    2. The main menu behaves differently. In normal light mode I can click File for example and then move the cursor over Edit and Edit will automatically open and File will close. However, that doesn't happen in Dark Mode. File just stays open. I don't know what to change in the style to fix it.

    If I had all the parameters of the default style (light) then I could compare with the parameters of the dark style to try to work out what the differences are and maybe fix these issues. But I don't know how to do that?

    Dark Mode Demo.zip


  16. I'm trying to create a 'Dark Mode' for my Windows application, but I want to keep the basic style of the controls and just change the colours. I have downloaded a VCL style (Windows 10 Charcoal) and converted it to an FMX style using the Bitmap Style Designer. It looks mostly ok. However, there are some annoying differences. The main one being that there's a thicker border around the forms. There are a few other issues with some controls.

     

    I can open the Style Designer to edit the parameters, but it's difficult to know what to change. I'd like to compare the parameters with the default style to see what's different, but how do I do that? The default style seems to be hardcoded and not visible in the Style Designer.


  17. 21 hours ago, Anders Melander said:

    Btw, I don't know if the following is relevant to what you're doing:

    https://blog.grijjy.com/2021/01/14/shader-programming/

     

    That could be very useful. I've often considered if I could use the 3D capabilities of FMX for my 2D graphics. I may give textures a go in my circle demo. Implementing the interpolation for downsampling with higher quality should just be a matter of writing it into the pixel shader. One down side is that different shaders need to be written to support all platforms, but that's not a big issue. The main issue is combining this with other drawing primitives such as lines, circles, text and others that I use from TCanvas. The shader requires a 3D component, so mixing the two to draw to a single canvas seems difficult.


  18. 2 hours ago, Rollo62 said:

    If your circles are that critical, maybe it's worth if you are looking into Skia4Delphi, which is the next, new hot thing in town.

    It is well-supported and in favor of Embarcadero too, but probably adding a lot of extra baggage too, but seems to have endless possibilities on the cons side :-)

    The circles is just an example. My users could load any image and then want to animate it at various scale and angles.
    I've tried Skia4Delphi. One issue for me is that it doesn't use the GPU when drawing to an off screen TBitmap, whereas TCanvasD2D does.

     

    1 hour ago, Anders Melander said:

    Unless you're running this on a potato you shouldn't really need the GPU for something as simple as this. Of course, the GPU will be faster but the CPU should be fast enough.

    Rotation, translation, and scaling can be done in one go with a 3x3 (well, 2x3 actually) affine transformation. You "just" need to find a library that does that (or write it yourself). Graphics32 can do it but it doesn't support FMX. I'm guessing Image32 can too.

    I've already benchmarked TCanvasD2D (using GPU) against TCanvasGDIPlus (without GPU) on Windows and TCanvasD2D is significantly faster. That tells me that the GPU is making a big difference even with a fast library. I'm not running on a potato either, but my users might be (I use a potato for testing to make sure that it will work for all user setups). A previous version of my software was developed in VCL and rendered the images with scale and rotation in software, so I have those libraries already. There was a significant performance boost moving to FMX, so there's no going back. I'm doing full screen animation at up to 30fps so I need to make use of any hardware boost available.

    You said that you think the code is AND-ing rather than OR-ing. What makes you think that rather than it just using nearest neighbour sub-sampling? Surely the Delphi code is just sending instructions to the GPU and the GPU is unlikely to be making an error like that.


  19. I think the issue is with BitmapScale. With the code below I get the text in the right position.

     

    procedure TForm1.Button1Click(Sender: TObject);
    var
      ARect: TRectF;
      s: string;
    begin
      with Image1.Bitmap do
      begin
        Canvas.Font.Family := 'Arial';
        Canvas.Fill.Color := TAlphaColorRec.Black;
        ARect.Top := 200;
        ARect.Left := 100;
        ARect.Width := 105;
        ARect.Height := 50;
        s := 'hellow Fmx';
        Canvas.BeginScene;
        Canvas.Clear(TAlphaColorRec.White);
    //    canvas.textout(20,20,'hellow Fmx');
        Canvas.FillText(ARect, s, false, 1, [], TTextAlign.Leading, TTextAlign.Leading);
        Canvas.EndScene;
    
        SaveToFile('testBmp.png');
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Image1.Bitmap.SetSize(Round(Image1.Width), Round(Image1.Height));
      Image1.Bitmap.BitmapScale := 1;
    end;

     

    • Like 1

  20. Thanks everyone for those suggestions. However, I don't think anyone has suggested a way to get the GPU to handle this. My hand written code is about as fast as the CPU can go (I also have code for downscaling by exactly a factor of 2 which is faster still). But my original question was about doing this on the GPU, because I'm dealing with animated real time graphics. I also need to draw these images onto a canvas at an angle, which I do by setting TCanvas.Matrix with TCanvas.DrawBitmap. I could write code to do shrink and rotate but that would be super slow compared to the GPU.

    // shrink a bitmap by a factor of 2. ABitmapOut size needs to be pre set
    procedure ShrinkFast(const ABitmap : TBitmap ; out ABitmapOut : TBitmap);
    Var
      Lx, Ly, R : integer;
      P1, P2, P3, P4, POut, PRowStart, PRowStartOut : pByte;
      W, HM, WL : integer;
      LRowSizeOut, LRowSize : integer;
      bdata, bdatao : TBitmapData;
    begin
      if (ABitmapOut.Width = 0) or (ABitmapOut.Height = 0) then Exit;
    
      ABitmap.Map(TMapAccess.Read, bdata);
      ABitmapOut.Map(TMapAccess.Write, bdatao);
    
      try
        W := ABitmapOut.Width;
        R := ABitmap.Width div W; // shrink ratio
        if R <> 2 then Exit;
    
        HM := ABitmapOut.Height - 1;
        WL := W - 3;
        PRowStart := pByte(bdata.GetScanline(0));
        LRowSize := bdata.Pitch;
        PRowStartOut := pByte(bdatao.GetScanline(0));
        LRowSizeOut := bdatao.Pitch;
        if R = 2 then begin
          for Ly := 0 to HM do begin
            P1 := PRowStart;
            P2 := P1 + LRowSize;
            P3 := P1 + 4;
            P4 := P2 + 4;
            POut := PRowStartOut;
            Lx := 0;
            // set output pixel to the average of the 2X2 box of input pixels
            while Lx < WL do begin // loop unrolled by 4
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // blue
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // green
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // red
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // alpha
              Inc(P1,5); Inc(P2,5); Inc(P3,5); Inc(P4,5); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // blue
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // green
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // red
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // alpha
              Inc(P1,5); Inc(P2,5); Inc(P3,5); Inc(P4,5); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // blue
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // green
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // red
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // alpha
              Inc(P1,5); Inc(P2,5); Inc(P3,5); Inc(P4,5); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // blue
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // green
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // red
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // alpha
              Inc(P1,5); Inc(P2,5); Inc(P3,5); Inc(P4,5); Inc(POut);
              Inc(Lx, 4);
            end;
            while Lx < W do begin
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // blue
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // green
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // red
              Inc(P1); Inc(P2); Inc(P3); Inc(P4); Inc(POut);
              POut^ := (P1^ + P2^ + P3^ + P4^) shr 2; // alpha
              Inc(P1,5); Inc(P2,5); Inc(P3,5); Inc(P4,5); Inc(POut);
              Inc(Lx);
            end;
            Inc(PRowStartOut, LRowSizeOut);
            Inc(PRowStart, LRowSize shl 1);
          end;
        end;
    
      finally
        ABitmap.Unmap(bdata);
        ABitmapOut.Unmap(bdatao);
      end;
    end;

     


  21. On 4/30/2023 at 6:46 PM, KodeZwerg said:

    How about using an ImageViewer control, put your bitmap in and give the control the "BestFit" property.

    That doesn't do a great job either. Looking into the code, it appears to use DrawBitmap as well. However it wouldn't help me anyway. I need to be able to render the images to a TCanvas. I'm updating the canvas for dragging the objects around in real time, which is why I need high performance.


  22. FMX mostly does a very good job of antialiasing graphics, however I notice that quality of TCanvas.DrawBitmap is poor when the destination rect is smaller than the source rect. I'm running on Windows for now. This is especially obvious when the image contains thin lines as the subsampling causes parts of the lines to disappear. I'm looking for a way to improve the quality without compromising too much on runtime. So ideally I'd like it to be done on the GPU. I feel that this is a job that the GPU should be doing. Below is an example with 3 different methods. The last method is my own code, which shows what I'm trying to achieve but is not done on the GPU and so is not as fast as I'd like it to be. It also won't work if I want to include some rotation as well as scale using TCanvas.Matrix. I have also tried changing the HighSpeed flag in the DrawBitmap function, but it doesn't seem to make a difference (it does when upscaling an image but not when downscaling). See the attached project code example.

     

    Is this something that GPUs can normally do and if so, why isn't DrawBitmap doing it? Is there an alternative that will also work on different platforms? If I reduce an image in something like Inkscape it will do a much better job, although I'm not sure if the GPU is being used for the downsampling.

     

    Rfoje.png

    Draw_bitmap_small.zip


  23. On 12/11/2022 at 2:32 AM, Nigel Thomas said:

    Not the answer you are looking for, but you are aware that many users these days have browser adblockers installed? I suspect depending on advertising revenue from website visits to support your application may not be the best way of funding your work on it.

    Thanks, but I've used this funding model for some time and it's already proved to be easily profitable enough and I've had no complaints about the ads. The whole internet seems to be based on advertising so I think people are used to it. On the other hand, very few people are willing to pay for software in my experience. I've found that a lot more income can be made from free software with advertising compared to the same paid software without advertising, simply because it is much more likely to become popular. Of course it depends on the type of software and the target users

×