TPanel作为MDI应用程序中的启动画面

时间:2012-08-18 19:58:06

标签: delphi

我想在表单中间显示一个TPanel,它是其他表单的MDI父级。某种“泼溅”的形式,但并不完全。该面板将包含用户将调用misc的链接/按钮/快捷方式。功能

主要要求是当我点击MDI孩子时,TPanel应该放在MDI子表单下面。但是,就目前而言,TPanel将始终保持在MDI子表格之上。

调用Panel.SendToBack将使面板消失。我该怎么办?

2 个答案:

答案 0 :(得分:6)

您需要覆盖Panel的WindowProc,以便面板始终位于MDI子项后面,例如:

TMainForm = class(TForm)
...
private
  FPanelWndProc: TWndMethod;
  procedure PanelWndProc(var M: TMessage);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Windows.SetParent(Panel1.Handle, ClientHandle);
  // Override Panel1 WindowProc
  FPanelWndProc := Panel1.WindowProc;
  Panel1.WindowProc := PanelWndProc;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  // Restore Panel1 WindowProc
  Panel1.WindowProc := FPanelWndProc;
end;

procedure TMainForm.PanelWndProc(var M: TMessage);
var
  P: ^WINDOWPOS;
begin
  if M.Msg = WM_WINDOWPOSCHANGING then
  begin
    P := Pointer(M.LParam);
    // Always place panel at bottom
    P.hwndInsertAfter := HWND_BOTTOM;
  end;
  FPanelWndProc(M);
end;

注意:要快速测试代码,您可以通过File -> New -> MDI Application

创建MDI应用程序

编辑:上面的代码实际上回答了您的初始问题。如果您希望“ Panel以某种方式表现为MDI孩子”(您的评论引用),那么只需(......嗯......)使用MDI Child表单。即使用.FormStyle = fsMDIChild创建一个新表单,然后使用类似:

SetWindowLong(Child.Handle, GWL_STYLE, 
   GetWindowLong(Child.Handle, GWL_STYLE) and not (WS_BORDER or WS_DLGFRAME or WS_SIZEBOX));

删除它的边框(因为只设置.BorderStyle = bsNone不起作用) 在表单上放置您需要的任何内容,一旦单击它,它将移动到其他MDI表单之上。

答案 1 :(得分:1)

MDI系统的工作原理是拥有一个窗口,该窗口是所有MDI子窗口的父窗口,称为客户端窗口。反过来,该客户端窗口是MDI表单的子级。 MDI的VCL实现为您创建子窗口。您可以通过ClientHandle访问其窗口句柄。

由于客户端窗口是主窗体的子窗口,并且父窗口是所有MDI窗体,因此唯一的解决方案是使此面板成为客户端窗口的一部分。

您可以控制客户端窗口的绘制。您可以通过将客户端窗口的窗口proc替换为您自己的窗口proc来完成此操作。你还需要处理按钮点击等。但这非常混乱。

现在,也许你可以让你的面板成为客户端窗口的孩子。但我很确定这会搞砸你的MDI,事实证明你确实如此。