Willicious 8 Posted May 11, 2023 (edited) I have a hotkey config dialog which responds to key presses by jumping to that key in a list and focusing it for editing. The user must first press "Find Key" and then select a key in order to edit it (but, I'm seriously considering removing this button altogether and just have the dialog always listen for key presses). Problem is, if they hit [Space], this clicks the "Find Key" button again. Space is focused for editing, no problem, but the "Press any key to edit..." label is shown instead of "Editing key: Space." This could cause potential confusion for the end-user. Similarly, hitting [Enter] doesn't focus Enter for editing, which is a bit frustrating but I'm not sure what I can do about that. Not looking to restructure/rewrite the unit or change the way that the app handles reading/writing key names, etc. I just want to know if there's a simple way to stop the Space bar from auto-clicking the "Find Key" button. Tried "if Key = VK_SPACE then Exit;" on the form's OnKeyDown event handler and on the [btnFindKey] OnKeyDown event handler and similar things like that, nothing seems to work. --- As an aside, if I can't find a way to get the dialog to always listen for key presses without first pressing "Find Key", then ideally it'd be better if FindKey must be pressed in order to focus any key for editing. At the moment, it's sometimes possible to press a few keys after hitting "Find Key" and each one will be focused, but then some won't be. I can't figure out what's causing this behaviour, but if there's a way to stop the form from listening for key presses once one has been focused in the list, that would also be something of an improvement. Edited May 11, 2023 by Willicious Share this post Link to post
Willicious 8 Posted May 11, 2023 In support of the above question, here are the most relevant code snippets: This is the "Find Key" button's KeyDown event handler. At present, it's necessary to have a separate TLabel for the Space bar as a band aid for the issue described in the OP. As you can see, the unit is something of a mess at the moment. There's only so much I can do without spending days rewriting the whole thing: procedure GameHotkeys.btnFindKeyKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var i: Integer; KeyName: String; begin if Key = VK_SPACE then begin lblSpace.Visible := true; end else lblSpace.Visible := false; KeyName := fKeyNames[Key]; for i := 0 to lvHotkeys.Items.Count-1 do if KeyName = lvHotkeys.Items[i].Caption then begin lvHotkeys.SetFocus; lvHotkeys.ItemIndex := i; Exit; end; end; This is the OnClick for the FindKey button: procedure GameHotkeys.btnFindKeyClick(Sender: TObject); begin if not fShownFindInfo then begin fShownFindInfo := true; lblPressAnyKey.Visible := true; lblEditingKey.Caption := ''; end else begin lblPressAnyKey.Visible := true; lblEditingKey.Caption := ''; end; end; This is the part that sets the caption from which "Find Key" gets its signpost, but also responds to directly clicking into the lvHotkey list: procedure GameHotkeys.lvHotkeysClick(Sender: TObject); var i: Integer; begin i := FindKeyFromList(lvHotkeys.ItemIndex); if i = -1 then begin //some non-relevant stuff here lblEditingKey.Caption := ''; lblPressAnyKey.Visible := false; Exit; end; //some non-relevant stuff here lblEditingKey.Caption := 'Editing key: ' + fKeyNames[i]; lblPressAnyKey.Visible := false; lvHotkeys.Selected.MakeVisible(True); cbFunctionsChange(self); end; This is the part that finds the key from the list according to the caption: function GameHotkeys.FindKeyFromList(aValue: Integer): Integer; var i: Integer; begin Result := -1; if aValue = -1 then Exit; for i := 0 to MAX_KEY do if fKeyNames[i] = lvHotkeys.Items[aValue].Caption then begin Result := i; Exit; end; end; Share this post Link to post
programmerdelphi2k 237 Posted May 11, 2023 (edited) @Willicious did you try some like this ( to see "what key" was pressed... later, do your actions... all keys will be processed by form, then you can get it more easy or using a API func like GetKeyStatexxxx() implementation {$R *.dfm} procedure TForm1.MyKeyPressed(AEvent: string; AKeyPressed: Word); // a procedure for easy usage... var LText: string; begin if (ActiveControl <> nil) then LText := '... ActiveControl = ' + ActiveControl.ToString else LText := '... ActiveControl = nil'; // Memo1.Lines.Add(LText + ', Event: ' + AEvent + ', Key pressed: ' + AKeyPressed.ToString); // 3 events will call it end; procedure TForm1.FormCreate(Sender: TObject); begin KeyPreview := true; // capture all keys pressed on form... same that in some controls Label1.Caption := 'Click on form to remove the focus if in any control...'; end; procedure TForm1.FormClick(Sender: TObject); begin ActiveControl := nil; // try remove the focus in any control (if focused) end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin MyKeyPressed('FormOnKeyDown: ', Key); end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin MyKeyPressed('FormOnKeyUp: ', Key); end; procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin MyKeyPressed('FormOnKeyPress: ', ord(Key)); end; Edited May 11, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted May 12, 2023 in time, you can use "GetKeyNameText(...) + MapVirtualKey(...)" to get all key names used in your system, at least in MSWindows! Share this post Link to post
dwrbudr 8 Posted May 12, 2023 if Key = VK_SPACE then begin Key := 0; end; Share this post Link to post
Willicious 8 Posted May 12, 2023 16 hours ago, dwrbudr said: if Key = VK_SPACE then begin Key := 0; end; I tried this. Whilst it does disable the space bar from any further presses of the "Find Key" button, it also selects key "0000" for editing in the hotkey dialog. I wonder if this can be modified to first change the key to 0 (to pull focus away from the button), but then jump to "Space" in the lvHotkeys list...? Share this post Link to post