代码之家  ›  专栏  ›  技术社区  ›  durumdara

Delphi-如何防止窗体/MsgBoxes在以前的窗体下移动?

  •  15
  • durumdara  · 技术社区  · 15 年前

    在windows98时代之后,我们已经经历过很多次了,一些对话框失去了Z顺序,回到了以前的形式。

    Dialog1.ShowModal;
    
    Dialog1.OnClickButton() : ShowMessage('anything');
    

    用户对此感到困惑,他们说:我的应用程序冻结了!!! 但是如果他们使用Alt+Tab移动到另一个应用程序并返回,焦点将返回到MessageBox,它将是前台窗口。

    有人知道这件事吗?是Windows的错误吗?你怎么能预防呢?怎么抓住这个?

    感谢您的帮助: dd公司


    我真的说过在Win98之后,所以所有的操作系统(Win7也)都会受到这个问题的影响。 我们使用了delphi6prof,因此这些属性不适用于默认窗体。

    有人说消息对话框可以通过MessageBox+MB\u进行控制。 这是个好消息,但是我们有很多旧的表单和组件,第三方工具。

    因此,用表格的替代来实现一个全新的应用是一项艰巨的工作。

    但我们会尝试这样做。

    我认为答案是这是一个半应用程序问题和半Windows问题。如果Windows有时能处理这个问题,有时却不能——那似乎就是Windows的一个bug。 但是,如果我们能强迫良好的模式窗口,那么这是一个编程错误。

    有人能给我解释一下WS\u弹出标志的含义吗? 有没有副作用?

    谢谢: dd公司

    4 回复  |  直到 10 年前
        1
  •  16
  •   Craig Stuntz    15 年前

    PopupMode and PopupParent properties 是给你的。

    Dialog1.PopupMode := pmExplicit;
    Dialog1.PopupParent := self;
    Dialog1.ShowModal;
    

    这将告诉Windows正确的Z顺序。

        2
  •  7
  •   Warren P    15 年前

    interface
      TMyForm = Class(TForm)
      protected
        procedure CreateParams(var Para: TCreateParams); override;
      end;
    ...
    implementation
    ...
    procedure TMyForm.CreateParams(var Para: TCreateParams);
    begin
      inherited;
      Para.Style := Para.Style or WS_POPUP;
      { WinXP Window manager requires this for proper Z-Ordering }
      // Para.WndParent:=GetActiveWindow;
      Para.WndParent := Application.MainForm.Handle;
    end;
    

    对于消息框,请在标记中包含MB\ U最上面的部分:

    Application.MessageBox(PChar(amessage), PChar(atitle),    otherflags or MB_TOPMOST);
    
        3
  •  0
  •   Mike Versteeg    15 年前

    首先我想说清楚的是,海报IMHO没有使用windows98,他写的是“windows98时代之后”,我理解这意味着他在98之后的Windows版本上有这个问题。

    如果我能理解z-order的支持哪里出了问题,这将非常有帮助,因为它可能会提供一个如何避免它的线索。

        4
  •  0
  •   Jerry Gagnon    14 年前

    我最近使用的一个技巧是在创建每个表单时应用这两行代码:

    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
      WS_EX_APPWINDOW or WS_EX_TOPMOST);
    SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);
    

    对于我的主窗体,我使用以下行:

    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
      WS_EX_TOPMOST);
    

    我还使用此函数来帮助构建自定义对话框(我为每种类型的对话框创建了一个新函数-错误、确认等):

    function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
      const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
    begin
      Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
      with Result do
        begin
          SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
            WS_EX_APPWINDOW or WS_EX_TOPMOST);
          SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
          FormStyle := fsStayOnTop;
          BringToFront;
        end;
    end;
    

    这个 FormStyle := fsStayOnTop; 当然,part是可选的,但是我使用它来确保我的确认和错误对话框对用户总是可见的。

    这似乎是一个工作,但净效果是,我不再担心形式意外地隐藏在其他形式。

    推荐文章