SetWindowPos不起作用原因

pengderun 2013-09-05 03:41:21
新建个工程,在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,不明白什么原因,求指教,谢谢!
...全文
1441 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengderun 2013-09-09
  • 打赏
  • 举报
回复
引用 3 楼 s11ss 的回复:
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;
感谢s11ss指点,看了下这里面的代码好像只有mainform才能置顶?不是mainform要置顶的话还有什么办法吗?
s11ss 2013-09-09
  • 打赏
  • 举报
回复
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;
pengderun 2013-09-06
  • 打赏
  • 举报
回复
SetWindowPos起不起作用和application有关?不太明白
simonhehe 2013-09-06
  • 打赏
  • 举报
回复
Form1:= TForm1.Create(nil); 这样建立, application 就管不上Tform1了 Form1:= TForm1.Create(nil); Form1.ShowModal; Form1.Free; 这已经是模态窗口了
s11ss 2013-09-06
  • 打赏
  • 举报
回复
总之就是在你调用SetWindowPos置顶后,Application又调用SetWindowPos取消了置顶。
s11ss 2013-09-06
  • 打赏
  • 举报
回复
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;

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