ImGui directx hook, крашит, хелп.

ImmortalDev

Участник
Автор темы
90
50
Нашел рабочий directx hook для гта са, при инжекте все ок, рисовал маленький черный квадратик как надо.
Но, когда я попытался встроить сюда ImGui, при инжекте просто напросто крашит игру.
В чем тут может проблема? Не пинайте сильно, в этой теме не особо шарю.
Код:

C++:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "framework.h"
//#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h"

typedef HRESULT(__stdcall* _EndScene)(IDirect3DDevice9* pDevice);
_EndScene oEndScene;

const char* windowName = "GTA: San Andreas";


HWND  window = FindWindowA(NULL, windowName);
IDirect3DDevice9* pDevice;

bool initialized = false;

void InitImGui(IDirect3DDevice9* pDevice) {
    D3DDEVICE_CREATION_PARAMETERS CP;
    pDevice->GetCreationParameters(&CP);
    //hWnd = CP.hFocusWindow;
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.IniFilename = NULL;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.Fonts->AddFontDefault();

    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX9_Init(pDevice);
    initialized = true;
    return;
}

HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();


        //ImGui::ShowDemoWindow(&bShow);


        ImGui::EndFrame();
        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}

DWORD APIENTRY MainThread(LPVOID lparam)
{
    while (!GetModuleHandleA("d3d9.dll"))//waiting till d3d9.dll gets loaded
    {
        Sleep(1);
    }
    // Endscene hook
    void** vTableDevice = *(void***)(*(DWORD*)0xC97C28);
    VTableHookManager* vmtHooks = new VTableHookManager(vTableDevice, 119);
    oEndScene = (_EndScene)vmtHooks->Hook(42, (void*)hkEndScene);
    ////////////////////////////////////////////////////////////////////////////////
    return false;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(0, 0, MainThread, hModule, 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
 
Решение
C++:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "framework.h"
//#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h"

typedef HRESULT(__stdcall* _EndScene)(IDirect3DDevice9* pDevice);
_EndScene oEndScene;

bool initialized = false;

void InitImGui(IDirect3DDevice9* pDevice) {
    D3DDEVICE_CREATION_PARAMETERS CP;
    pDevice->GetCreationParameters(&CP);
    //hWnd = CP.hFocusWindow;
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.IniFilename = NULL;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.Fonts->AddFontDefault();

    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX9_Init(pDevice);
    initialized = true;
    return;
}

HRESULT...

zTechnology

Известный
1,101
486
C++:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "framework.h"
//#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h"

typedef HRESULT(__stdcall* _EndScene)(IDirect3DDevice9* pDevice);
_EndScene oEndScene;

bool initialized = false;

void InitImGui(IDirect3DDevice9* pDevice) {
    D3DDEVICE_CREATION_PARAMETERS CP;
    pDevice->GetCreationParameters(&CP);
    //hWnd = CP.hFocusWindow;
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.IniFilename = NULL;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.Fonts->AddFontDefault();

    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX9_Init(pDevice);
    initialized = true;
    return;
}

HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}

DWORD APIENTRY MainThread(LPVOID lparam)
{
    while (!GetModuleHandleA("d3d9.dll"))//waiting till d3d9.dll gets loaded
    {
        Sleep(1);
    }
    HWND  window = FindWindowA(NULL, "GTA: San Andreas");
    // Endscene hook
    void** vTableDevice = *(void***)(*(DWORD*)0xC97C28);
    VTableHookManager* vmtHooks = new VTableHookManager(vTableDevice, 119);
    oEndScene = (_EndScene)vmtHooks->Hook(42, (void*)hkEndScene);
    ////////////////////////////////////////////////////////////////////////////////
    return false;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(0, 0, MainThread, hModule, 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
 
  • Нравится
Реакции: ImmortalDev

ImmortalDev

Участник
Автор темы
90
50
C++:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "framework.h"
//#include "imgui.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_win32.h"

typedef HRESULT(__stdcall* _EndScene)(IDirect3DDevice9* pDevice);
_EndScene oEndScene;

bool initialized = false;

void InitImGui(IDirect3DDevice9* pDevice) {
    D3DDEVICE_CREATION_PARAMETERS CP;
    pDevice->GetCreationParameters(&CP);
    //hWnd = CP.hFocusWindow;
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    io.IniFilename = NULL;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.Fonts->AddFontDefault();

    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX9_Init(pDevice);
    initialized = true;
    return;
}

HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}

DWORD APIENTRY MainThread(LPVOID lparam)
{
    while (!GetModuleHandleA("d3d9.dll"))//waiting till d3d9.dll gets loaded
    {
        Sleep(1);
    }
    HWND  window = FindWindowA(NULL, "GTA: San Andreas");
    // Endscene hook
    void** vTableDevice = *(void***)(*(DWORD*)0xC97C28);
    VTableHookManager* vmtHooks = new VTableHookManager(vTableDevice, 119);
    oEndScene = (_EndScene)vmtHooks->Hook(42, (void*)hkEndScene);
    ////////////////////////////////////////////////////////////////////////////////
    return false;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(0, 0, MainThread, hModule, 0, 0);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
Хм, большое спасибо, это правда работает)
Правда первый раз крашнуло, но я в енд сцене потом добавил EndRender и все заработало!
 
  • Нравится
Реакции: zTechnology

zTechnology

Известный
1,101
486
Хм, большое спасибо, это правда работает)
Правда первый раз крашнуло, но я в енд сцене потом добавил EndRender и все заработало!
endframe не всегда нужен. Если у тебя нет чилда, хук будет крашить т.к. нет окна и нет endframe'a, если сделать:
C++:
HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();
        ImGui::Begin("test", nullptr);
        {
        }
        ImGui::End();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}
