mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-01 08:13:28 +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;
|
||||
NotifyUserInput := False;
|
||||
|
||||
// WriteLn('Msg: ', WM_To_String(Msg));
|
||||
|
||||
WindowInfo := GetWin32WindowInfo(Window);
|
||||
if WindowInfo^.isChildEdit then
|
||||
begin
|
||||
@ -2207,15 +2209,15 @@ begin
|
||||
begin
|
||||
//WriteLn('Restore');
|
||||
RestoreStayOnTopFlags(Window);
|
||||
if assigned(Application) then
|
||||
Application.IntfAppActivate;
|
||||
if Assigned(Application) then
|
||||
Application.IntfAppActivate;
|
||||
end
|
||||
else
|
||||
begin // deactivated
|
||||
//WriteLn('Remove');
|
||||
RemoveStayOnTopFlags(Window);
|
||||
if assigned(Application) then
|
||||
Application.IntfAppDeactivate;
|
||||
if Assigned(Application) then
|
||||
Application.IntfAppDeactivate;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -99,8 +99,8 @@ function AllocWindowInfo(Window: HWND): PWin32WindowInfo;
|
||||
function DisposeWindowInfo(Window: HWND): boolean;
|
||||
function GetWin32WindowInfo(Window: HWND): PWin32WindowInfo;
|
||||
|
||||
procedure RemoveStayOnTopFlags(Window: HWND; ASystemTopAlso: Boolean = False);
|
||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
||||
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
|
||||
procedure RestoreStayOnTopFlags(AppHandle: HWND);
|
||||
procedure HidePopups(AppHandle: HWND);
|
||||
procedure RestorePopups;
|
||||
|
||||
@ -132,6 +132,7 @@ procedure UpdateWindowsVersion;
|
||||
type
|
||||
PStayOnTopWindowsInfo = ^TStayOnTopWindowsInfo;
|
||||
TStayOnTopWindowsInfo = record
|
||||
AppHandle: HWND;
|
||||
SystemTopAlso: Boolean;
|
||||
StayOnTopList: TList;
|
||||
end;
|
||||
@ -903,7 +904,7 @@ var
|
||||
WindowInfo: PWin32WindowInfo;
|
||||
begin
|
||||
WindowInfo := PWin32WindowInfo(Windows.GetProp(Window, PChar(PtrUInt(WindowInfoAtom))));
|
||||
Result := Windows.RemoveProp(Window, PChar(PtrUInt(WindowInfoAtom)))<>0;
|
||||
Result := Windows.RemoveProp(Window, PChar(PtrUInt(WindowInfoAtom))) <> 0;
|
||||
if Result then
|
||||
begin
|
||||
WindowInfo^.StayOnTopList.Free;
|
||||
@ -920,76 +921,76 @@ end;
|
||||
|
||||
function EnumStayOnTopRemove(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||
var
|
||||
AStyle: DWord;
|
||||
StayOnTopWindowsInfo: PStayOnTopWindowsInfo absolute Param;
|
||||
lWindowInfo: PWin32WindowInfo;
|
||||
lWinControl: TWinControl;
|
||||
begin
|
||||
Result := True;
|
||||
AStyle := GetWindowLong(Handle, GWL_EXSTYLE);
|
||||
if (AStyle and WS_EX_TOPMOST) <> 0 then // if stay on top then
|
||||
if ((GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST) <> 0) then
|
||||
begin
|
||||
// Don't remove system-wide stay on top, unless desired
|
||||
if not StayOnTopWindowsInfo^.SystemTopAlso then
|
||||
begin
|
||||
lWindowInfo := GetWin32WindowInfo(Handle);
|
||||
if (lWindowInfo <> nil) then
|
||||
if Assigned(lWindowInfo) then
|
||||
begin
|
||||
lWinControl := lWindowInfo^.WinControl;
|
||||
if (lWinControl <> nil) and (lWinControl is TCustomForm)
|
||||
and (TCustomForm(lWinControl).FormStyle = fsSystemStayOnTop) then
|
||||
if Assigned(lWinControl) and
|
||||
(lWinControl is TCustomForm) and
|
||||
(TCustomForm(lWinControl).FormStyle = fsSystemStayOnTop) then
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
procedure RemoveStayOnTopFlags(Window: HWND; ASystemTopAlso: Boolean = False);
|
||||
procedure RemoveStayOnTopFlags(AppHandle: HWND; ASystemTopAlso: Boolean = False);
|
||||
var
|
||||
StayOnTopWindowsInfo: PStayOnTopWindowsInfo;
|
||||
WindowInfo: PWin32WindowInfo;
|
||||
I: Integer;
|
||||
begin
|
||||
// WriteLn('RemoveStayOnTopFlags 1');
|
||||
//WriteLn('RemoveStayOnTopFlags ', InRemoveStayOnTopFlags);
|
||||
if InRemoveStayOnTopFlags = 0 then
|
||||
begin
|
||||
New(StayOnTopWindowsInfo);
|
||||
StayOnTopWindowsInfo^.AppHandle := AppHandle;
|
||||
StayOnTopWindowsInfo^.SystemTopAlso := ASystemTopAlso;
|
||||
StayOnTopWindowsInfo^.StayOnTopList := TList.Create;
|
||||
WindowInfo := GetWin32WindowInfo(Window);
|
||||
WindowInfo := GetWin32WindowInfo(AppHandle);
|
||||
WindowInfo^.StayOnTopList := StayOnTopWindowsInfo^.StayOnTopList;
|
||||
EnumThreadWindows(GetWindowThreadProcessId(Window, nil),
|
||||
EnumThreadWindows(GetWindowThreadProcessId(AppHandle, nil),
|
||||
@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);
|
||||
end;
|
||||
inc(InRemoveStayOnTopFlags);
|
||||
// WriteLn('RemoveStayOnTopFlags 2');
|
||||
end;
|
||||
|
||||
procedure RestoreStayOnTopFlags(Window: HWND);
|
||||
procedure RestoreStayOnTopFlags(AppHandle: HWND);
|
||||
var
|
||||
WindowInfo: PWin32WindowInfo;
|
||||
I: integer;
|
||||
begin
|
||||
// WriteLn('RestoreStayOnTopFlags 1');
|
||||
//WriteLn('RestoreStayOnTopFlags ', InRemoveStayOnTopFlags);
|
||||
if InRemoveStayOnTopFlags = 1 then
|
||||
begin
|
||||
WindowInfo := GetWin32WindowInfo(Window);
|
||||
WindowInfo := GetWin32WindowInfo(AppHandle);
|
||||
if WindowInfo^.StayOnTopList <> nil then
|
||||
begin
|
||||
for I := 0 to WindowInfo^.StayOnTopList.Count - 1 do
|
||||
SetWindowPos(HWND(WindowInfo^.StayOnTopList.Items[I]),
|
||||
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);
|
||||
end;
|
||||
end;
|
||||
if InRemoveStayOnTopFlags > 0 then
|
||||
dec(InRemoveStayOnTopFlags);
|
||||
// WriteLn('RestoreStayOnTopFlags 2');
|
||||
end;
|
||||
|
||||
function EnumHidePopups(Handle: HWND; Param: LPARAM): WINBOOL; stdcall;
|
||||
|
@ -493,14 +493,15 @@ begin
|
||||
if (lWindowInfo <> nil) then
|
||||
begin
|
||||
lWinControl := lWindowInfo^.WinControl;
|
||||
if (lWinControl <> nil) and (lWinControl is TCustomForm)
|
||||
and (TCustomForm(lWinControl).FormStyle in fsAllStayOnTop)
|
||||
and not (csDesigning in TCustomForm(lWinControl).ComponentState) then
|
||||
if Assigned(lWinControl) and
|
||||
(lWinControl is TCustomForm) and
|
||||
(TCustomForm(lWinControl).FormStyle in fsAllStayOnTop) and
|
||||
not (csDesigning in lWinControl.ComponentState) then
|
||||
list.Add(Pointer(Handle));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure EnumStayOnTop(window: THandle; dstlist: TList);
|
||||
procedure EnumStayOnTop(Window: THandle; dstlist: TList);
|
||||
begin
|
||||
EnumThreadWindows(GetWindowThreadProcessId(Window, nil),
|
||||
@EnumStayOnTopProc, LPARAM(dstlist));
|
||||
@ -508,9 +509,11 @@ end;
|
||||
|
||||
class procedure TWin32WSCustomForm.SetFormStyle(const AForm: TCustomform;
|
||||
const AFormStyle, AOldFormStyle: TFormStyle);
|
||||
const
|
||||
WindowPosFlags = SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER;
|
||||
var
|
||||
toplist : TList;
|
||||
i : Integer;
|
||||
toplist: TList;
|
||||
i: Integer;
|
||||
begin
|
||||
// Some changes don't require RecreateWnd
|
||||
|
||||
@ -518,7 +521,7 @@ begin
|
||||
if (AOldFormStyle = fsNormal) and (AFormStyle in fsAllStayOnTop) then
|
||||
begin
|
||||
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
|
||||
end
|
||||
else
|
||||
@ -546,12 +549,10 @@ begin
|
||||
toplist := TList.Create;
|
||||
try
|
||||
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
|
||||
begin
|
||||
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);
|
||||
end;
|
||||
SetWindowPos(HWND(toplist[i]), HWND_TOPMOST, 0, 0, 0, 0, WindowPosFlags);
|
||||
finally
|
||||
toplist.Free;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user