Delphi 子窗体始终位于主窗体的上方

Delphi 子窗体始终位于主窗体的上方,delphi,delphi-2007,Delphi,Delphi 2007,我使用的是Delphi2007,每次我都使用这样的代码创建一个新表单 var Child : TFrmChild; begin Child:=TFrmChild.Create(Self); Child.Show(); end; 子窗体将显示并显示在所有其他窗体的上方,这是可以的,但单击主窗体时,子窗体将停留在主窗体的上方。所以我有两个问题 为什么即使单击主窗体,子窗体仍位于主窗体上方 当我点击主窗体时,如何使它保持在所有其他窗体之上 谢谢 更新 这是子窗体的dfm object F

我使用的是Delphi2007,每次我都使用这样的代码创建一个新表单

var
  Child : TFrmChild;
begin
  Child:=TFrmChild.Create(Self);
  Child.Show();
end;
子窗体将显示并显示在所有其他窗体的上方,这是可以的,但单击主窗体时,子窗体将停留在主窗体的上方。所以我有两个问题

  • 为什么即使单击主窗体,子窗体仍位于主窗体上方
  • 当我点击主窗体时,如何使它保持在所有其他窗体之上
  • 谢谢

    更新

    这是子窗体的dfm

    object FrmChild: TFrmChild
      Left = 549
      Top = 308
      Caption = 'FrmChild'
      ClientHeight = 228
      ClientWidth = 213
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
    end
    
  • 您的子窗体可能始终位于顶部窗体上
  • 您可以使用MDI表单(man表单)和MDI子表单(子表单)。或者你可以使用MTI,检查这篇文章
  • 这一情况已向秘书处报告。简单的解决方法是设置

      Application.MainFormOnTaskbar := False;
    
    在项目的.dpr文件中。缺点是失去了一些Vista功能


    还有另一种解决方法,但它很笨拙,并且还有其他问题(请参见QC的链接)。

    您有两个顶级窗口。主窗体是子窗体的所有者。拥有的窗口总是出现在其所有者的上方,这只是windows的规则之一

    请注意,我指的是Windows概念,而不是Delphi概念

    本主题解释了规则。关键的声明是:

    拥有的窗口在z顺序中始终高于其所有者


    至于如何让你的应用程序表现不同,我不太确定。如果您将您的子窗体设为无主窗体,则它将有自己的任务栏按钮,并且当主窗体最小化时,它不会被最小化。例如。

    后期回答-我刚刚解决了这个问题。我们想要Aero风格的ALT-TAB和WIN-TAB功能,但MainFormOnTaskBar导致第三方组件出现一些问题。(LMD停靠-如果主窗体上有停靠站点,子窗体上有停靠站点,则拖动子窗体上的停靠项会将主窗体带到前面)

    解决办法是:

    • 在CreateParams中将Params.WndParent设置为0
    • 使用管理任务栏选项卡。这还会将窗口添加到ALT-TAB和WIN-TAB处理程序中
    TaskBarList.pas

    unit TaskbarList;
    
    interface
    
    uses
      Windows, Messages,
      CommCtrl,
      ShlObj,
      SysUtils, Classes, ComCtrls;
    
    const
      SID_ITaskbarList                            = '{56FDF342-FD6D-11D0-958A-006097C9A090}';
      SID_ITaskbarList2                           = '{602D4995-B13A-429B-A66E-1935E44F4317}';
      SID_ITaskbarList3                           = '{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}';
      SID_ITaskbarList4                           = '{C43DC798-95D1-4BEA-9030-BB99E2983A1A}';
    
      CLSID_TaskbarList: TGUID                            = '{56FDF344-FD6D-11d0-958A-006097C9A090}';
    
    type
      ITaskbarList = interface(IUnknown)
        [SID_ITaskbarList]
        function HrInit: HRESULT; stdcall;
        function AddTab(hwnd: HWND): HRESULT; stdcall;
        function DeleteTab(hwnd: HWND): HRESULT; stdcall;
        function ActivateTab(hwnd: HWND): HRESULT; stdcall;
        function SetActiveAlt(hwnd: HWND): HRESULT; stdcall;
      end;
    
      ITaskbarList2 = interface(ITaskbarList)
        [SID_ITaskbarList2]
        function MarkFullscreenWindow(hwnd: HWND; fFullscreen: BOOL): HRESULT; stdcall;
      end;
    
    type
      THUMBBUTTON = record
        dwMask: DWORD;
        iId: UINT;
        iBitmap: UINT;
        hIcon: HICON;
        szTip: packed array[0..259] of WCHAR;
        dwFlags: DWORD;
      end;
      tagTHUMBBUTTON = THUMBBUTTON;
      TThumbButton = THUMBBUTTON;
      PThumbButton = ^TThumbButton;
    
    // THUMBBUTTON flags
    const
      THBF_ENABLED        =  $0000;
      THBF_DISABLED       =  $0001;
      THBF_DISMISSONCLICK =  $0002;
      THBF_NOBACKGROUND   =  $0004;
      THBF_HIDDEN         =  $0008;
      THBF_NONINTERACTIVE = $10;
    // THUMBBUTTON mask
      THB_BITMAP          =  $0001;
      THB_ICON            =  $0002;
      THB_TOOLTIP         =  $0004;
      THB_FLAGS           =  $0008;
      THBN_CLICKED        =  $1800;
    
    const
      TBPF_NOPROGRESS    = 0;
      TBPF_INDETERMINATE = $1;
      TBPF_NORMAL        = $2;
      TBPF_ERROR         = $4;
      TBPF_PAUSED        = $8;
    
      TBATF_USEMDITHUMBNAIL   = $1;
      TBATF_USEMDILIVEPREVIEW = $2;
    
    const
      STPF_NONE                       = $00000000;
      STPF_USEAPPTHUMBNAILALWAYS      = $00000001;
      STPF_USEAPPTHUMBNAILWHENACTIVE  = $00000002;
      STPF_USEAPPPEEKALWAYS           = $00000004;
      STPF_USEAPPPEEKWHENACTIVE       = $00000008;
    
    
    type
      ITaskbarList3 = interface(ITaskbarList2)
        [SID_ITaskbarList3]
        function SetProgressValue(hwnd: HWND; ullCompleted: ULONGLONG;
          ullTotal: ULONGLONG): HRESULT; stdcall;
        function SetProgressState(hwnd: HWND; tbpFlags: Integer): HRESULT; stdcall;
        function RegisterTab(hwndTab: HWND; hwndMDI: HWND): HRESULT; stdcall;
        function UnregisterTab(hwndTab: HWND): HRESULT; stdcall;
        function SetTabOrder(hwndTab: HWND; hwndInsertBefore: HWND): HRESULT; stdcall;
        function SetTabActive(hwndTab: HWND; hwndMDI: HWND;
          tbatFlags: Integer): HRESULT; stdcall;
        function ThumbBarAddButtons(hwnd: HWND; cButtons: UINT;
          pButton: PThumbButton): HRESULT; stdcall;
        function ThumbBarUpdateButtons(hwnd: HWND; cButtons: UINT;
          pButton: PThumbButton): HRESULT; stdcall;
        function ThumbBarSetImageList(hwnd: HWND; himl: HIMAGELIST): HRESULT; stdcall;
        function SetOverlayIcon(hwnd: HWND; hIcon: HICON;
          pszDescription: LPCWSTR): HRESULT; stdcall;
        function SetThumbnailTooltip(hwnd: HWND; pszTip: LPCWSTR): HRESULT; stdcall;
        function SetThumbnailClip(hwnd: HWND; var prcClip: TRect): HRESULT; stdcall;
      end;
    
      ITaskbarList4 = interface(ITaskbarList3)
        [SID_ITaskbarList4]
    
        function SetTabProperties (hwnd: HWND; stpFlags: Integer): HRESULT; stdcall;
    
      end;
    
    implementation
    
    end.
    
    BaseForm.pas:

    unit BaseForm;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,
      TaskBarList;
    
    type
      TBaseForm = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        class var FTaskBarList: ITaskbarList;
      protected
        class function TaskBarList: ITaskbarList;
        procedure DoShow;override;
        procedure DoHide;override;
        procedure Activate;override;
        procedure CreateParams(var Params: TCreateParams); override;
      public
        constructor Create(AOwner: TComponent); override;
      end;
    
    var
      BaseForm: TBaseForm;
    
    implementation
    
    uses
      ComObj;
    
    {$R *.dfm}
    
    { TBaseForm }
    
    procedure TBaseForm.Activate;
    begin
      inherited;
      TaskBarList.ActivateTab(Handle);
    end;
    
    procedure TBaseForm.Button1Click(Sender: TObject);
    begin
      TBaseForm.Create(Self).Show;
    end;
    
    constructor TBaseForm.Create(AOwner: TComponent);
    begin
      inherited;
      // remove taskbar button for Application.Handle
      TaskBarList.DeleteTab(Application.Handle);
    end;
    
    procedure TBaseForm.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      if (Parent = nil) and (ParentWindow = 0) then // don't use on docked Windows
        Params.WndParent := 0;
    end;
    
    procedure TBaseForm.DoHide;
    begin
      inherited;
      TaskBarList.DeleteTab(Handle);
    end;
    
    procedure TBaseForm.DoShow;
    begin
      inherited;
      TaskBarList.AddTab(Handle);
    end;
    
    class function TBaseForm.TaskBarList: ITaskbarList;
    var
      pIntF: IInterface;
    begin
      if not assigned(FTaskBarList) then
      begin
        pIntF := CreateComObject(CLSID_TaskbarList);
        pIntF.QueryInterface(ITaskBarList, FTaskBarList);
    
        FTaskBarList.HrInit;
      end;
      Result := FTaskBarList;
    end;
    
    end.
    

    注意:我没有使用OleCheck检查HRESULT,因为我希望它在字段中以静默方式失败。

    谢谢,但是我的子窗体的
    formstyle
    属性设置为
    fsNormal
    ,我也不想使用MDI接口。您不需要始终处于顶部的窗体来实现这一点。您只需将子窗体归主窗体所有(在windows意义上)。感谢该链接,如果我将
    应用程序设置为
    ,则windows Vista功能可能会丢失。MainFormOnTaskbar
    false
    ?虽然您已向QC报告了这一点,但您是正确的,您应该注意到,它已被关闭,原因是其行为符合设计要求。@DelphiNewbie-我不使用Vista,所以我不知道,但我相信它与应用程序在任务栏上的显示方式有关。@DelphiNewbie-其中有对MainFormOnTaskbar的描述,它可能位于QualityCentral(bug db)上,但这不是一个bug,这是预期的Windows平台行为。