-
Content Count
75 -
Joined
-
Last visited
Everything posted by XylemFlow
-
Many thanks again. That has solved a few of the issues. However, the scale issue is now on my other screen. The issue is that I have 2 monitors set to different scales. Your GetScreenScale function always returns the scale of the main screen, not the screen that the active form is on. I do have a better solution now though, after seeking support from Embarcadero. The solution prevents the Alt key being processed while the mouse button is down, but it does require editing a local copy of FMX.Platform.Win. Change the code in "function WndProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;" for WM_SYSKEYUP to this: WM_SYSKEYUP: begin // Local Edit: Change to prevent Alt key being processed while left mouse button is down if ((wParam = VK_MENU) or (wParam = VK_F10)) and not (PlatformWin.FormInfo[LForm].WasLeftMouseButtonPressed) then begin LForm.EnterMenuLoop; Result := 0; end else Result := DefWindowProc(hwnd, uMsg, wParam, lParam); end; I'm happy to make this change. I will report the bug in the Quality portal so that it hopefully gets fixed in future.
-
Many thanks. That does work and it also works when the Alt key is pressed down before the mouse. However, there is a small issue on my screen that has scale set to 125% in display settings. My guess is that the click on the caption bar isn't working in that case. That may be a quick fix to take the screen scale into account. That part may cause other issues though. For example, if the window is set to border style none or transparent mode then there is no caption bar to click. Also I wonder how I would get this to work on a second form that isn't the main form.
-
Something else I noticed. A breakpoint in TCommonCustomForm.KeyUp is never reached for the Alt key even though a breakpoint in TCommonCustomForm.KeyDown is. For all other keys on the keyboard that I tried, both were reached (even the Alt Gr key). Why is that?
-
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
-
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?
-
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.
-
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.
-
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?
-
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.
-
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
-
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. PathDemo.zip
-
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.
-
IDE - Delphi 11.1 "View Unit" and "View Form" buttons stopped working.
XylemFlow replied to Louis Kriel's topic in Delphi IDE and APIs
Thanks everyone, but I don't think the line endings are the cause of the issue. Like I said, Notepad++ couldn't find any incorrect line endings. I also tried converting to Unix EOL and back to Windows EOL and the resulting file was identical to the original. -
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.
-
IDE - Delphi 11.1 "View Unit" and "View Form" buttons stopped working.
XylemFlow replied to Louis Kriel's topic in Delphi IDE and APIs
Thanks. I tried searching the file in Notepad++ using Regular expression \r(?!\n)|(?<!\r)\n, which is supposed to find these. None were found though. -
IDE - Delphi 11.1 "View Unit" and "View Form" buttons stopped working.
XylemFlow replied to Louis Kriel's topic in Delphi IDE and APIs
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. -
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.
-
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.
-
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. 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. 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
-
Poor image quality with DrawBitmap when destination is smaller than source
XylemFlow replied to XylemFlow's topic in FMX
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. -
Poor image quality with DrawBitmap when destination is smaller than source
XylemFlow replied to XylemFlow's topic in FMX
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. 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. -
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;
-
Poor image quality with DrawBitmap when destination is smaller than source
XylemFlow replied to XylemFlow's topic in FMX
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; -
Poor image quality with DrawBitmap when destination is smaller than source
XylemFlow replied to XylemFlow's topic in FMX
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. -
This isn't specifically a Delphi question. More of a general Windows development and deployment question. I'm looking into the best options for hosting my application. My application is free and should be available publicly to everyone who wants to download it. My revenue model is based on advertising on my website, so I want to drive all the download traffic through my website. Of course the best option is most likely to host it on my website, but the application is fairly large and the number of downloads it high. My current web host is unlikely to provide enough bandwidth without me upgrading it. I'd also like to prevent people sharing the download link and thus avoiding visiting my website. If it was hosted on my site I would simply change the download file name every few days. What other options are there with 3rd party hosting? I have looked into using the Windows Store, but even if I make the listing undiscoverable I can't avoid people sharing the link and avoid going through my website. It doesn't look like Windows store provides a feature for changing the URL on a regular basis, and if they did how would I synch my website to the new link each time?