- 当前目标:尝试将自定义代码注入 DirectX11 游戏以显示窗口。
- 预期结果: ImGui Demo Window 应该在注入后显示,但不应该是可交互的
- 结果得到: ImGui Demo Window 不显示或在注射时不显示任何内容。
我尝试过的事情:制作一个自定义的 Imgui 窗口并重新注入,调试代码以确保它正在运行并在每一帧都被调用,确保没有任何内容为 NULL,在 google、ImGui GitHub 上搜索我的问题、堆栈溢出。
D3D11 Init(注入后调用的第一件事)
LRESULT CALLBACK DXGIMsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, uMsg, wParam, lParam); }
DWORD __stdcall D3D11Init() {
// Create Dummy Window
WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC, DXGIMsgProc, 0L, 0L, GetModuleHandleA(NULL), NULL, NULL, NULL, NULL, "DX", NULL };
RegisterClassExA(&wc);
HWND hWnd = CreateWindowA("DX", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL);
D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
D3D_FEATURE_LEVEL obtainedLevel;
DXGI_SWAP_CHAIN_DESC sd;
{
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.OutputWindow = hWnd;
sd.Windowed = TRUE;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.SampleDesc.Count = 1;
}
HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, levels, sizeof(levels) / sizeof(D3D_FEATURE_LEVEL), D3D11_SDK_VERSION, &sd, &d3dSwapChain, &d3dDevice, &obtainedLevel, &d3dContext);
if (FAILED(hr))
{
return E_FAIL;
}
pSwapChainVTable = (DWORD_PTR*)(d3dSwapChain);
pSwapChainVTable = (DWORD_PTR*)(pSwapChainVTable[0]);
pDeviceVTable = (DWORD_PTR*)(d3dDevice);
pDeviceVTable = (DWORD_PTR*)pDeviceVTable[0];
pDeviceContextVTable = (DWORD_PTR*)(d3dContext);
pDeviceContextVTable = (DWORD_PTR*)(pDeviceContextVTable[0]);
SAFE_RELEASE(d3dSwapChain);
SAFE_RELEASE(d3dDevice);
SAFE_RELEASE(d3dContext);
UnregisterClassA(wc.lpszClassName, wc.hInstance);
if (MH_Initialize() != MH_OK) { return 1; }
if (MH_CreateHook((DWORD_PTR*)pSwapChainVTable[8], PresentHook, reinterpret_cast<void**>(&pHookD3D11Present)) != MH_OK) { return 1; }
if (MH_EnableHook((DWORD_PTR*)pSwapChainVTable[8]) != MH_OK) { return 1; }
DWORD old_protect;
VirtualProtect(pHookD3D11Present, 2, PAGE_EXECUTE_READWRITE, &old_protect);
}
PresentHook(每次游戏调用 Present 函数时调用)
HRESULT __stdcall PresentHook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
if(!init) {
std::cout << "\t[+] Present Hook called First Time!" << std::endl;
if (FAILED(GetDeviceAndCtxFromSwapChain(pSwapChain, &d3dDevice, &d3dContext)))
return pHookD3D11Present(pSwapChain, SyncInterval, Flags);
// Get Game Window Handle
DXGI_SWAP_CHAIN_DESC sd;
pSwapChain->GetDesc(&sd);
window = sd.OutputWindow;
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void) io;
io.IniFilename = NULL;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.DisplaySize = ImVec2(1280, 720);
ImGui_ImplWin32_Init(window);
ImGui_ImplDX11_Init(d3dDevice, d3dContext);
init = true;
};
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
ImGui::ShowDemoWindow();
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
return pHookD3D11Present(pSwapChain, SyncInterval, Flags);
}