Skip to content

Commit fc5538e

Browse files
committed
black background + constrain mouse cursor
1 parent 5293f6d commit fc5538e

1 file changed

Lines changed: 103 additions & 9 deletions

File tree

EmperorHooks/dllmain.cpp

Lines changed: 103 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
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

125126
bool isBorderlessWindowed = true;
126127

128+
volatile HWND backgroundWindowHandle = nullptr;
129+
volatile DWORD backgroundWindowThreadId = 0;
130+
volatile bool focus = true;
131+
132+
127133
HWND* const mainWindowHandleP = (HWND*)0x007D75A8;
128134
uint8_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
181192
WndProcDuneIIIType wndProcDuneIIIOriginal = (WndProcDuneIIIType)0x004A6560;
182193

183194

184-
bool focus = true;
185-
uint64_t lastFocusCheckTick = 0;
186-
187195
int __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

Comments
 (0)