Delphi 10.1 Berlin MDI应用实现常驻首页/仪表盘方法
Delphi 10.1 Berlin MDI应用常驻仪表盘实现方案
你遇到的子窗体无法显示问题,本质是Delphi MDI框架的默认机制导致:MDI主窗体的客户区会被系统自动创建的MDIClient窗口完全占满,所有MDI子窗体都是这个MDIClient的子窗口。如果直接往主窗体拖放网格、面板等控件,控件会覆盖在MDIClient上方,完全挡住MDI子窗体的显示区域,自然无法正常加载子窗体。
方案1:常驻锁定MDI子窗体实现仪表盘
该方案完全沿用现有MDI架构,不需要调整整体布局逻辑,实现步骤如下:
- 创建独立的仪表盘窗体(例如命名为
frmDashboard),提前设置基础属性:FormStyle设为fsMDIChildBorderStyle设为bsNone,去掉标题栏和边框,实现和主窗体融合的效果Position设为poDesigned
- 在主窗体的
OnCreate事件中优先创建仪表盘窗体,拦截关闭逻辑保证永不销毁:
procedure TfrmMain.FormCreate(Sender: TObject); begin // 优先加载仪表盘 frmDashboard := TfrmDashboard.Create(Self); frmDashboard.Show; frmDashboard.OnClose := DashboardCloseEvent; end; procedure TfrmMain.DashboardCloseEvent(Sender: TObject; var Action: TCloseAction); begin // 拦截关闭操作,不销毁窗体 Action := caNone; end;
- 处理Z序逻辑,保证仪表盘永远在MDI子窗体最底层,不会遮挡业务子窗体。可以在公共的业务子窗体创建方法、仪表盘的
OnActivate事件中调用如下方法:
procedure TfrmMain.SetDashboardZOrder; begin if not Assigned(frmDashboard) then Exit; frmDashboard.BringToFront; frmDashboard.SendToBack; end;
- 在主窗体的
OnResize事件中添加代码,让仪表盘始终撑满MDI客户区,避免缩放留空隙。
方案2:分割布局+固定面板嵌入仪表盘(更稳定,推荐)
该方案不会出现MDI子窗体常见的Z序错乱、焦点异常、被误拖动覆盖等问题,体验更接近原生桌面应用,核心是把主窗体客户区分割为固定仪表盘区和MDI子窗体显示区:
- 在主窗体上放置一个
TPanel控件(命名为pnlDashboard),根据设计需求设置对齐方式:如果做侧边导航式仪表盘就设为alLeft,做顶部信息栏式仪表盘就设为alTop,提前调整好面板宽度/高度。 - 将快捷菜单、网格、功能链接等仪表盘需要的控件,直接放在
pnlDashboard上即可。 - 关键步骤:在主窗体
OnCreate事件中调整系统MDIClient窗口的位置,不要让它铺满整个主窗体,而是放在面板之外的剩余区域:
procedure TfrmMain.FormCreate(Sender: TObject); var hMDIClient: HWND; rcMainClient: TRect; begin hMDIClient := ClientHandle; // 获取MDI客户区窗口句柄 GetClientRect(Self.Handle, rcMainClient); // 如果pnlDashboard是左对齐,用下面这行调整MDIClient位置 SetWindowPos(hMDIClient, 0, pnlDashboard.Width, 0, rcMainClient.Width - pnlDashboard.Width, rcMainClient.Height, SWP_NOZORDER); // 如果pnlDashboard是顶部对齐,替换为下面这行 // SetWindowPos(hMDIClient, 0, 0, pnlDashboard.Height, // rcMainClient.Width, rcMainClient.Height - pnlDashboard.Height, SWP_NOZORDER); end;
- 在主窗体
OnResize事件中重复上述位置调整逻辑,保证窗体缩放时布局不会错位。
该方案下仪表盘区域完全独立,永远常驻不会被覆盖,MDI子窗体在专属区域内可以正常打开、排列、最大化最小化,不会出现显示异常。如果需要做全屏仪表盘切换效果,只需要动态修改pnlDashboard的对齐方式为alClient,同时把MDIClient窗口大小设为0即可,切换流畅度远高于MDI子窗体方案。
注意事项
- 不要在未调整
MDIClient位置的情况下,直接把控件放在主窗体客户区,否则必然会遮挡MDI子窗体。 - 如果使用方案1的常驻MDI子窗体,记得去掉子窗体的最大化、最小化、关闭按钮,避免用户误操作导致仪表盘覆盖其他业务窗口。
内容的提问来源于stack exchange,提问作者Ankush
相关产品推荐
相关产品推荐

