Как перестать получать повторяющиеся события OnKeyPress на TForm? - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть основная форма, и когда я выбираю элемент и нажимаю Введите , отображается вторая модальная форма.Имеется несколько TEdit элементов управления для изменения параметров элемента.Когда пользователь закончил, он может нажать Esc для отмены или Введите , чтобы обновить элемент, и закрыть форму редактирования.

Проблема в том, что если пользователь нажимает и удерживает Ввод , происходит цикл.Форма закрывается и открывается снова, а затем закрывается ... и т. Д.

Я изменил WndProc модальной формы и отменил, если было нажато предыдущее состояние клавиши.Но это работает, только если у меня нет никаких элементов управления в форме.Если я опускаю TEdit (что необходимо), Форма снова входит в цикл.Для модальной формы KeyPreview установлено значение true, потому что я хочу иметь возможность проверять данные из любого места.

Это минимальный код для воспроизведения проблемы:

После проверки этого, вы можете сбросить TEdit на Form2, и вы заметите, что происходит цикл.

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.

1 Ответ

0 голосов
/ 21 ноября 2018

Поскольку невозможно перехватить TWinControl.DoKeyPress, чтобы решить эту проблему, как следует, я нашел обходной путь:

Форма 1:

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;

Форма 2:

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;
...