Проблема с WndProc в SF

CatKnight

Известный
Автор темы
148
55
Всем привет. Возникла проблема при обработке нажатий в WndProc, а именно их блокировании, когда сообщения обрабатывает ImGui.
Сначала использовал обычный хук от SF на WndProc:
SF->getGame()->registerWndProcCallback(SFGame::MEDIUM_CB_PRIORITY, WndProcHandler);
Но после нескольких попыток блокирования нажатий для окна, пришёл к выводу, что игра на эти блокировки вообще никак не реагирует при разных приоритетах в коллбеке.
C++:
bool CALLBACK WndProcHandler(HWND hwd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ImGui_ImplWin32_WndProcHandler(hwd, msg, wParam, lParam);
    switch (msg)
    {
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_RBUTTONUP:
            return !ImGui::GetIO().WantCaptureMouse;
        case WM_CHAR:
            return !ImGui::GetIO().WantCaptureKeyboard;
    }
    return true;
}

После решил попробовать добавить уже свой хук на WndProc через SetWindowLongPtr. Наконец-таки нажатия начались блокироваться (кроме кликов мыши :(), но возникла новая проблема. Если я выгружу свой плагин через консоль СФ, то игра крашнется. Нашёл похожую проблему в этом посте, но решения не увидел.
C++:
LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
WNDPROC hOrigProc = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
    if (uMsg >= WM_LBUTTONDOWN && uMsg <= WM_MBUTTONDBLCLK && ImGui::GetIO().WantCaptureMouse)
        return FALSE;
    if (uMsg == WM_CHAR && ImGui::GetIO().WantCaptureKeyboard)
        return FALSE;
    return CallWindowProcA((WNDPROC)hOrigProc, hWnd, uMsg, wParam, lParam);
}

...
if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized())
{
    hOrigProc = (WNDPROC)SetWindowLongPtr(**(HWND**)0xC17054, GWLP_WNDPROC, (LONG_PTR)WndProc);
    ...
}


Прошу подсказать как лучше всего решить трабл этот. В планах было сделать игнорирование нажатий символов и кликов мыши для игры, когда используется ImGui, чтобы не открывался ни чат, ни нажимались клавиши управления игрой и так далее. Заранее спасибо.
 
Решение
Всем привет. Возникла проблема при обработке нажатий в WndProc, а именно их блокировании, когда сообщения обрабатывает ImGui.
Сначала использовал обычный хук от SF на WndProc:
SF->getGame()->registerWndProcCallback(SFGame::MEDIUM_CB_PRIORITY, WndProcHandler);
Но после нескольких попыток блокирования нажатий для окна, пришёл к выводу, что игра на эти блокировки вообще никак не реагирует при разных приоритетах в коллбеке.
C++:
bool CALLBACK WndProcHandler(HWND hwd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ImGui_ImplWin32_WndProcHandler(hwd, msg, wParam, lParam);
    switch (msg)
    {
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_RBUTTONUP:
            return...

Stiopko

Известный
Проверенный
307
218
Всем привет. Возникла проблема при обработке нажатий в WndProc, а именно их блокировании, когда сообщения обрабатывает ImGui.
Сначала использовал обычный хук от SF на WndProc:
SF->getGame()->registerWndProcCallback(SFGame::MEDIUM_CB_PRIORITY, WndProcHandler);
Но после нескольких попыток блокирования нажатий для окна, пришёл к выводу, что игра на эти блокировки вообще никак не реагирует при разных приоритетах в коллбеке.
C++:
bool CALLBACK WndProcHandler(HWND hwd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ImGui_ImplWin32_WndProcHandler(hwd, msg, wParam, lParam);
    switch (msg)
    {
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_RBUTTONUP:
            return !ImGui::GetIO().WantCaptureMouse;
        case WM_CHAR:
            return !ImGui::GetIO().WantCaptureKeyboard;
    }
    return true;
}

После решил попробовать добавить уже свой хук на WndProc через SetWindowLongPtr. Наконец-таки нажатия начались блокироваться (кроме кликов мыши :(), но возникла новая проблема. Если я выгружу свой плагин через консоль СФ, то игра крашнется. Нашёл похожую проблему в этом посте, но решения не увидел.
C++:
LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
WNDPROC hOrigProc = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
    if (uMsg >= WM_LBUTTONDOWN && uMsg <= WM_MBUTTONDBLCLK && ImGui::GetIO().WantCaptureMouse)
        return FALSE;
    if (uMsg == WM_CHAR && ImGui::GetIO().WantCaptureKeyboard)
        return FALSE;
    return CallWindowProcA((WNDPROC)hOrigProc, hWnd, uMsg, wParam, lParam);
}

...
if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized())
{
    hOrigProc = (WNDPROC)SetWindowLongPtr(**(HWND**)0xC17054, GWLP_WNDPROC, (LONG_PTR)WndProc);
    ...
}


Прошу подсказать как лучше всего решить трабл этот. В планах было сделать игнорирование нажатий символов и кликов мыши для игры, когда используется ImGui, чтобы не открывался ни чат, ни нажимались клавиши управления игрой и так далее. Заранее спасибо.
запихни вот это в сфофовский деструктор, там его интиализировать надо

C++:
SetWindowLongPtr(**(HWND**)0xC17054, GWLP_WNDPROC, (LONG_PTR)hOrigProc);
но учти что все плагины которые тоже зарегали хук WNDPROC после твоего хука то у них уже не будет исполнятся WndProc
может быть ошибка

уже не будет исполнятся WndProc
 
Последнее редактирование:
  • Нравится
Реакции: Cake_

CatKnight

Известный
Автор темы
148
55
запихни вот это в сфофовский деструктор, там его интиализировать надо

C++:
SetWindowLongPtr(**(HWND**)0xC17054, GWLP_WNDPROC, (LONG_PTR)hOrigProc);
но учти что все плагины которые тоже зарегали хук WNDPROC после твоего хука то у них уже не будет исполнятся WndProc
может быть ошибка

уже не будет исполнятся WndProc
Спасибо, работает, хоть теперь плагин и не загружается повторно через pload :unsure: (или лучше сказать не полностью выгружается). Но скорее всего дело не из-за хука.

Хм, прочитал изменение, плакать теперь хочется.
Подсказали ещё одну реализацию через выделение памяти, попробую её реализовать. Спасибо человеку выше за ответ, который хоть и работает, но не подходит. Закрыто, полагаю.
 
Последнее редактирование: