ImGUI не скрывается курсор.

vg1tl1ne

Известный
Автор темы
3
1
Подскажите, пожалуйста, почему курсор не скрывается после закрытия ImGui-меню в SAMP.


entry.cpp:
#include "include.h"

kthook::kthook_simple<CTimer__UpdateSignature> CTimerHook{};
kthook::kthook_signal<PresentSignature> PresentHook{};
kthook::kthook_signal<ResetSignature> ResetHook{};
kthook::kthook_simple<WndProcSignature> WndProcHook{};

bool ImGuiEnable;
char ImGuiInputBuffer[256];

DWORD dwSAMP = 0;
DWORD SAMP_GAME_PTR = 0;
DWORD SAMP_FUNC_TOGGLECURSOR = 0;
DWORD SAMP_FUNC_CURSORUNLOCKACTORCAM = 0;

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

bool ToggleCursor(bool state) {
    if (dwSAMP && SAMP_GAME_PTR && SAMP_FUNC_TOGGLECURSOR && SAMP_FUNC_CURSORUNLOCKACTORCAM) {
        void* obj = *(void**)(dwSAMP + SAMP_GAME_PTR);
        reinterpret_cast<void(__thiscall*)(void*, int, bool)>(dwSAMP + SAMP_FUNC_TOGGLECURSOR)(obj, state ? 3 : 0, !state);
        if (!state)
            reinterpret_cast<void(__thiscall*)(void*)>(dwSAMP + SAMP_FUNC_CURSORUNLOCKACTORCAM)(obj);
    }
    return state;
}

HRESULT WndProc(const decltype(WndProcHook)& hook, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    if (uMsg == WM_KEYUP && wParam == VK_INSERT) {
        ImGuiEnable = !ImGuiEnable;
        ToggleCursor(ImGuiEnable);
    }

    if (ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam))
        return 1;

    return hook.get_trampoline()(hwnd, uMsg, wParam, lParam);
}

std::optional<HRESULT> D3D9Present(
    const decltype(PresentHook)& hook,
    IDirect3DDevice9* pDevice,
    const RECT* pSrcRect,
    const RECT* pDestRect,
    HWND hDestWindow,
    const RGNDATA* pDirtyRegion)
{
    static bool ImGuiInit = false;

    if (!ImGuiInit) {
        ImGui::CreateContext();
        ImGui_ImplWin32_Init(**reinterpret_cast<HWND**>(0xC17054));
        ImGui_ImplDX9_Init(pDevice);
        ImGui::GetIO().IniFilename = nullptr;

        std::string font = std::string(getenv("WINDIR")) + "\\Fonts\\arial.ttf";
        ImGui::GetIO().Fonts->AddFontFromFileTTF(font.c_str(), 14.0f, nullptr, ImGui::GetIO().Fonts->GetGlyphRangesCyrillic());

        auto latest_wndproc_ptr = GetWindowLongPtrW(**reinterpret_cast<HWND**>(0xC17054), GWLP_WNDPROC);
        WndProcHook.set_dest(latest_wndproc_ptr);
        WndProcHook.set_cb(&WndProc);
        WndProcHook.install();

        ImGuiInit = true;
    }

    ImGui_ImplDX9_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImGui::GetIO().MouseDrawCursor = ImGuiEnable;

    if (ImGuiEnable) {
        ImGui::SetNextWindowPos(ImVec2(250.f, 250.f), ImGuiCond_FirstUseEver);
        ImGui::SetNextWindowSize(ImVec2(300.f, 100.f), ImGuiCond_FirstUseEver);
        ImGui::Begin("ImGuiTemplate", &ImGuiEnable);

        ImGui::Text("Text");
        ImGui::InputText("Input text", ImGuiInputBuffer, sizeof(ImGuiInputBuffer));

        if (ImGui::Button("Touch button"))
            MessageBoxA(**reinterpret_cast<HWND**>(0xC17054), ImGuiInputBuffer, "", MB_OK);

        ImGui::End();
    }

    ImGui::EndFrame();
    ImGui::Render();
    ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());

    return std::nullopt;
}

std::optional<HRESULT> D3D9Lost(const decltype(ResetHook)& hook, LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentParams) {
    ImGui_ImplDX9_InvalidateDeviceObjects();
    return std::nullopt;
}

void D3D9Reset(const decltype(ResetHook)& hook, HRESULT& return_value, IDirect3DDevice9* device_ptr, D3DPRESENT_PARAMETERS* parameters) {
    ImGui_ImplDX9_InvalidateDeviceObjects();
}

