How to stop receiving repeated OnKeyPress events on a TForm?
I have a main Form and when I select an item and press Enter a second modal Form is shown. This has some TEdit
controls to change the item parameters. When the user has finished, he can press Esc to cancel or Enter to update the item, and close the edit Form.
The problem is that if the user presses and holds Enter, a loop is occurs. The Form is closed and opened again and then closed... and so on.
I changed the WndProc
of the modal Form and cancel if the previous key state was pressed. But this works only if I don't have any controls on the Form. If I drop a TEdit
(which is needed), the Form re-enters the loop. The modal Form has KeyPreview
set to true, because I want to be able to validate the data from anywhere.
This is the minimal code to reproduce the problem:
After you test this, you can drop a TEdit
on Form2
and you will notice that a loop occurs.
Form1:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormKeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then Form2.ShowModal;
end;
end.
Form2:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
protected
procedure WndProc(var Msg: TMessage); override;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin Key:= #0; ModalResult:= mrOK; end;
end;
procedure TForm2.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CHAR) and ((Msg.LParam and $40000000) <> 0) then Exit;
inherited;
end;
end.
forms delphi delphi-2009
|
show 7 more comments
I have a main Form and when I select an item and press Enter a second modal Form is shown. This has some TEdit
controls to change the item parameters. When the user has finished, he can press Esc to cancel or Enter to update the item, and close the edit Form.
The problem is that if the user presses and holds Enter, a loop is occurs. The Form is closed and opened again and then closed... and so on.
I changed the WndProc
of the modal Form and cancel if the previous key state was pressed. But this works only if I don't have any controls on the Form. If I drop a TEdit
(which is needed), the Form re-enters the loop. The modal Form has KeyPreview
set to true, because I want to be able to validate the data from anywhere.
This is the minimal code to reproduce the problem:
After you test this, you can drop a TEdit
on Form2
and you will notice that a loop occurs.
Form1:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormKeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then Form2.ShowModal;
end;
end.
Form2:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
protected
procedure WndProc(var Msg: TMessage); override;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin Key:= #0; ModalResult:= mrOK; end;
end;
procedure TForm2.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CHAR) and ((Msg.LParam and $40000000) <> 0) then Exit;
inherited;
end;
end.
forms delphi delphi-2009
How about unselecting theitem
in the main form, on return from the modal form?
– Tom Brunberg
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
1
Or you can useOnKeyDown
/OnKeyUp
instead ofOnKeyPress
. Those one's won't repeat when held down.
– Jerry Dodge
Nov 20 '18 at 20:50
|
show 7 more comments
I have a main Form and when I select an item and press Enter a second modal Form is shown. This has some TEdit
controls to change the item parameters. When the user has finished, he can press Esc to cancel or Enter to update the item, and close the edit Form.
The problem is that if the user presses and holds Enter, a loop is occurs. The Form is closed and opened again and then closed... and so on.
I changed the WndProc
of the modal Form and cancel if the previous key state was pressed. But this works only if I don't have any controls on the Form. If I drop a TEdit
(which is needed), the Form re-enters the loop. The modal Form has KeyPreview
set to true, because I want to be able to validate the data from anywhere.
This is the minimal code to reproduce the problem:
After you test this, you can drop a TEdit
on Form2
and you will notice that a loop occurs.
Form1:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormKeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then Form2.ShowModal;
end;
end.
Form2:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
protected
procedure WndProc(var Msg: TMessage); override;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin Key:= #0; ModalResult:= mrOK; end;
end;
procedure TForm2.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CHAR) and ((Msg.LParam and $40000000) <> 0) then Exit;
inherited;
end;
end.
forms delphi delphi-2009
I have a main Form and when I select an item and press Enter a second modal Form is shown. This has some TEdit
controls to change the item parameters. When the user has finished, he can press Esc to cancel or Enter to update the item, and close the edit Form.
The problem is that if the user presses and holds Enter, a loop is occurs. The Form is closed and opened again and then closed... and so on.
I changed the WndProc
of the modal Form and cancel if the previous key state was pressed. But this works only if I don't have any controls on the Form. If I drop a TEdit
(which is needed), the Form re-enters the loop. The modal Form has KeyPreview
set to true, because I want to be able to validate the data from anywhere.
This is the minimal code to reproduce the problem:
After you test this, you can drop a TEdit
on Form2
and you will notice that a loop occurs.
Form1:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormKeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
uses Unit2;
{$R *.dfm}
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then Form2.ShowModal;
end;
end.
Form2:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
protected
procedure WndProc(var Msg: TMessage); override;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin Key:= #0; ModalResult:= mrOK; end;
end;
procedure TForm2.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CHAR) and ((Msg.LParam and $40000000) <> 0) then Exit;
inherited;
end;
end.
forms delphi delphi-2009
forms delphi delphi-2009
edited Nov 20 '18 at 18:07
Remy Lebeau
339k19262456
339k19262456
asked Nov 20 '18 at 17:48
Marus NebunuMarus Nebunu
1,226931
1,226931
How about unselecting theitem
in the main form, on return from the modal form?
– Tom Brunberg
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
1
Or you can useOnKeyDown
/OnKeyUp
instead ofOnKeyPress
. Those one's won't repeat when held down.
– Jerry Dodge
Nov 20 '18 at 20:50
|
show 7 more comments
How about unselecting theitem
in the main form, on return from the modal form?
– Tom Brunberg
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
1
Or you can useOnKeyDown
/OnKeyUp
instead ofOnKeyPress
. Those one's won't repeat when held down.
– Jerry Dodge
Nov 20 '18 at 20:50
How about unselecting the
item
in the main form, on return from the modal form?– Tom Brunberg
Nov 20 '18 at 19:04
How about unselecting the
item
in the main form, on return from the modal form?– Tom Brunberg
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
1
1
Or you can use
OnKeyDown
/ OnKeyUp
instead of OnKeyPress
. Those one's won't repeat when held down.– Jerry Dodge
Nov 20 '18 at 20:50
Or you can use
OnKeyDown
/ OnKeyUp
instead of OnKeyPress
. Those one's won't repeat when held down.– Jerry Dodge
Nov 20 '18 at 20:50
|
show 7 more comments
1 Answer
1
active
oldest
votes
Because it's impossible to hook TWinControl.DoKeyPress
to solve this issue as it should, I came up with this workaround:
Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnActivate:= AppActivate;
end;
procedure TForm1.AppActivate(Sender: TObject);
begin
EnterReleased:= (GetAsyncKeyState(VK_RETURN) and $8000) = 0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
Form2.ShowModal;
end;
end;
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Form2:
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
ModalResult:= mrOK;
end;
end;
end;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53398701%2fhow-to-stop-receiving-repeated-onkeypress-events-on-a-tform%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Because it's impossible to hook TWinControl.DoKeyPress
to solve this issue as it should, I came up with this workaround:
Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnActivate:= AppActivate;
end;
procedure TForm1.AppActivate(Sender: TObject);
begin
EnterReleased:= (GetAsyncKeyState(VK_RETURN) and $8000) = 0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
Form2.ShowModal;
end;
end;
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Form2:
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
ModalResult:= mrOK;
end;
end;
end;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
add a comment |
Because it's impossible to hook TWinControl.DoKeyPress
to solve this issue as it should, I came up with this workaround:
Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnActivate:= AppActivate;
end;
procedure TForm1.AppActivate(Sender: TObject);
begin
EnterReleased:= (GetAsyncKeyState(VK_RETURN) and $8000) = 0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
Form2.ShowModal;
end;
end;
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Form2:
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
ModalResult:= mrOK;
end;
end;
end;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
add a comment |
Because it's impossible to hook TWinControl.DoKeyPress
to solve this issue as it should, I came up with this workaround:
Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnActivate:= AppActivate;
end;
procedure TForm1.AppActivate(Sender: TObject);
begin
EnterReleased:= (GetAsyncKeyState(VK_RETURN) and $8000) = 0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
Form2.ShowModal;
end;
end;
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Form2:
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
ModalResult:= mrOK;
end;
end;
end;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Because it's impossible to hook TWinControl.DoKeyPress
to solve this issue as it should, I came up with this workaround:
Form1:
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnActivate:= AppActivate;
end;
procedure TForm1.AppActivate(Sender: TObject);
begin
EnterReleased:= (GetAsyncKeyState(VK_RETURN) and $8000) = 0;
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
Form2.ShowModal;
end;
end;
end;
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
Form2:
procedure TForm2.FormCreate(Sender: TObject);
begin
KeyPreview:= True;
end;
procedure TForm2.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then begin
Key:= #0;
if EnterReleased then begin
EnterReleased:= False;
ModalResult:= mrOK;
end;
end;
end;
procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = VK_RETURN then EnterReleased:= True;
end;
edited Nov 22 '18 at 20:27
answered Nov 21 '18 at 14:57
Marus NebunuMarus Nebunu
1,226931
1,226931
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53398701%2fhow-to-stop-receiving-repeated-onkeypress-events-on-a-tform%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
How about unselecting the
item
in the main form, on return from the modal form?– Tom Brunberg
Nov 20 '18 at 19:04
If it's only valid to press ENTER if Edit1 has a value, why not check that also: if (key = #13) then if (trim(Edit1.Text) <> '') then begin Key := #0; ModalResult := mrOK; end else Key := #0;
– A Lombardo
Nov 20 '18 at 19:04
@TomBrunberg the item must remain selected.
– Marus Nebunu
Nov 20 '18 at 19:07
@ALombardo, I check it, but if it's valid the loop will occur.
– Marus Nebunu
Nov 20 '18 at 19:09
1
Or you can use
OnKeyDown
/OnKeyUp
instead ofOnKeyPress
. Those one's won't repeat when held down.– Jerry Dodge
Nov 20 '18 at 20:50