1

A. Create a VCL Forms Application.

B. Put a TListBox on the form and fill in some items at design-time, for example:

enter image description here

C. Set the Form's KeyPreview property to True:

enter image description here

D. In the Form's OnKeyDownevent-handler write this code:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_BACK then
  begin
    if ListBox1.Focused then
    begin
      Key := 0;
      CodeSite.Send('ListBox1 is focused!');
    end;
  end;
end;

E. Run the program and select Item5 by clicking on it:

enter image description here

Now ListBox1 has the focus.

F. Now press the BACKSPACE key. Supposedly, setting Key := 0; in the Form's OnKeyDownevent-handler should block the BACKSPACE key from being processed by the ListBox1 control. But this does not work, as you can see: The BACKSPACE key caused to change the selection from Item5 to Item1:

enter image description here

So how can I prevent the BACKSPACE key from being processed in the focused ListBox control and to change the ListBox's selection?

Delphi 10.1 Berlin Update 2
Windows 7 x64 SP1

user1580348
  • 5,721
  • 4
  • 43
  • 105
  • Read about WM_GETDLGCODE – David Heffernan Dec 03 '16 at 20:56
  • 1
    @DavidHeffernan: And what value would you propose returning from that message? There is no flag that says to ignore backspace keystrokes. Are you thinking of disabling the `DLGC_WANTALLKEYS` and/or `DLGC_WANTCHARS` flags, or enabling the `DLGC_WANTMESSAGE` flag? You are going to have to be more specific. – Remy Lebeau Dec 03 '16 at 23:36
  • 1
    TranslateMessage is called before DispatchMessage in the message loop, therefore you haven't prevented a WM_CHAR (which is translated from the WM_KEYDOWN) to be posted to the list box. Hence Remy's answer.... – Sertac Akyuz Dec 04 '16 at 00:18

1 Answers1

2

Use the OnKeyPress event instead:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #8 then
  begin
    if ListBox1.Focused then
    begin
      Key := #0;
      CodeSite.Send('ListBox1 is focused!');
    end;
  end;
end;

You can't always block everything in OnKeyDown.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you, it works. But this is amazing, as `OnKeyDown` occurs **BEFORE** `OnKeyPress`, and ALTHOUGH `Key` ist explicitly set to zero in `OnKeyDown` the event `OnKeyPress` is still called! I was always convinced that keys like `BACKSPACE` don't trigger `OnKeyPress`. – user1580348 Dec 04 '16 at 01:35
  • Normally `OnKeyPress` is not called if `OnKeyDown` rejects a key. Notice my answer said to use `OnKeyPress` **instead of** `OnKeyDown`, not with it. In any case, `Key` in `OnKeyDown/Up` is a *virtual key code*, but `Key` in `OnKeyPress` is a *translated character*, so they are not always the same value (in this case, they are). – Remy Lebeau Dec 04 '16 at 02:27
  • Strangely, blocking the `HOME` key and the `END` key with `Key := 0;` in `OnKeyDown` DOES work and no `OnKeyPress` event is being triggered with these keys. Why? Why this different handling of these keys? – user1580348 Dec 04 '16 at 02:31
  • `Home` and `End` are not **characters** and dont trigger `OnKeyPress` at all (try it). `Backspace` is a **character** (Unicode codepoint `U+0008`). `OnKeyDown/Up` are triggered in reply to `WM_KEYDOWN/UP` messages that carry virtual key codes from the keyboard, even for non-character keys, but `OnKeyPress` in triggered in reply to `WM_CHAR` which only carries characters: "*[`WM_CHAR`] Posted to the window with the keyboard focus when a `WM_KEYDOWN` message is **translated** by the `TranslateMessage()` function. The `WM_CHAR` message contains the **character code** of the key that was pressed*" – Remy Lebeau Dec 04 '16 at 02:48
  • Thank you for the detailed explanation, it is much appreciated! – user1580348 Dec 04 '16 at 02:57