class Overlay {
public:
IDirect3D9Ex* pDirectEx;
LPDIRECT3DDEVICE9EX pDeviceEx;
D3DPRESENT_PARAMETERS PresentParams;
RECT RectGame;
ImVec2 SizeGame;
HWND hwnd_game;
HWND hwnd_overlay;
LPCSTR szWindowName = "window";
bool IsInitialization = false;
void OverlayRunning(LPCSTR szNameProcess, HINSTANCE hInst, int nCmdShow)
{
WNDCLASSEX wClass;
wClass.cbClsExtra = 0;
wClass.cbSize = sizeof(WNDCLASSEX);
wClass.cbWndExtra = 0;
wClass.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wClass.hCursor = LoadCursor(0, IDC_ARROW);
wClass.hIcon = 0;
wClass.hIconSm = 0;
wClass.hInstance = hInst;
wClass.lpfnWndProc = WndProc;
wClass.lpszClassName = this->szWindowName;
wClass.lpszMenuName = this->szWindowName;
wClass.style = CS_VREDRAW | CS_HREDRAW;
if (!RegisterClassEx(&wClass))
exit(1);
this->hwnd_game = FindWindowA(0, szNameProcess);
GetClientRect(this->hwnd_game, &this->RectGame);
this->SizeGame.x = this->RectGame.right - this->RectGame.left;
this->SizeGame.y = this->RectGame.bottom - this->RectGame.top;
if (this->hwnd_game)
{
this->hwnd_overlay = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED,
this->szWindowName,
this->szWindowName,
WS_POPUP,
this->RectGame.left,
this->RectGame.top,
this->RectGame.right,
this->RectGame.bottom,
0, 0, 0, 0);
const MARGINS margins = { -1 };
DwmExtendFrameIntoClientArea(this->hwnd_overlay, &margins);
SetLayeredWindowAttributes(this->hwnd_overlay, 0, 255, LWA_ALPHA);
SetLayeredWindowAttributes(this->hwnd_overlay, RGB(0, 0, 0), 0, ULW_COLORKEY);
ShowWindow(this->hwnd_overlay, SW_SHOW);
}
this->InitializationDirectX9();
MSG msg;
while (true)
{
this->pDeviceEx->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.f, 0);
this->pDeviceEx->BeginScene();
if (pState->menu.active)
SetWindowLongPtr(this->hwnd_overlay, GWL_EXSTYLE, WS_EX_LAYERED );
else SetWindowLongPtr(this->hwnd_overlay, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT);
// Render ImGui Window
this->pDeviceEx->EndScene();
this->pDeviceEx->SetRenderState(D3DRS_ZENABLE, false);
this->pDeviceEx->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
this->pDeviceEx->SetRenderState(D3DRS_SCISSORTESTENABLE, false);
HRESULT result = this->pDeviceEx->PresentEx(0, 0, 0, 0, 0);
if (result == D3DERR_DEVICELOST && this->pDeviceEx->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) {
ImGui_ImplDX9_InvalidateDeviceObjects();
HRESULT hr = this->pDeviceEx->Reset(&this->PresentParams);
if (hr == D3DERR_INVALIDCALL) { IM_ASSERT(0); }
ImGui_ImplDX9_CreateDeviceObjects();
}
if (PeekMessage(&msg, this->hwnd_overlay, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
TranslateMessage(&msg);
}
Sleep(1);
}
}
private:
void InitializationDirectX9(void)
{
if (FAILED(Direct3DCreate9Ex(D3D_SDK_VERSION, &this->pDirectEx)))
exit(2);
ZeroMemory(&this->PresentParams, sizeof(D3DPRESENT_PARAMETERS));
this->PresentParams.Windowed = 1;
this->PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
this->PresentParams.BackBufferFormat = D3DFMT_A8R8G8B8;
this->PresentParams.AutoDepthStencilFormat = D3DFMT_D16;
this->PresentParams.MultiSampleQuality = D3DMULTISAMPLE_NONE;
this->PresentParams.hDeviceWindow = this->hwnd_overlay;
this->PresentParams.BackBufferWidth = this->RectGame.right;
this->PresentParams.BackBufferHeight = this->RectGame.bottom;
this->PresentParams.EnableAutoDepthStencil = 1;
if (FAILED(this->pDirectEx->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, this->hwnd_overlay, D3DCREATE_HARDWARE_VERTEXPROCESSING, &this->PresentParams, 0, &this->pDeviceEx)))
exit(3);
this->IsInitialization = true;
}
}
extern IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
if (ImGui_ImplWin32_WndProcHandler(hWnd, message, wParam, lParam))
return true;
return DefWindowProc(hWnd, message, wParam, lParam);
}