新建个工程,在TForm1.Create里面写了句代码:
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)如果.dpr单元是
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
SetWindowPos置顶就起作用,
后来我改.dpr单元成
  Form1:= TForm1.Create(nil);
  Form1.ShowModal;
  Form1.Free;
SetWindowPos就没起作用了,但是返回值还是true,不明白什么原因,求指教,谢谢!

解决方案 »

  1.   

    Form1:= TForm1.Create(nil);
    这样建立,  application 就管不上Tform1了Form1:= TForm1.Create(nil);
      Form1.ShowModal;
      Form1.Free;
    这已经是模态窗口了
      

  2.   

    SetWindowPos起不起作用和application有关?不太明白
      

  3.   

    Application在响应WM_ACTIVATEAPP时,调用了NormalizeTopMosts,而它调用DoNormalizeTopMosts,其内部EnumWindows的回调函数GetTopMostWindows中,判断了Application.MainForm = nil,如果是nil则将窗口句柄加入Application.FTopMostList,EnumWindows返回后,调用SetWindowPos改变FTopMostList中的窗口的Z-Order。在Forms.pas可找到相关代码:
    function GetTopMostWindows(Handle: HWND; Info: Pointer): BOOL; stdcall;
    begin
      Result := True;
      if GetWindow(Handle, GW_OWNER) = Application.Handle then
        if (GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0) and
          ((Application.MainForm = nil) or PTopMostEnumInfo(Info)^.IncludeMain or
          (Handle <> Application.MainForm.Handle)) then
          Application.FTopMostList.Add(Pointer(Handle))
        else
        begin
          PTopMostEnumInfo(Info)^.TopWindow := Handle;
          Result := False;
        end;
    end;procedure TApplication.DoNormalizeTopMosts(IncludeMain: Boolean);
    var
      I: Integer;
      Info: TTopMostEnumInfo;
    begin
      if Application.Handle <> 0 then
      begin
        if FTopMostLevel = 0 then
        begin
          Info.TopWindow := Handle;
          Info.IncludeMain := IncludeMain;
          EnumWindows(@GetTopMostWindows, Longint(@Info));
          if FTopMostList.Count <> 0 then
          begin
            Info.TopWindow := GetWindow(Info.TopWindow, GW_HWNDPREV);
            if GetWindowLong(Info.TopWindow, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0 then
              Info.TopWindow := HWND_NOTOPMOST;
            for I := FTopMostList.Count - 1 downto 0 do
              SetWindowPos(HWND(FTopMostList[I]), Info.TopWindow, 0, 0, 0, 0,
                SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER);
          end;
        end;
        Inc(FTopMostLevel);
      end;
    end;
      

  4.   

    总之就是在你调用SetWindowPos置顶后,Application又调用SetWindowPos取消了置顶。
      

  5.   


    感谢s11ss指点,看了下这里面的代码好像只有mainform才能置顶?不是mainform要置顶的话还有什么办法吗?
      

  6.   

    Application在响应WM_ACTIVATEAPP时,调用了NormalizeTopMosts之后,还会调用PostMessage(FHandle, CM_DEACTIVATE, 0, 0),会触发Application的OnDeactivate事件,在此事件中重新置顶即可。procedure TForm1.doit(Sender: TObject);
    begin
    SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
    SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
    application.OnDeactivate := doit;
    end;