【问题标题】:How to pull a MDI child window out of the main form?如何将 MDI 子窗口拉出主窗体?
【发布时间】:2013-05-09 04:51:45
【问题描述】:

我想创建一个带有自己的任务栏的 MDI 应用程序,以便用户可以快速访问他/她想要带到前面的子窗口。然后我想到一个使用两个或多个监视器的用户可以将子窗口从我的应用程序的主窗体内部拖到它的外部,例如,拖到另一个监视器中。

怎么做?

【问题讨论】:

  • 您所描述的不是 MDI 应用程序,因为我认为 MDI 不会轻易支持您的需求。相反,它是一个使用可停靠表单的 MDI 应用程序。典型的 Delphi 示例就是 Delphi IDE 本身。阅读对接,这应该是非常常规的。
  • Delphi IDE 没有容器作为这些可停靠项目的基础。 MDI 有一个主窗体,整个窗口作为一个容器,孩子在其中。当您将其中一个拉出时,它本身就变成了一个主窗体。那我在描述什么?也许是第三种东西?
  • 好吧,你可以简单地构建一个主窗体并添加你自己的容器。
  • Windows 7 通过ITaskbarList3 接口增加了对任务栏访问 MDI 子窗口的支持。但是不可能将 MDI 子窗口“拉”成浮动窗口。要么创建停靠窗口,要么将 MDI 内容移动到可以在需要时在 MDI 子窗体和浮动窗体之间重新设置父级的框架上。
  • @DavidHeffernan 你测试过 NGLN 的答案吗?这只是我的意思,而且效果很好! :-)

标签: delphi mdi multiple-monitors sdi


【解决方案1】:

也许这个示例 MDI 客户端表单代码可以提供灵感:

unit Unit3;

interface

uses
  Windows, Messages, Controls, Forms;

type
  TForm3 = class(TForm)
  private
    FSizing: Boolean;
    procedure WMNCMouseLeave(var Message: TMessage);
      message WM_NCMOUSELEAVE;
    procedure WMWindowPosChanged(var Message: TWMWindowPosChanged);
      message WM_WINDOWPOSCHANGED;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Resize; override;
  end;

implementation

{$R *.dfm}

{ TForm3 }

var
  FDragging: Boolean = False;

procedure TForm3.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  if FormStyle = fsNormal then
    Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW
  else
    Params.ExStyle := Params.ExStyle and not WS_EX_APPWINDOW;
end;

procedure TForm3.Resize;
begin
  inherited Resize;
  FSizing := True;
end;

procedure TForm3.WMNCMouseLeave(var Message: TMessage);
begin
  inherited;
  FDragging := False;
end;

procedure TForm3.WMWindowPosChanged(var Message: TWMWindowPosChanged);
var
  P: TPoint;
  F: TCustomForm;
  R: TRect;
begin
  inherited;
  if not FDragging and not FSizing and not (fsShowing in FormState) and
    (WindowState = wsNormal) then
  begin
    F := Application.MainForm;
    P := F.ScreenToClient(Mouse.CursorPos);
    R := F.ClientRect;
    InflateRect(R, -5, -5);
    if not PtInRect(R, P) and (FormStyle = fsMDIChild) then
    begin
      FDragging := True;
      FormStyle := fsNormal;
      Top := Top + F.Top;
      Left := Left + F.Left;
    end
    else if PtInRect(R, P) and (FormStyle = fsNormal) then
    begin
      FDragging := True;
      FormStyle := fsMDIChild;
    end;
  end;
  FSizing := False;
end;

end.

【讨论】:

  • 这很有趣,它完成了工作!但我会在这方面做一些工作,因为当我们拉出一个孩子时,所有其他孩子都会从主窗体中出来,当我们单击重新恢复按钮时,它们也会消失。 :-)
  • @EASI 将 FDragging 声明为类 var,您的问题就解决了
  • @EASI 是的,显然WM_WINDOWPOSCHANGED 也被发送到所有其他表单...查看编辑。
  • @EASI 如果你添加 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);在 TForm3.CreateParams 的最后一行之后,你有一辆兰博基尼
  • 没发现有什么不同,应该怎么回事? :-/
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多