Skip to content

[NFSU2] Window moves after a little bit making it misaligned again #2210

Description

@DeathWrench

Starts off alright, but after playing for about a minute this happens, 1 and 4 seem to both have this issue, didn't test with stretched but I imagine it wouldn't happen with it, reason for not just using stretched is because it smushes things, you can see seams in the image (using steam overlay FPS counter it becomes compacted a little bit when using stretched). Notice the seam at the top of the window in this image:
Image
I have this .ahk script I use for some games that don't have a borderless window option:

F12::
WinGet, TempWindowID, ID, A
If (WindowID != TempWindowID)
{
  WindowID:=TempWindowID
  WindowState:=0
}
If (WindowState != 1)
{
WinGet, WindowID, ID, A
WinSet, Style, -0xC40000, ahk_id %WindowID%
WinMove, ahk_id %WindowID%, , -1, -1, A_ScreenWidth + 1, A_ScreenHeight + 1
}
Else
{
  WinSet, Style, +0xC40000, ahk_id %WindowID%
  WinMove, ahk_id %WindowID%, , WinPosX, WinPosY, WindowWidth, WindowHeight
  ;Show the task bar again
  ;WinShow ahk_class Shell_TrayWnd
  WinShow Start ahk_class Button
}
WindowState:=!WindowState
return

The important line is this I had to modify for NFSU2:
WinMove, ahk_id %WindowID%, , -1, -1, A_ScreenWidth + 1, A_ScreenHeight + 1
For every other game it's
WinMove, ahk_id %WindowID%, , 0, 0, A_ScreenWidth, A_ScreenHeight
but in order to stretch it to fit the screen I move it up and to the left -1 pixel and then +1 pixel to the resolution. If not, the same 1 pixel seam thing happens.

I made a .asi to test and it does work the same as the .ahk script:

#include <Windows.h>

static HWND g_hwnd = nullptr;

static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    if (!IsWindowVisible(hwnd) || !IsWindowEnabled(hwnd))
        return TRUE;

    DWORD pid = 0;
    GetWindowThreadProcessId(hwnd, &pid);

    if (pid == GetCurrentProcessId())
    {
        g_hwnd = hwnd;
        return FALSE; // Stop at first match (usually the main window)
    }
    return TRUE;
}

static void ForceBorderless(HWND hwnd)
{
    if (!hwnd || !IsWindow(hwnd))
        return;

    // Remove all decorations
    LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
    style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX |
        WS_MAXIMIZEBOX | WS_SYSMENU | WS_OVERLAPPED);
    style |= WS_POPUP;

    SetWindowLongPtr(hwnd, GWL_STYLE, style);

    // Clean extended styles too
    LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
    exStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
        WS_EX_STATICEDGE | WS_EX_WINDOWEDGE);
    SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle);

    // Your required dimensions to fix the seam/off-center bug
    int width = GetSystemMetrics(SM_CXSCREEN) + 1;
    int height = GetSystemMetrics(SM_CYSCREEN) + 1;

    SetWindowPos(
        hwnd,
        HWND_TOP,
        -1, -1,
        width, height,
        SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_SHOWWINDOW
    );
}

static DWORD WINAPI WindowThread(LPVOID)
{
    Sleep(1000);

    // Reliable main window detection
    EnumWindows(EnumWindowsProc, 0);

    // Fallback
    if (!g_hwnd)
    {
        g_hwnd = GetForegroundWindow();
        while (!g_hwnd)
        {
            Sleep(1000);
            g_hwnd = GetForegroundWindow();
        }
    }

    if (!g_hwnd)
        return 0;

    ForceBorderless(g_hwnd);

    // Monitoring loop (lighter than before)
    while (IsWindow(g_hwnd))
    {
        RECT rect{};
        GetWindowRect(g_hwnd, &rect);

        int expectedW = GetSystemMetrics(SM_CXSCREEN) + 1;
        int expectedH = GetSystemMetrics(SM_CYSCREEN) + 1;

        if (rect.left != -1 || rect.top != -1 ||
            (rect.right - rect.left) != expectedW ||
            (rect.bottom - rect.top) != expectedH)
        {
            ForceBorderless(g_hwnd);
        }

        Sleep(1000); // Balanced polling
    }

    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID)
{
    if (reason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hModule);
        CreateThread(nullptr, 0, WindowThread, nullptr, 0, nullptr);
    }
    return TRUE;
}

Widescreenfix no .ahk/.asi:
Image
Widescreen fix with .ahk/.asi:
Image
It's of course up to you how to implement this in Widescreen Fix, but I figured I would post a solution to this. Unlike stretched it doesn't cause the smushing.
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions