不用MDI方式,如何能让背景主窗体总是在本程序最底?
用SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE + SWP_NOSENDCHANGING); 会变成所有程序最底,效果不好。
也不能把其他窗体设为总在最前来解决,还有其他办法吗?

解决方案 »

  1.   

    我要多窗体切换操作,也不能用ShowModal
      

  2.   

    BForm.ParentWindow := MainForm.Handle;
      

  3.   

    下面的窗体总是呆在父窗体的上层。支持多个窗体切换unit StayOnTopFrm;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      CommFrm, ActnList, ImgList, ResChange;type
      TfrmStayOnTop = class(TForm)
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        FMoved: boolean;
        newProc: pointer;
        oldProc: pointer;
        procedure OwnerWndProc(var Message: TMessage);
        //procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
        //procedure WMMove(var Message: TMessage); message WM_MOVE;
      protected
        class function CanMultiInstance: boolean;  virtual;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
      end;const
      MM_CUSTOMMESSAGE = WM_USER+1076;implementationconst
      MM_PROCCHANGE = WM_USER + 127;{$R *.DFM}{ TfrmStayOnTop }constructor TfrmStayOnTop.Create(AOwner: TComponent);
    var
      a: integer;
    begin
      if not (AOwner is TForm) then Raise Exception.Create('The Owner Must Be a Form');
      a := Integer(ClassInfo);
      if SendMessage(TWinControl(AOwner).handle, MM_CUSTOMMESSAGE, -$FF, a)=1 then
        if not CanMultiInstance then
        begin
          abort;
        end;  inherited;
      newProc := MakeObjectInstance(OwnerWndProc);
      oldProc := Pointer(SetWindowLong(TWinControl(aOwner).handle, GWL_WNDPROC, integer(newProc)));
    end;procedure TfrmStayOnTop.OwnerWndProc(var Message: TMessage);
    begin
      message.Result := CallWindowProc(oldProc, TWinControl(Owner).handle, message.Msg, message.WParam, message.LParam);
      case message.Msg of
        WM_WINDOWPOSCHANGED:
          SetWindowPos(handle, PWINDOWPOS(message.lParam).hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE + SWP_NOSENDCHANGING);
        WM_DESTROY:
          //SendMessage(self.handle, WM_CLOSE, 0, 0);
          Self.free;
        MM_PROCCHANGE:
          if oldProc = Pointer(Message.wParam) then
          begin
            oldProc := Pointer(Message.lParam);
            Message.Result := 1;
          end;
        MM_CUSTOMMESSAGE:
          if Message.WParam = -$FF then
            if Message.LParam = Integer(ClassInfo) then
            begin
              SetWindowPos(handle, PWINDOWPOS(message.lParam).hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE + SWP_NOSENDCHANGING);
              Message.Result := 1;
            end;
      end;
    end;procedure TfrmStayOnTop.FormDestroy(Sender: TObject);
    begin
      if SendMessage(TWinControl(Owner).handle, MM_PROCCHANGE, integer(newProc), integer(oldProc)) = 0 then
        SetWindowLong(TWinControl(Owner).handle, GWL_WNDPROC, integer(oldProc));
      inherited;
    end;
    {
    procedure TfrmStayOnTop.CMShowingChanged(var Message: TMessage);
    var
      r, r1: TRect;
    begin
      if Showing then
      begin
        if not FMoved and (WindowState=wsNormal) then
        begin
          Windows.GetWindowRect(TWinControl(Owner).handle, r);
          Windows.GetWindowRect(handle, r1);
          Left := r.Right-(r1.Right-r1.left);
          Top := r.bottom-(r1.bottom-r1.top);
        end;
        PubYSBZ.AnimateShowWindow(self);
        ShowWindow(handle, SW_HIDE);
      end
      else
        PubYSBZ.AnimateShowWindow(self, false);
      FMoved := true;
      inherited;
    end;procedure TfrmStayOnTop.WMMove(var Message: TMessage);
    begin
      inherited;
    end;
    }
    class function TfrmStayOnTop.CanMultiInstance: boolean;
    begin
      result := true;
    end;end.