SetWindowPos不起作用原因,该如何解决
SetWindowPos不起作用原因
新建个工程,在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,不明白什么原因,求指教,谢谢!
------解决方案--------------------
Form1:= TForm1.Create(nil);
这样建立, application 就管不上Tform1了
Form1:= TForm1.Create(nil);
Form1.ShowModal;
Form1.Free;
这已经是模态窗口了
------解决方案--------------------
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;
新建个工程,在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,不明白什么原因,求指教,谢谢!
------解决方案--------------------
Form1:= TForm1.Create(nil);
这样建立, application 就管不上Tform1了
Form1:= TForm1.Create(nil);
Form1.ShowModal;
Form1.Free;
这已经是模态窗口了
------解决方案--------------------
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;