【问题标题】:In Delphi, how to restore a minimized modal form that is not the main form在Delphi中,如何恢复不是主窗体的最小化模态窗体
【发布时间】:2022-02-03 23:30:21
【问题描述】:

在项目源中,我检测到我的应用程序的前一个实例,打开它然后终止新实例。
请记住,我在项目源代码中执行此操作。
该应用程序有一个主窗体,可以打开第二个模态窗体。如果应用程序最小化(或用户切换到另一个应用程序)时第二个模态表单未打开,则它可以正常工作。

旧的主窗体打开,新的实例终止。但是,如果第二个模态窗体被最小化,它的父主窗体也被最小化。这是很好的 UI 行为。

尝试通过新实例恢复模态表单时存在问题。我似乎无法恢复模态表单。
我可以恢复主窗体,但是模态窗体仍然有焦点,但被隐藏了。

这可以防止用户对现在可见的主窗体进行任何操作。从用户的角度来看,应用程序已挂起。

模态表单的标题不会改变,因此很容易掌握它。
该应用程序有一个 DataModule,它是首先创建的。在创建 DM 之后,我在项目源中进行所有重复的应用程序测试,但在任何其他表单之前,并且在 Application.Run 之前。
这样可以确保我获取的句柄来自现有的应用程序。
我试过了:

PreviousHandle := FindWindow(nil, PAnsiChar('Form Editor'))
  ShowWindow(PreviousHandle,SW_RESTORE);
  ShowWindow(PreviousHandle,SW_NORMAL);
  BringWindowToTop(PreviousHandle);

我从这个变体中得到的最好的结果是恢复主窗体。

当句柄用于模态表单时,它有时会在左下方显示为最小化表单。
我有时会这么说,因为我已经尝试了上面的很多变体,以至于我不记得这个代码示例的具体表现了。
我所知道的是,无论我从项目源中尝试过什么,都没有恢复模态表单,所以我尝试将自定义 Windows 消息发送到模态表单。
我知道消息到达并且消息处理程序捕获了它。示例:

  if not PostMessage(PreviousHandle,WM_RESTORE_FORM,PreviousHandle,0) then
      ShowMessage('Can''t automatically show the Form program. '+
            'Please click the taskbar icon.');

这是消息处理程序的外观。它是模态形式。如您所见,我将表单的句柄作为 Message 参数传递。我已经确认它到货了。
这是 TApplicationEvents OnMessage 事件中的代码:

procedure TfrmDisplayForm.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
var
  oldHwnd : THandle;
begin
  if Msg.message = WM_RESTORE_ACORD then
  begin
    oldHwnd := Msg.lParam;
    if ForceForegroundWindow(OldHwnd) then ShowMessage('true') else ShowMessage('False');
    Handled := True;
  end;
end;

这是被调用的函数。但是,我尝试了各种 ShowWindows(...) 组合,但都没有成功。其实这个函数也没有用。

function TfrmDisplayForm.ForceForegroundWindow(hWnd: THandle): BOOL;
var
  hCurWnd: THandle;
begin
{credit Peter Below}
  hCurWnd := GetForegroundWindow;
  AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
     GetCurrentThreadId, True);
  Result := SetForegroundWindow(hWnd);
  AttachThreadInput(GetWindowThreadProcessId(hCurWnd, nil),
     GetCurrentThreadId, False);
end;

我已经为此工作了几天,不知道我做错了什么。 问题:如何恢复模态形式?一定是可以的,因为点击任务栏图标后完美还原。

【问题讨论】:

    标签: forms delphi


    【解决方案1】:

    不要尝试恢复单个表单,而是使用TApplication.Restore

    调用TApplication.Restore会将所有应用程序窗口恢复到整个应用程序最小化之前的状态,就像单击应用程序的任务栏图标一样。

    PS:我也希望您不要让用户最小化单个模态表单。或者您可能还会遇到应用程序似乎卡住的问题。

    【讨论】:

    • 您是否建议在通过 Windows 消息执行的正在运行的应用程序的主窗体中执行此操作?
    • 您必须在应用程序消息循环中处理特定消息。由于显示了模式形式,在主窗体 Windows 级别上处理此类消息可能不起作用。不幸的是,我找不到一篇文章,其中包含我过去读过的一个很好的例子。
    • 那行不通。我将“Application.Restore”放在最小化主窗体的消息处理程序中。什么也没做。代码如下。 ` 过程 TfrmFormParserMain.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);如果 Msg.message = WM_RESTORE_ACORD 开始,则开始 Application.Restore; Application.ProcessMessages; ShowMessage('收到消息。');处理:=真;结尾;结尾; `
    • 抱歉,我不知道如何正确格式化示例代码。我按照说明使用了反引号,但没有运气。
    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 2012-11-07
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多