mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-14 12:48:58 +02:00
win32: a trial to correct application focus lose when local stay on top windows are involved (issue #0018494)
git-svn-id: trunk@30228 -
This commit is contained in:
parent
6c7c35c17b
commit
f37b868f3a
@ -1006,6 +1006,8 @@ begin
|
|||||||
WinProcess := True;
|
WinProcess := True;
|
||||||
NotifyUserInput := False;
|
NotifyUserInput := False;
|
||||||
|
|
||||||
|
// WriteLn('Msg: ', WM_To_String(Msg));
|
||||||
|
|
||||||
WindowInfo := GetWin32WindowInfo(Window);
|
WindowInfo := GetWin32WindowInfo(Window);
|
||||||
if WindowInfo^.isChildEdit then
|
if WindowInfo^.isChildEdit then
|
||||||
begin
|
begin
|
||||||
@ -2207,14 +2209,14 @@ begin
|
|||||||
begin
|
begin
|
||||||
//WriteLn('Restore');
|
//WriteLn('Restore');
|
||||||
RestoreStayOnTopFlags(Window);
|
RestoreStayOnTopFlags(Window);
|
||||||
if assigned(Application) then
|
if Assigned(Application) then
|
||||||
Application.IntfAppActivate;
|
Application.IntfAppActivate;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin // deactivated
|
begin // deactivated
|
||||||
//WriteLn('Remove');
|
//WriteLn('Remove');
|
||||||
RemoveStayOnTopFlags(Window);
|
RemoveStayOnTopFlags(Window);
|
||||||
if assigned(Application) then
|
if Assigned(Application) then
|
||||||
Application.IntfAppDeactivate;
|
Application.IntfAppDeactivate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -99,8 +99,8 @@ function AllocWindowInfo(Window: HWND): PWin32WindowInfo;
|
|||||||
function DisposeWindowInfo(Window: HWND): boolean;
|
function DisposeWindowInfo(Window: HWND): boolean;
|
||||||
function GetWin32WindowInfo(Window: HWND): PWin32WindowInfo;
|
function GetWin32WindowInfo(Window: HWND): PWin32WindowInfo;
|
||||||
|
|
||||||
procedure RemoveStayOnTopFlags(Window: HWND; ASystemTopAlso: Boolean = False);
|
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
|
||||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
procedure RestoreStayOnTopFlags(AppHandle: HWND);
|
||||||
procedure HidePopups(AppHandle: HWND);
|
procedure HidePopups(AppHandle: HWND);
|
||||||
procedure RestorePopups;
|
procedure RestorePopups;
|
||||||
|
|
||||||
@ -132,6 +132,7 @@ procedure UpdateWindowsVersion;
|
|||||||
type
|
type
|
||||||
PStayOnTopWindowsInfo = ^TStayOnTopWindowsInfo;
|
PStayOnTopWindowsInfo = ^TStayOnTopWindowsInfo;
|
||||||
TStayOnTopWindowsInfo = record
|
TStayOnTopWindowsInfo = record
|
||||||
|
AppHandle: HWND;
|
||||||
SystemTopAlso: Boolean;
|
SystemTopAlso: Boolean;
|
||||||
StayOnTopList: TList;
|
StayOnTopList: TList;
|
||||||
end;
|
end;
|
||||||
@ -920,76 +921,76 @@ end;
|
|||||||
|
|
||||||
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||||
var
|
var
|
||||||
AStyle: DWord;
|
|
||||||
StayOnTopWindowsInfo: PStayOnTopWindowsInfo absolute Param;
|
StayOnTopWindowsInfo: PStayOnTopWindowsInfo absolute Param;
|
||||||
lWindowInfo: PWin32WindowInfo;
|
lWindowInfo: PWin32WindowInfo;
|
||||||
lWinControl: TWinControl;
|
lWinControl: TWinControl;
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Result := True;
|
||||||
AStyle := GetWindowLong(Handle, GWL_EXSTYLE);
|
if ((GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST) <> 0) then
|
||||||
if (AStyle and WS_EX_TOPMOST) <> 0 then // if stay on top then
|
|
||||||
begin
|
begin
|
||||||
// Don't remove system-wide stay on top, unless desired
|
// Don't remove system-wide stay on top, unless desired
|
||||||
if not StayOnTopWindowsInfo^.SystemTopAlso then
|
if not StayOnTopWindowsInfo^.SystemTopAlso then
|
||||||
begin
|
begin
|
||||||
lWindowInfo := GetWin32WindowInfo(Handle);
|
lWindowInfo := GetWin32WindowInfo(Handle);
|
||||||
if (lWindowInfo <> nil) then
|
if Assigned(lWindowInfo) then
|
||||||
begin
|
begin
|
||||||
lWinControl := lWindowInfo^.WinControl;
|
lWinControl := lWindowInfo^.WinControl;
|
||||||
if (lWinControl <> nil) and (lWinControl is TCustomForm)
|
if Assigned(lWinControl) and
|
||||||
and (TCustomForm(lWinControl).FormStyle = fsSystemStayOnTop) then
|
(lWinControl is TCustomForm) and
|
||||||
|
(TCustomForm(lWinControl).FormStyle = fsSystemStayOnTop) then
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
StayOnTopWindowsInfo^.StayOnTopList.Add(Pointer(Handle));
|
StayOnTopWindowsInfo^.StayOnTopList.Add(Pointer(Handle));
|
||||||
SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
||||||
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOSENDCHANGING);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure RemoveStayOnTopFlags(Window: HWND; ASystemTopAlso: Boolean = False);
|
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
|
||||||
var
|
var
|
||||||
StayOnTopWindowsInfo: PStayOnTopWindowsInfo;
|
StayOnTopWindowsInfo: PStayOnTopWindowsInfo;
|
||||||
WindowInfo: PWin32WindowInfo;
|
WindowInfo: PWin32WindowInfo;
|
||||||
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
// WriteLn('RemoveStayOnTopFlags 1');
|
//WriteLn('RemoveStayOnTopFlags ', InRemoveStayOnTopFlags);
|
||||||
if InRemoveStayOnTopFlags = 0 then
|
if InRemoveStayOnTopFlags = 0 then
|
||||||
begin
|
begin
|
||||||
New(StayOnTopWindowsInfo);
|
New(StayOnTopWindowsInfo);
|
||||||
|
StayOnTopWindowsInfo^.AppHandle := AppHandle;
|
||||||
StayOnTopWindowsInfo^.SystemTopAlso := ASystemTopAlso;
|
StayOnTopWindowsInfo^.SystemTopAlso := ASystemTopAlso;
|
||||||
StayOnTopWindowsInfo^.StayOnTopList := TList.Create;
|
StayOnTopWindowsInfo^.StayOnTopList := TList.Create;
|
||||||
WindowInfo := GetWin32WindowInfo(Window);
|
WindowInfo := GetWin32WindowInfo(AppHandle);
|
||||||
WindowInfo^.StayOnTopList := StayOnTopWindowsInfo^.StayOnTopList;
|
WindowInfo^.StayOnTopList := StayOnTopWindowsInfo^.StayOnTopList;
|
||||||
EnumThreadWindows(GetWindowThreadProcessId(Window, nil),
|
EnumThreadWindows(GetWindowThreadProcessId(AppHandle, nil),
|
||||||
@EnumStayOnTopRemove, LPARAM(StayOnTopWindowsInfo));
|
@EnumStayOnTopRemove, LPARAM(StayOnTopWindowsInfo));
|
||||||
|
for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
|
||||||
|
SetWindowPos(HWND(WindowInfo^.StayOnTopList[I]), HWND_NOTOPMOST, 0, 0, 0, 0,
|
||||||
|
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_DRAWFRAME);
|
||||||
Dispose(StayOnTopWindowsInfo);
|
Dispose(StayOnTopWindowsInfo);
|
||||||
end;
|
end;
|
||||||
inc(InRemoveStayOnTopFlags);
|
inc(InRemoveStayOnTopFlags);
|
||||||
// WriteLn('RemoveStayOnTopFlags 2');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
procedure RestoreStayOnTopFlags(AppHandle: HWND);
|
||||||
var
|
var
|
||||||
WindowInfo: PWin32WindowInfo;
|
WindowInfo: PWin32WindowInfo;
|
||||||
I: integer;
|
I: integer;
|
||||||
begin
|
begin
|
||||||
// WriteLn('RestoreStayOnTopFlags 1');
|
//WriteLn('RestoreStayOnTopFlags ', InRemoveStayOnTopFlags);
|
||||||
if InRemoveStayOnTopFlags = 1 then
|
if InRemoveStayOnTopFlags = 1 then
|
||||||
begin
|
begin
|
||||||
WindowInfo := GetWin32WindowInfo(Window);
|
WindowInfo := GetWin32WindowInfo(AppHandle);
|
||||||
if WindowInfo^.StayOnTopList <> nil then
|
if WindowInfo^.StayOnTopList <> nil then
|
||||||
begin
|
begin
|
||||||
for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
|
for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
|
||||||
SetWindowPos(HWND(WindowInfo^.StayOnTopList.Items[I]),
|
SetWindowPos(HWND(WindowInfo^.StayOnTopList.Items[I]),
|
||||||
HWND_TOPMOST, 0, 0, 0, 0,
|
HWND_TOPMOST, 0, 0, 0, 0,
|
||||||
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOSENDCHANGING);
|
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_DRAWFRAME);
|
||||||
FreeAndNil(WindowInfo^.StayOnTopList);
|
FreeAndNil(WindowInfo^.StayOnTopList);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if InRemoveStayOnTopFlags > 0 then
|
if InRemoveStayOnTopFlags > 0 then
|
||||||
dec(InRemoveStayOnTopFlags);
|
dec(InRemoveStayOnTopFlags);
|
||||||
// WriteLn('RestoreStayOnTopFlags 2');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function EnumHidePopups(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
function EnumHidePopups(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||||
|
@ -493,14 +493,15 @@ begin
|
|||||||
if (lWindowInfo <> nil) then
|
if (lWindowInfo <> nil) then
|
||||||
begin
|
begin
|
||||||
lWinControl := lWindowInfo^.WinControl;
|
lWinControl := lWindowInfo^.WinControl;
|
||||||
if (lWinControl <> nil) and (lWinControl is TCustomForm)
|
if Assigned(lWinControl) and
|
||||||
and (TCustomForm(lWinControl).FormStyle in fsAllStayOnTop)
|
(lWinControl is TCustomForm) and
|
||||||
and not (csDesigning in TCustomForm(lWinControl).ComponentState) then
|
(TCustomForm(lWinControl).FormStyle in fsAllStayOnTop) and
|
||||||
|
not (csDesigning in lWinControl.ComponentState) then
|
||||||
list.Add(Pointer(Handle));
|
list.Add(Pointer(Handle));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure EnumStayOnTop(window: THandle; dstlist: TList);
|
procedure EnumStayOnTop(Window: THandle; dstlist: TList);
|
||||||
begin
|
begin
|
||||||
EnumThreadWindows(GetWindowThreadProcessId(Window, nil),
|
EnumThreadWindows(GetWindowThreadProcessId(Window, nil),
|
||||||
@EnumStayOnTopProc, LPARAM(dstlist));
|
@EnumStayOnTopProc, LPARAM(dstlist));
|
||||||
@ -508,6 +509,8 @@ end;
|
|||||||
|
|
||||||
class procedure TWin32WSCustomForm.SetFormStyle(const AForm: TCustomform;
|
class procedure TWin32WSCustomForm.SetFormStyle(const AForm: TCustomform;
|
||||||
const AFormStyle, AOldFormStyle: TFormStyle);
|
const AFormStyle, AOldFormStyle: TFormStyle);
|
||||||
|
const
|
||||||
|
WindowPosFlags = SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER;
|
||||||
var
|
var
|
||||||
toplist: TList;
|
toplist: TList;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@ -518,7 +521,7 @@ begin
|
|||||||
if (AOldFormStyle = fsNormal) and (AFormStyle in fsAllStayOnTop) then
|
if (AOldFormStyle = fsNormal) and (AFormStyle in fsAllStayOnTop) then
|
||||||
begin
|
begin
|
||||||
if not (csDesigning in AForm.ComponentState) then
|
if not (csDesigning in AForm.ComponentState) then
|
||||||
SetWindowPos(AForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE)
|
SetWindowPos(AForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, WindowPosFlags)
|
||||||
// From StayOnTop to normal
|
// From StayOnTop to normal
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -546,12 +549,10 @@ begin
|
|||||||
toplist := TList.Create;
|
toplist := TList.Create;
|
||||||
try
|
try
|
||||||
EnumStayOnTop(AForm.Handle, toplist);
|
EnumStayOnTop(AForm.Handle, toplist);
|
||||||
SetWindowPos(AForm.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
|
SetWindowPos(AForm.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, WindowPosFlags);
|
||||||
for i := 0 to toplist.Count - 1 do
|
for i := 0 to toplist.Count - 1 do
|
||||||
begin
|
|
||||||
if HWND(toplist[i]) <> AForm.Handle then
|
if HWND(toplist[i]) <> AForm.Handle then
|
||||||
SetWindowPos(HWND(toplist[i]), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
|
SetWindowPos(HWND(toplist[i]), HWND_TOPMOST, 0, 0, 0, 0, WindowPosFlags);
|
||||||
end;
|
|
||||||
finally
|
finally
|
||||||
toplist.Free;
|
toplist.Free;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user