66#include < io.h>
77#include < fcntl.h>
88#include < intrin.h>
9+ #include < thread>
910#include " HookD3D7.hpp"
1011#include " PatchD3D7ResolutionLimit.hpp"
1112
@@ -124,6 +125,11 @@ void (*EmptyFuncSometimesLog)(...) = (void (*)(...))0x401CB0;
124125
125126bool isBorderlessWindowed = true ;
126127
128+ volatile HWND backgroundWindowHandle = nullptr ;
129+ volatile DWORD backgroundWindowThreadId = 0 ;
130+ volatile bool focus = true ;
131+
132+
127133HWND* const mainWindowHandleP = (HWND*)0x007D75A8 ;
128134uint8_t * gDoQuitP = (uint8_t *)0x007D75AC ;
129135
@@ -153,7 +159,12 @@ BOOL __cdecl setWindowStyleAndDrainMessages(HWND hWnd, int width, int height, ch
153159 SetWindowLongA (hWnd, GWL_STYLE, style);
154160 if (isBorderlessWindowed)
155161 {
156- SetWindowPos (hWnd, HWND_TOPMOST, GetSystemMetrics (SM_CXSCREEN) / 2 - useWidth / 2 , 0 , useWidth, useHeight, SWP_SHOWWINDOW);
162+ int left = GetSystemMetrics (SM_CXSCREEN) / 2 - useWidth / 2 ;
163+ SetWindowPos (hWnd, HWND_TOPMOST, left, 0 , useWidth, useHeight, SWP_SHOWWINDOW);
164+
165+ RECT rc = {};
166+ GetWindowRect (*mainWindowHandleP, &rc);
167+ ClipCursor (&rc);
157168 }
158169 else
159170 {
@@ -181,16 +192,14 @@ typedef int(__stdcall* WndProcDuneIIIType)(HWND hWnd, UINT Msg, WPARAM wParam, L
181192WndProcDuneIIIType wndProcDuneIIIOriginal = (WndProcDuneIIIType)0x004A6560 ;
182193
183194
184- bool focus = true ;
185- uint64_t lastFocusCheckTick = 0 ;
186-
187195int __stdcall wndProcDuneIII (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
188196{
189197 int ret = wndProcDuneIIIOriginal (hWnd, Msg, wParam, lParam);
190198
199+
191200 if (hWnd == *mainWindowHandleP && Msg == WM_ACTIVATEAPP)
192201 {
193- if (wParam)
202+ if (wParam || (!wParam && lParam == backgroundWindowThreadId) )
194203 {
195204 printf (" GAINED FOCUS\n " );
196205 focus = true ;
@@ -200,22 +209,95 @@ int __stdcall wndProcDuneIII(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
200209 printf (" LOST FOCUS\n " );
201210 focus = false ;
202211 SetWindowPos (hWnd, HWND_NOTOPMOST, 0 , 0 , 0 , 0 , SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
212+ ShowWindow (hWnd, SW_MINIMIZE);
213+
214+ SetWindowPos (backgroundWindowHandle, HWND_NOTOPMOST, 0 , 0 , 0 , 0 , SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
215+ ShowWindow (backgroundWindowHandle, SW_MINIMIZE);
203216 }
204217 }
205218
206- // We do this repeatedly because if we just do it once the taskbar sometimes stays on top. Not sure why, but this fixes it.
207- if (GetTickCount64 () - lastFocusCheckTick >= 1000 * 5 )
219+ static bool hadFocus = true ;
220+
221+ if (focus && !hadFocus)
208222 {
209- lastFocusCheckTick = GetTickCount64 ();
223+ RECT rc = {};
224+ GetWindowRect (*mainWindowHandleP, &rc);
225+ ClipCursor (&rc);
210226
211- if (focus && *mainWindowHandleP && *mainWindowHandleP != INVALID_HANDLE_VALUE)
227+ std::thread ([]()
228+ {
229+ printf (" %p %p\n " , *mainWindowHandleP, backgroundWindowHandle);
230+ Sleep (1000 * 2 );
231+ ShowWindow (backgroundWindowHandle, SW_SHOWNOACTIVATE);
232+ Sleep (1000 * 2 );
233+ SetWindowPos (backgroundWindowHandle, HWND_TOPMOST, 0 , 0 , 0 , 0 , SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
234+ Sleep (1000 * 2 );
212235 SetWindowPos (*mainWindowHandleP, HWND_TOPMOST, 0 , 0 , 0 , 0 , SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
236+ ShowWindow (*mainWindowHandleP, SW_SHOW);
237+ }).detach ();
213238 }
214239
240+ hadFocus = focus;
241+
215242 return ret;
216243}
217244
218245
246+
247+ void backgroundWindow ()
248+ {
249+ backgroundWindowThreadId = GetCurrentThreadId ();
250+
251+ // Register the window class.
252+ const char CLASS_NAME[] = " DuneIII background" ;
253+
254+ WNDCLASSA wc = { };
255+ wc.lpfnWndProc = DefWindowProcA;
256+ wc.hInstance = GetModuleHandleA (nullptr );
257+ wc.lpszClassName = CLASS_NAME;
258+ RegisterClassA (&wc);
259+
260+ HWND temp = CreateWindowExA (
261+ WS_EX_TOOLWINDOW, // Optional window styles.
262+ CLASS_NAME, // Window class
263+ nullptr , // Window text
264+ WS_POPUP, // Window style
265+
266+ // Size and position
267+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
268+
269+ NULL , // Parent window
270+ NULL , // Menu
271+ wc.hInstance , // Instance handle
272+ NULL // Additional application data
273+ );
274+
275+ ShowWindow (temp, SW_MAXIMIZE);
276+
277+ HBRUSH black = CreateSolidBrush (RGB (0 , 0 , 0 ));
278+ SetClassLongPtrA (temp, GCLP_HBRBACKGROUND, (LONG_PTR)black);
279+ InvalidateRect (temp, nullptr , 1 );
280+
281+ backgroundWindowHandle = temp;
282+
283+ BOOL bRet;
284+
285+ MSG msg;
286+ while ((bRet = GetMessage (&msg, backgroundWindowHandle, 0 , 0 )) != 0 )
287+ {
288+ if (bRet == -1 )
289+ {
290+ break ;
291+ }
292+ else
293+ {
294+ TranslateMessage (&msg);
295+ DispatchMessage (&msg);
296+ }
297+ }
298+ }
299+
300+
219301__declspec (dllexport) BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
220302{
221303 if (DetourIsHelperProcess ()) {
@@ -241,6 +323,18 @@ __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOI
241323 DetourTransactionCommit ();
242324
243325 patchD3D7ResolutionLimit ();
326+
327+ std::thread ([]() { backgroundWindow (); }).detach ();
328+ std::thread ([]()
329+ {
330+ while (true )
331+ {
332+ Sleep (1000 * 1 );
333+ RECT rect;
334+ if (GetWindowRect (*mainWindowHandleP, &rect))
335+ ClipCursor (&rect);
336+ }
337+ }).detach ();
244338 }
245339
246340 return TRUE ;
0 commit comments