Показать сообщение отдельно

  #3  
Старый 26.12.2025, 13:19
g305noobo
Постоянный
Регистрация: 24.09.2020
Сообщений: 364
С нами: 2966237

Репутация: 148
По умолчанию

Цитата:
Сообщение от rhjossss  

пока что пришел к такому результату -

видно, что моментами чит все таки проскакивает на запись, подскажите в чем проблема
Вот как сейчас работает StreamProof и хук Present:

StreamProof.cpp:

Создаёт отдельное overlay-окно с флагом WDA_EXCLUDEFROMCAPTURE (исключает из захвата OBS/стримов)
Окно создаётся поверх игры с флагами WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED
UpdatePosition() синхронизирует позицию оверлея с окном игры и скрывает его когда игра не в фокусе
Хук Present (Hooks.cpp):

Хук Present (Hooks.cpp)::





Код:
if (StreamProof::IsEnabled())
{
    // 1. Презентуем игру БЕЗ оверлея (это захватит OBS)
    oPresent(pDevice, pSrcRect, pDestRect, hDestWindow, pDirtyRegion);
   
    // 2. Рисуем оверлей
    Cheat::Render();
   
    // 3. Презентуем оверлей в скрытое окно (OBS не захватит)
    HWND hOverlay = StreamProof::GetOverlayWindow();
    if (hOverlay)
        return oPresent(pDevice, nullptr, nullptr, hOverlay, nullptr);
   
    return D3D_OK;
}


Streamproof.cpp:





Код:
#include "main.h"
#ifndef WDA_EXCLUDEFROMCAPTURE
#define WDA_EXCLUDEFROMCAPTURE 0x00000011
#endif
static
LRESULT CALLBACK
OverlayWndProc
(
HWND hWnd
,
UINT uMsg
,
WPARAM wParam
,
LPARAM lParam
)
{
return
DefWindowProcW
(
hWnd
,
uMsg
,
wParam
,
lParam
)
;
}
void
StreamProof
::
Init
(
)
{
}
void
StreamProof
::
Shutdown
(
)
{
if
(
hOverlayWindow
)
{
DestroyWindow
(
hOverlayWindow
)
;
hOverlayWindow
=
nullptr
;
}
bInitialized
=
false
;
}
void
StreamProof
::
CreateOverlayWindow
(
)
{
if
(
hOverlayWindow
)
return
;
HWND hGameWindow
=
*
reinterpret_cast

(
0xC97C1C
)
;
if
(
!
hGameWindow
)
return
;
WNDCLASSEXW wc
=
{
}
;
wc
.
cbSize
=
sizeof
(
WNDCLASSEXW
)
;
wc
.
style
=
CS_HREDRAW
|
CS_VREDRAW
;
wc
.
lpfnWndProc
=
OverlayWndProc
;
wc
.
hInstance
=
GetModuleHandleW
(
nullptr
)
;
wc
.
lpszClassName
=
L
"StreamProofWnd"
;
RegisterClassExW
(
&
wc
)
;
RECT rcGame
;
GetWindowRect
(
hGameWindow
,
&
rcGame
)
;
int
w
=
rcGame
.
right
-
rcGame
.
left
;
int
h
=
rcGame
.
bottom
-
rcGame
.
top
;
// Создаём обычное окно поверх игры
hOverlayWindow
=
CreateWindowExW
(
WS_EX_TOPMOST
|
WS_EX_TRANSPARENT
|
WS_EX_LAYERED
|
WS_EX_NOACTIVATE
,
L
"StreamProofWnd"
,
L
""
,
WS_POPUP
,
rcGame
.
left
,
rcGame
.
top
,
w
,
h
,
nullptr
,
nullptr
,
GetModuleHandleW
(
nullptr
)
,
nullptr
)
;
if
(
hOverlayWindow
)
{
// Главное - исключаем окно из захвата экрана
SetWindowDisplayAffinity
(
hOverlayWindow
,
WDA_EXCLUDEFROMCAPTURE
)
;
// Прозрачность
SetLayeredWindowAttributes
(
hOverlayWindow
,
RGB
(
0
,
0
,
0
)
,
255
,
LWA_ALPHA
)
;
ShowWindow
(
hOverlayWindow
,
SW_SHOWNOACTIVATE
)
;
}
bInitialized
=
true
;
}
void
StreamProof
::
UpdatePosition
(
)
{
if
(
!
hOverlayWindow
)
return
;
HWND hGameWindow
=
*
reinterpret_cast

(
0xC97C1C
)
;
if
(
!
hGameWindow
)
return
;
// Проверяем, активна ли игра (в фокусе)
HWND hForeground
=
GetForegroundWindow
(
)
;
bool
bGameActive
=
(
hForeground
==
hGameWindow
)
;
if
(
!
bGameActive
)
{
// Игра не в фокусе - скрываем оверлей
ShowWindow
(
hOverlayWindow
,
SW_HIDE
)
;
return
;
}
// Игра в фокусе - показываем и обновляем позицию
RECT rcGame
;
GetWindowRect
(
hGameWindow
,
&
rcGame
)
;
SetWindowPos
(
hOverlayWindow
,
HWND_TOPMOST
,
rcGame
.
left
,
rcGame
.
top
,
rcGame
.
right
-
rcGame
.
left
,
rcGame
.
bottom
-
rcGame
.
top
,
SWP_NOACTIVATE
|
SWP_SHOWWINDOW
)
;
}
HWND StreamProof
::
GetOverlayWindow
(
)
{
if
(
!
bEnabled
)
return
nullptr
;
if
(
!
hOverlayWindow
)
CreateOverlayWindow
(
)
;
UpdatePosition
(
)
;
return
hOverlayWindow
;
}
bool
StreamProof
::
IsEnabled
(
)
{
return
bEnabled
;
}
void
StreamProof
::
SetEnabled
(
bool
bEnable
)
{
bEnabled
=
bEnable
;
if
(
bEnabled
&&
!
hOverlayWindow
)
CreateOverlayWindow
(
)
;
if
(
hOverlayWindow
)
ShowWindow
(
hOverlayWindow
,
bEnabled
?
SW_SHOWNOACTIVATE
:
SW_HIDE
)
;
}


Streamproof.h:





Код:
#pragma once
namespace
StreamProof
{
void
Init
(
)
;
void
Shutdown
(
)
;
void
CreateOverlayWindow
(
)
;
void
UpdatePosition
(
)
;
HWND
GetOverlayWindow
(
)
;
bool
IsEnabled
(
)
;
void
SetEnabled
(
bool
bEnabled
)
;
inline
HWND hOverlayWindow
{
nullptr
}
;
inline
bool
bEnabled
{
false
}
;
inline
bool
bInitialized
{
false
}
;
}

Ты можешь поставить хук на оригинальный Present в d3d9.dll, так как в игре несколько экземпляров IDirect3DDevice9. Как я понимаю получается так, что обс по своей сигнатуре находит немного другое место и ставит хук который будет вызываться до твоего рендера и его не будет видно.

Можешь использовать эту функцию:

C++:





[CODE]
std
::
uintptr_t
*
find_d3d9_vtable
(
std
::
size_t len
=
0x128000
)
{
auto
b
=
(
uint8_t
*
)
GetModuleHandleA
(
"d3d9.dll"
)
;
if
(
!
b
)
return
nullptr
;
for
(
size_t i
=
0
;
i

 
Ответить с цитированием