XylemFlow 8 Posted August 5, 2023 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. Share this post Link to post
XylemFlow 8 Posted August 5, 2023 (edited) 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 Edited August 6, 2023 by XylemFlow Share this post Link to post
Mike Warren 2 Posted August 7, 2023 (edited) 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. Edited August 7, 2023 by Mike Warren Share this post Link to post
Fr0sT.Brutal 900 Posted August 7, 2023 (edited) 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. Edited August 7, 2023 by Fr0sT.Brutal Share this post Link to post
XylemFlow 8 Posted August 8, 2023 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. Share this post Link to post
Lars Fosdal 1792 Posted August 8, 2023 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. 1 Share this post Link to post
XylemFlow 8 Posted August 8, 2023 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? Share this post Link to post
XylemFlow 8 Posted August 8, 2023 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. Share this post Link to post
Lars Fosdal 1792 Posted August 8, 2023 That sounds like a bug? There should be a MouseUp event? Edit: The "modal window" may be receiving the event instead of the parent form. Share this post Link to post
XylemFlow 8 Posted August 8, 2023 (edited) 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. Edited August 8, 2023 by XylemFlow Share this post Link to post
Lars Fosdal 1792 Posted August 8, 2023 1 hour ago, Lars Fosdal said: The "modal window" may be receiving the event instead of the parent form. Not sure if you missed my edit? Share this post Link to post
mvanrijnen 123 Posted August 8, 2023 (edited) I once dived into this (FMX) and the click is just "swallowed" somewhere, in the deep grounds of FMX. Can't remember clearly, but i might have created an topic about it @embarcadero. Edited August 8, 2023 by mvanrijnen Share this post Link to post
XylemFlow 8 Posted August 8, 2023 (edited) 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? Edited August 8, 2023 by XylemFlow link to other thread Share this post Link to post
Mike Warren 2 Posted August 12, 2023 On 8/9/2023 at 12:21 AM, XylemFlow said: 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 was a normal TTimer set to 1 second, IIRC. I don't have it on my form any more, but I do still have a backup of my copy of FMX.Platform.Win. Well, I just deleted a very long reply, including a new version of your test program because I thought I'd found a workaround, but it didn't really solve anything. What I have discovered, however, is that very early on, WM_LBUTTONUP messages are no longer handled if the Alt key is pressed and released while the mouse button is being held down. I'll keep investigating. I suspect this has something to do with the FMX Message Manager, which I currently know nothing about. Share this post Link to post
Mike Warren 2 Posted August 12, 2023 I just tested your program on an ARM Mac and it seems to work fine. That means a solution only needs to be found for Windows. Share this post Link to post
Mike Warren 2 Posted August 12, 2023 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. Share this post Link to post
XylemFlow 8 Posted August 13, 2023 (edited) 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 Edited August 13, 2023 by XylemFlow Share this post Link to post
XylemFlow 8 Posted August 14, 2023 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? Share this post Link to post
Mike Warren 2 Posted August 15, 2023 (edited) Here's a unit that seems to solve this for me. All you need to do is add MouseHelper to your form's uses clause. It creates a low priority thread that generates an extra MouseUp event if an Alt key was pressed while the left mouse button is down. TMenuBarAltIssueMW.zip Edit: I should mention I've done minimal testing at this stage. I really need to get back to my other work. Edited August 15, 2023 by Mike Warren 1 Share this post Link to post
XylemFlow 8 Posted August 15, 2023 (edited) 3 hours ago, Mike Warren said: Here's a unit that seems to solve this for me. All you need to do is add MouseHelper to your form's uses clause. It creates a low priority thread that generates an extra MouseUp event if an Alt key was pressed while the left mouse button is down. TMenuBarAltIssueMW.zip Edit: I should mention I've done minimal testing at this stage. I really need to get back to my other work. 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. Edited August 15, 2023 by XylemFlow Share this post Link to post
Mike Warren 2 Posted August 16, 2023 12 hours ago, XylemFlow said: However, there is a small issue on my screen that has scale set to 125% in display settings. The new version attached should account for that. Quote For example, if the window is set to border style none or transparent mode then there is no caption bar to click. I did think of this as a limitation, but figured it wouldn't be likely to be the case on a form that is using a menu bar. In that case the click would be on the first menu item. Quote Also I wonder how I would get this to work on a second form that isn't the main form. I thought about that last night. The new version uses Application.ActiveForm instead of Application.MainForm. This is very definitely a kludge. As I said previously, I've moved to using TMainMenu instead of TMenuBar. TMenuBarAltIssueMW2.zip 1 Share this post Link to post
XylemFlow 8 Posted August 16, 2023 (edited) 12 hours ago, Mike Warren said: The new version attached should account for that. I did think of this as a limitation, but figured it wouldn't be likely to be the case on a form that is using a menu bar. In that case the click would be on the first menu item. I thought about that last night. The new version uses Application.ActiveForm instead of Application.MainForm. This is very definitely a kludge. As I said previously, I've moved to using TMainMenu instead of TMenuBar. TMenuBarAltIssueMW2.zip 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. Edited August 16, 2023 by XylemFlow Share this post Link to post
XylemFlow 8 Posted August 17, 2023 Regarding the above code edit. I decided it was better to just comment out that whole part and just leave the following since I don't want the menu to ever interact with the Alt key. Result := DefWindowProc(hwnd, uMsg, wParam, lParam); Share this post Link to post
Mike Warren 2 Posted August 21, 2023 (edited) On 8/16/2023 at 11:32 PM, XylemFlow said: 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. Excellent! If you do report it, post the link here and I'll vote for it. Edited August 21, 2023 by Mike Warren Share this post Link to post
XylemFlow 8 Posted August 21, 2023 11 hours ago, Mike Warren said: Excellent! If you do report it, post the link here and I'll vote for it. https://quality.embarcadero.com/browse/RSP-42144 Thanks Share this post Link to post