-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfunctions.windowfocus.pas
98 lines (80 loc) · 2.81 KB
/
functions.windowfocus.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
unit functions.windowfocus;
interface
uses
Windows, Messages, Forms, MultiMon, SysUtils, ShellApi;
type
TWindowFocusHelper = class
private
class procedure ForceForegroundWindow(hwnd: HWND);
class function IsWindowFullscreen(hwnd: HWND): Boolean;
public
class procedure FocusWindow(FormHandle: HWND);
end;
implementation
procedure SwitchToThisWindow(hWnd: HWND; fUnknown: BOOL); external 'user32.dll';
class procedure TWindowFocusHelper.ForceForegroundWindow(hwnd: HWND);
var
HForegroundThread, HAppThread: DWORD;
HActiveWindow: THandle;
FClientId: DWORD;
begin
TForm(hwnd).Show;
HActiveWindow := GetForegroundWindow();
if HActiveWindow <> hwnd then
begin
HForegroundThread := GetWindowThreadProcessId(HActiveWindow, @FClientId);
AllowSetForegroundWindow(FClientId);
HAppThread := GetCurrentThreadId;
if not SetForegroundWindow(hwnd) then
SwitchToThisWindow(GetDesktopWindow, True);
// magic part to switch correctly to our window
if HForegroundThread <> HAppThread then
begin
AttachThreadInput(HForegroundThread, HAppThread, True);
BringWindowToTop(hwnd);
Windows.SetFocus(hwnd);
AttachThreadInput(HForegroundThread, HAppThread, False);
end;
var rct: TRect;
Windows.GetWindowRect(HActiveWindow, rct);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, {SWP_ASYNCWINDOWPOS or }SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW);
var helperPath := ExtractFilePath(ParamStr(0))+'focusHelper.exe';
if FileExists(helperPath) then
ShellExecute(0, 'OPEN', PChar(ExtractFilePath(ParamStr(0))+'focusHelper.exe'), nil, nil, SW_SHOW);
end;
end;
class function TWindowFocusHelper.IsWindowFullscreen(hwnd: HWND): Boolean;
var
WinRect: TRect;
Monitor: HMonitor;
MonInfo: TMonitorInfo;
begin
GetWindowRect(hwnd, WinRect);
Monitor := MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
MonInfo.cbSize := SizeOf(MonInfo);
GetMonitorInfo(Monitor, @MonInfo);
Result := (WinRect.Left = MonInfo.rcMonitor.Left) and
(WinRect.Top = MonInfo.rcMonitor.Top) and
(WinRect.Right = MonInfo.rcMonitor.Right) and
(WinRect.Bottom = MonInfo.rcMonitor.Bottom);
end;
class procedure TWindowFocusHelper.FocusWindow(FormHandle: HWND);
begin
// Handle minimized state
if IsIconic(FormHandle) then
ShowWindow(FormHandle, SW_RESTORE);
// Don't steal focus from fullscreen applications
if not IsWindowFullscreen(GetForegroundWindow) then
begin
// Try standard approach first
if not SetForegroundWindow(FormHandle) then
// If that fails, use the forced approach
ForceForegroundWindow(FormHandle);
end;
// Ensure window is visible and on top
ShowWindow(FormHandle, SW_SHOW);
BringWindowToTop(FormHandle);
// Send activation message
SendMessage(FormHandle, WM_ACTIVATE, WA_ACTIVE, 0);
end;
end.