IMGUI D3D9 透明窗口

发布时间 2023-07-19 16:37:01作者: Dir-A

这里以docking分支的direct9官方例子进行演示
https://github.com/ocornut/imgui/tree/docking

IMGUI 分主窗口和主窗口下的各种其它窗口,也就是main view窗口,这个窗口是正常win32样式,运行官方的例子可以更改主窗口的背景色

 代码就是这段了,用了一个ImGui::ColorEdit3组件,不过这个组件并不支持alpha通道的选择,clear_color是ImVec4,有alpha通道的值,修改成这样,就可以设置alpha通道的值了

1 ImGui::ColorEdit4("clear color", (float*)&clear_color, ImGuiColorEditFlags_AlphaBar);

这时候我们把alpha通道调成透明的,发现只是变黑了,并没有透明,可见除了背景这层外,底下还有个黑色的图层。

 先找到主窗口的创建,也就是开头这一行,给CreateWindow返回值的hwnd调用 ImGui_ImplWin32_EnableAlphaCompositing(hwnd); 这个方法是写在imgui_impl_win32.cpp里的

// Main code
int main(int, char**)
{
    // Create application window
    //ImGui_ImplWin32_EnableDpiAwareness();
    WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
    ::RegisterClassExW(&wc);
    HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui DirectX9 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
    ImGui_ImplWin32_EnableAlphaCompositing(hwnd);

这时主窗口就透明了,并且alpha通道的值可以随意改动,其它imgui创建的窗口也可以透明,但是前提是你在主窗口内

 一旦离开主窗口就变成了非透明的,而且窗口的alpha值,只对imgui创建的窗口生效,下图可以发现,Helllo world可以透明demo窗口,但是并不透明主窗口背景。
如果要透明主窗口背景,只能把背景颜色的alpha调到到最低,这样就完全透明,也就是说透明主窗口不能半透明。

 我们先解决移出主窗口不透明的情况,在direct9官方例子的项目里找到后端的imgui_impl_win32.cpp文件,找到里面的

static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)

 这个函数就是IMGUI拿来创建窗口的,也就你一旦把窗口移动到主窗口外,就会调用这个函数创建窗口,并画成IMGUI窗口的样式
我们给这个CreateWindow返回的hwnd也套一个 ImGui_ImplWin32_EnableAlphaCompositing

1     // Create window
2     RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
3     ::AdjustWindowRectEx(&rect, vd->DwStyle, FALSE, vd->DwExStyle);
4     vd->Hwnd = ::CreateWindowEx(
5         vd->DwExStyle, _T("ImGui Platform"), _T("Untitled"), vd->DwStyle,       // Style, class name, window name
6         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,    // Window area
7         vd->HwndParent, nullptr, ::GetModuleHandle(nullptr), nullptr);          // Owner window, Menu, Instance, Param
8     ImGui_ImplWin32_EnableAlphaCompositing(vd->Hwnd);

可以发现,脱离主窗口后,依然不透明,我们打开demo窗口的 No background,发现直接变成纯黑的背景了

可以猜测,这个窗口的背景,还覆盖了一层黑色的背景,来到imgui_impl_dx9.cpp,找到

可以发现,虽然我们还不知道它背景的alpha具体在上面地方控制,但是这里,如果把no background勾上,也不透明的原因就是它后端强制把alpha写成了1.0f

static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)

 我们把其修改成0.0,这样,当勾线no background的时候就可以脱离主窗口透明了

    ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);

 但是背景颜色的alpha值依旧不对主窗口外的窗口生效,即,外部的窗口只能全透明或不透明

猜测这个和imgui绘制背景颜色有关,暂时没研究出来怎么让imgui的窗口在外边也能让alpha生效

当然我们在这也可以把窗口背景颜色传到这个函数里来实现半透明效果,不过这个可能需要修改较多的代码。