void setD3D9Hooks() {
    DWORD pDevice = *reinterpret_cast<DWORD*>(0xC97C28);
    void** vTable = *reinterpret_cast<void***>(pDevice);

    PresentHook.set_dest(vTable[17]);
    PresentHook.before.connect(&D3D9Present);
    PresentHook.install();

    ResetHook.set_dest(vTable[16]);
    ResetHook.before.connect(&D3D9Lost);
    ResetHook.after.connect(&D3D9Reset);
    ResetHook.install();
}

void CTimer__Update(const decltype(CTimerHook)& hook) {
    static bool init = false;
    if (!init) {
        setD3D9Hooks();
        init = true;
    }
    hook.get_trampoline()();
}

using namespace plugin;

struct Main {
    Main() {
        Events::gameProcessEvent += [] {
            auto hSAMP = GetModuleHandle(L"samp.dll");
            if (hSAMP) {
                dwSAMP = reinterpret_cast<DWORD>(hSAMP);
                SAMP_GAME_PTR = 0x21A10C;
                SAMP_FUNC_TOGGLECURSOR = 0x9BD30;
                SAMP_FUNC_CURSORUNLOCKACTORCAM = 0x9BC10;
            }

            CTimerHook.set_dest(0x561B10);
            CTimerHook.set_cb(&CTimer__Update);
            CTimerHook.install();
            };
    }
} gInstance;

include.h:
#pragma once

#include <plugin.h>
#include <d3d9.h>
#include <Windows.h>
#include <string>
#include <optional>

#include "src/kthook/include/kthook/kthook.hpp"
#include "src/imgui/imgui.h"
#include "src/imgui/imgui_impl_dx9.h"
#include "src/imgui/imgui_impl_win32.h"

using CTimer__UpdateSignature = void(__cdecl*)();
using PresentSignature = HRESULT(__stdcall*)(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*);
using ResetSignature = HRESULT(__stdcall*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*);
using WndProcSignature = HRESULT(__stdcall*)(HWND, UINT, WPARAM, LPARAM);


extern kthook::kthook_simple<CTimer__UpdateSignature> CTimerHook;
extern kthook::kthook_signal<PresentSignature> PresentHook;
extern kthook::kthook_signal<ResetSignature> ResetHook;
extern kthook::kthook_simple<WndProcSignature> WndProcHook;


extern bool ImGuiEnable;
extern char ImGuiInputBuffer[256];

extern DWORD dwSAMP;
extern DWORD SAMP_GAME_PTR;
extern DWORD SAMP_FUNC_TOGGLECURSOR;
extern DWORD SAMP_FUNC_CURSORUNLOCKACTORCAM;

bool ToggleCursor(bool state);
void setD3D9Hooks();
 
Последнее редактирование:
  • Нравится
Реакции: norb3rd
Решение
Данный вариант работает, но при наводке на поле ввода появляется двойной курсор, мне бы такое лучше избежать и использовать дефолтный курсор. Будет ли работать, если всегда отключать самповский курсор, и отобразить стандартный через ImGui::GetIO().MouseDrawCursor?
Нет, ImGui::GetIO().MouseDrawCursor рисует свой курсор, а не системный. Он всегда один и тот же и не меняется на I-beam и другие формы. Если хочешь дефолтный курсор винды — убери NoMouseCursorChange и поставь MouseDrawCursor = false тада ImGui будет управлять системным курсором без двойного отображения

Данный вариант работает, но при наводке на поле ввода появляется двойной курсор, мне бы такое лучше избежать и использовать дефолтный курсор. Будет...

vg1tl1ne

Известный
Автор темы
3
1
проверь и скажи
Данный вариант работает, но при наводке на поле ввода появляется двойной курсор, мне бы такое лучше избежать и использовать дефолтный курсор. Будет ли работать, если всегда отключать самповский курсор, и отобразить стандартный через ImGui::GetIO().MouseDrawCursor?
 

nsxfgbhosdnghfbhpsdng

Участник
15
7
Данный вариант работает, но при наводке на поле ввода появляется двойной курсор, мне бы такое лучше избежать и использовать дефолтный курсор. Будет ли работать, если всегда отключать самповский курсор, и отобразить стандартный через ImGui::GetIO().MouseDrawCursor?
Нет, ImGui::GetIO().MouseDrawCursor рисует свой курсор, а не системный. Он всегда один и тот же и не меняется на I-beam и другие формы. Если хочешь дефолтный курсор винды — убери NoMouseCursorChange и поставь MouseDrawCursor = false тада ImGui будет управлять системным курсором без двойного отображения

Данный вариант работает, но при наводке на поле ввода появляется двойной курсор, мне бы такое лучше избежать и использовать дефолтный курсор. Будет ли работать, если всегда отключать самповский курсор, и отобразить стандартный через ImGui::GetIO().MouseDrawCursor?
вот не должен рисовать и щя все норм должно быть
 

Вложения

  • fix.txt
    4.9 KB · Просмотры: 3
  • Нравится
Реакции: vg1tl1ne