当Form具有父级时,不会触发OnKeyPress事件

时间:2017-02-25 18:07:34

标签: delphi parent keypress tabbed

我正在尝试在我的项目中实现TDI接口。它到目前为止工作正常(表单是在我的PageControl上的选项卡内创建的 - 正如预期的那样)。但是,我正面临一个令人讨厌的问题:OnKeyPress事件不是因为它们是“父级”而在我的子表单上触发。我在下面尝试了两种方法,但没有成功:

procedure TForm1.Button1Click(Sender: TObject);
var
  f: TForm2;
begin
  f := TForm2.Create(self);
  f.ManualDock(PageControl1);
  f.Show;
end;

-OR -

procedure TForm1.Button1Click(Sender: TObject);
var
  f: TForm2;
  tab: TTabSheet;
begin
  tab := TTabSheet.Create(PageControl1);
  tab.PageControl := PageControl1;
  tab.Parent := PageControl1;

  f := TForm2.Create(tab);
  f.BorderStyle := bsNone;
  f.Align := alClient;
  f.Parent := tab;
  tab.Caption := f.Caption;

  f.Show;
end;

¹不用说KeyPreview属性设置为True。

²如果我只是注释以下行,则事件正常(但表单不是在TabSheet中创建的):

//f.Parent := tab;

以前有人遇到过这个问题吗?有帮助吗? 谢谢!

1 个答案:

答案 0 :(得分:1)

我查看了这些来源,结果发现接收KeyPress的控件搜索其父窗体,如果窗体设置了KeyPreview,则将事件转发到该窗体:< / p>

function TWinControl.DoKeyPress(var Message: TWMKey): Boolean;
var
  Form: TCustomForm;
  Ch: Char;
begin
  Result := True;
  Form := GetParentForm(Self);
  if (Form <> nil) and (Form <> Self) and Form.KeyPreview and
    TWinControl(Form).DoKeyPress(Message) then Exit;
  // [...]
  Result := False;
end;

父表单是链中的顶级表单。这意味着除了原始控件之外,您的Form1会收到该事件(如果已设置KeyPreview):

function GetRealParentForm(Control: TControl; TopForm: Boolean = True): TCustomForm;
begin
  while (TopForm or not (Control is TCustomForm)) and (Control.Parent <> nil) do
    Control := Control.Parent;
  if Control is TCustomForm then
    Result := TCustomForm(Control) else
    Result := nil;
end;

这给你留下了几个选择:

  • 处理KeyPress中的Form1代替,但您可能必须找出它最初来自哪个子窗体。
  • 将表单KeyPreview设置为false,然后将处理程序添加到 直接Form2上的控件。
  • 修改VCL 来源不会将他们KeyPress转发到顶级表单,但是 而不是链中的下一个形式,我认为这就是我想要的 做。
  • 当然,我现在可能还有其他选择。