5
votes

In code I have developed some years ago I have been using this a lot to close the current form on pressing the Escape key at any moment:

procedure TSomeForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
    if key = #27 then close;
end;

This behaviour is defined for the TForm. The form's KeyPreview property is be set to True to let the form react to key presses before any other components. It all works perfectly well for the best part of the program, however, when the Escape key is pressed while a TEdit component is focused a sound (a ding sound used by Windows to signify invalid operation) is issued. It still works fine but I have never quite managed to get rid of the sound.

What's the problem with this?


Steps to recreate:

  • new VCL Forms application, set the form's KeyPreview to true
  • on the Events tab double-click the onKeyPress event and enter dummy code:

    if key=#27 then ;

  • add a TListBox, TCheckBox, TEdit to the form and run the application

  • in the application try pressing Esc and NOTHING happens, as specified by the dummy code
  • focus the TEdit and press Esc. Nothing happens but the sound is played.
3

3 Answers

23
votes

You get the ding because you left the ESC in the input. See how Key is a var? Set it to #0 and you eliminate the ding. That removes it from further processing.

procedure TSomeForm.FormKeyPress(Sender: TObject; var Key: Char);
begin
    if key = #27 then 
    begin
      key := #0;
      close;
    end;
end;

KeyPreview is just that, a preview of what will be passed to the controls unless you stop it.

0
votes

Starting from Jim's answer (thanks Jim) I had to make it work for me. What I needed was to make a dropped down combobox close keeping the selected item and move to the next/previous control when TAB/shift+TAB was pressed. Everytime I did press TAB the annoying sound filled the room. My work arroud was using onKeyDown event to catch the shiftstate, declaring var aShift: boolean; in form's interface and use the following code:

procedure TForm2.StComboKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if ssShift in Shift then aShift := true else aShift := false;
end;

procedure TForm2.StComboKeyPress(Sender: TObject; var Key: Char);
begin
 if Key=char(VK_TAB) then
   begin
     Key := #0;
     StCombo.DroppedDown := false;
     if aShift
       then previousControl.SetFocus
       else nextControl.SetFocus;
   end;
end;
-1
votes

It's an old thread... but anyway, here's a far better one: catching Alt-C!

Unlike ESC, Alt-C isn't serviced by KeyPress, so setting Key to #0 in KeyPress doesn't work, and the horrendous "ding!" is issued every time. After hours of trying, here's the workaround I found: - create a main menu option to service the request - set its ShortCut to Alt+C - yes indeed, that is NOT one of the available ShortCut choices(!!)... but it does work anyway! - do the processing in that menu option's OnClick - you may even make in "in the background": you may set the menu option's Visible to false - as long as its Enabled stays true, it will be activated by Alt-C even though it will not be visible in the menu.

Hope that may help! And if you have something more elegant, please advise.