то крашить не будет, а если сделать так:
C++:
HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();
        ImGui::EndFrame();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}
то так тоже не будет, т.к. не рендерится окно, при рендере окна(begin) endframe не нужен
 
  • Нравится
Реакции: ImmortalDev

ImmortalDev

Участник
Автор темы
90
50
endframe не всегда нужен. Если у тебя нет чилда, хук будет крашить т.к. нет окна и нет endframe'a, если сделать:
C++:
HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();
        ImGui::Begin("test", nullptr);
        {
        }
        ImGui::End();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}
то крашить не будет, а если сделать так:
C++:
HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice)
{
 if (!initialized) InitImGui(pDevice);
    else {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();
        ImGui::EndFrame();

        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}
то так тоже не будет, т.к. не рендерится окно, при рендере окна(begin) endframe не нужен
Cпасибо тебе большое, но у меня к тебе еще один вопрос.
Как убрать захват мыши в игре, ну то есть, я нарисовал окно, но пододвинуть его/изменить не могу, т.к игра не дает.
 

zTechnology

Известный
1,101
486
Cпасибо тебе большое, но у меня к тебе еще один вопрос.
Как убрать захват мыши в игре, ну то есть, я нарисовал окно, но пододвинуть его/изменить не могу, т.к игра не дает.
windproc ещё нужен вроде как
 

ImmortalDev

Участник
Автор темы
90
50
windproc ещё нужен вроде как
Я создал
C++:
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef LRESULT(CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    if (true && ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return true;
    return CallWindowProc( oriWndProc, hwnd, uMsg, wParam, lParam );
}
и вызываю его в MainThread
C++:
oriWndProc = (WNDPROC)SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);

Все ок, вроде не крашит, но каковы действия дальше? Нужно как то перехватывать нажатия? Что мне дальше делать с windproc?
 

zTechnology

Известный
1,101
486
Я создал
C++:
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef LRESULT(CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    if (true && ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return true;
    return CallWindowProc( oriWndProc, hwnd, uMsg, wParam, lParam );
}
и вызываю его в MainThread
C++:
oriWndProc = (WNDPROC)SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);

Все ок, вроде не крашит, но каковы действия дальше? Нужно как то перехватывать нажатия? Что мне дальше делать с windproc?
C++:
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef LRESULT(CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    if (true && ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return true;
        
        switch ( uMsg )
        {
        case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
        case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
        case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
        case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
        case WM_MOUSEWHEEL:
        case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP:
        case WM_XBUTTONUP: case WM_MOUSEMOVE:
            return true;
        }
    return CallWindowProc( oriWndProc, hwnd, uMsg, wParam, lParam );
}
 
  • Нравится
Реакции: ImmortalDev

ImmortalDev

Участник
Автор темы
90
50
C++:
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
typedef LRESULT(CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    if (true && ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return true;
       
        switch ( uMsg )
        {
        case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
        case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
        case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
        case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
        case WM_MOUSEWHEEL:
        case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP:
        case WM_XBUTTONUP: case WM_MOUSEMOVE:
            return true;
        }
    return CallWindowProc( oriWndProc, hwnd, uMsg, wParam, lParam );
}
Написал вот такой обработчик, но, все равно не работает.
C++:
if (true && ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return true;

        ImGuiIO& io = ImGui::GetIO();
        switch (uMsg)
        {
        case WM_LBUTTONDOWN:
            io.MouseDown[0] = true;
            return true;
        case WM_LBUTTONUP:
            io.MouseDown[0] = false;
            return true;
        case WM_RBUTTONDOWN:
            io.MouseDown[1] = true;
            return true;
        case WM_RBUTTONUP:
            io.MouseDown[1] = false;
            return true;
        case WM_MBUTTONDOWN:
            io.MouseDown[2] = true;
            return true;
        case WM_MBUTTONUP:
            io.MouseDown[2] = false;
            return true;
        case WM_MOUSEWHEEL:
            io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
            return true;
        case WM_MOUSEMOVE:
            io.MousePos.x = (signed short)(lParam);
            io.MousePos.y = (signed short)(lParam >> 16);
            return true;
        case WM_KEYDOWN:
            if (wParam < 256)
                io.KeysDown[wParam] = 1;
            return true;
        case WM_KEYUP:
            if (wParam < 256)
                io.KeysDown[wParam] = 0;
            return true;
        case WM_CHAR:
            if (wParam > 0 && wParam < 0x10000)
                io.AddInputCharacter((unsigned short)wParam);
            return true;
        }