2017-02-25 60 views
0

我试图在我的项目中实现TDI接口。到目前为止它工作得很好(表单在我的PageControl的选项卡内创建 - 如预期的那样)。然而,我正面临着一个恼人的问题:OnKeyPress事件不是因为它们是“父对象”而在我的子表单上触发的。我已经试过两种方式下面,但没有成功:当Form有父项时,OnKeyPress事件不会被触发

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

- 或 -

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。

²如果我只是注释以下行,事件工作正常(但不是一个标签页中创建的形式):

//f.Parent := tab; 

有没有人遇到这个问题?任何帮助? 谢谢!

+2

KeyPreview为True解释它。按照设计,活动将转到顶层表单。 –

+0

正常情况下,KeyPreview只会使窗体在控件中接收* * *添加*中的事件*,所以它仍然可以工作。 – dummzeuch

+0

它应该工作,但它不会。 –

回答

1

我看看人士透露,事实证明,控制接收KeyPress搜索它的父窗体,如果窗体上有KeyPreview集,中继事件这种形式:

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; 

这让你有两个选择:

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

你说得对。我试图重写这个方法,但我不确定它是否会按需要工作。 –

相关问题