Browse Source

Examples: Extend Win32/Winapi + OpenGL example for multi-viewport. (#3218, #5170 and #6086, #2772, #2600, #2359, #2022, #1553)

Mark Jansen 2 years ago
parent
commit
4bc51c6ff4
2 changed files with 81 additions and 5 deletions
  1. 4 5
      backends/imgui_impl_win32.cpp
  2. 77 0
      examples/example_win32_opengl3/main.cpp

+ 4 - 5
backends/imgui_impl_win32.cpp

@@ -87,7 +87,7 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
 //  2016-11-12: Inputs: Only call Win32 ::SetCursor(nullptr) when io.MouseDrawCursor is set.
 
 // Forward Declarations
-static void ImGui_ImplWin32_InitPlatformInterface();
+static void ImGui_ImplWin32_InitPlatformInterface(bool platformHasOwnDC);
 static void ImGui_ImplWin32_ShutdownPlatformInterface();
 static void ImGui_ImplWin32_UpdateMonitors();
 
@@ -153,8 +153,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
     ImGuiViewport* main_viewport = ImGui::GetMainViewport();
     main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd;
     if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
-        ImGui_ImplWin32_InitPlatformInterface();
-    IM_UNUSED(platform_has_own_dc); // Used in 'docking' branch
+        ImGui_ImplWin32_InitPlatformInterface(platform_has_own_dc);
 
     // Dynamically load XInput library
 #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
@@ -1166,11 +1165,11 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
     return DefWindowProc(hWnd, msg, wParam, lParam);
 }
 
-static void ImGui_ImplWin32_InitPlatformInterface()
+static void ImGui_ImplWin32_InitPlatformInterface(bool platformHasOwnDC)
 {
     WNDCLASSEX wcex;
     wcex.cbSize = sizeof(WNDCLASSEX);
-    wcex.style = CS_HREDRAW | CS_VREDRAW;
+    wcex.style = CS_HREDRAW | CS_VREDRAW | (platformHasOwnDC ? CS_OWNDC : 0);
     wcex.lpfnWndProc = ImGui_ImplWin32_WndProcHandler_PlatformWindow;
     wcex.cbClsExtra = 0;
     wcex.cbWndExtra = 0;

+ 77 - 0
examples/example_win32_opengl3/main.cpp

@@ -29,6 +29,48 @@ void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data);
 void ResetDeviceWGL();
 LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 
+
+static void Win32_CreateWindow(ImGuiViewport* viewport)
+{
+    assert(viewport->RendererUserData == NULL);
+
+    WGL_WindowData* data = IM_NEW(WGL_WindowData);
+    CreateDeviceWGL((HWND)viewport->PlatformHandle, data);
+    viewport->RendererUserData = data;
+}
+
+static void Win32_DestroyWindow(ImGuiViewport* viewport)
+{
+    if (viewport->RendererUserData != NULL)
+    {
+        WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData;
+        CleanupDeviceWGL((HWND)viewport->PlatformHandle, data);
+        IM_DELETE(data);
+        viewport->RendererUserData = NULL;
+    }
+}
+
+static void Win32_RenderWindow(ImGuiViewport* viewport, void*)
+{
+    WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData;
+
+    if (data)
+    {
+        // Activate the platform window DC in the OpenGL rendering context
+        wglMakeCurrent(data->hDC, g_hRC);
+    }
+}
+
+static void Win32_SwapBuffers(ImGuiViewport* viewport, void*)
+{
+    WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData;
+
+    if (data)
+    {
+        SwapBuffers(data->hDC);
+    }
+}
+
 // Main code
 int main(int, char**)
 {
@@ -58,15 +100,41 @@ int main(int, char**)
     ImGuiIO& io = ImGui::GetIO(); (void)io;
     io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;   // Enable Keyboard Controls
     io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;    // Enable Gamepad Controls
+    io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;       // Enable Docking
+    io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;     // Enable Multi-Viewport / Platform Windows
 
     // Setup Dear ImGui style
     ImGui::StyleColorsDark();
     //ImGui::StyleColorsClassic();
 
+    // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
+    ImGuiStyle& style = ImGui::GetStyle();
+    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
+    {
+        style.WindowRounding = 0.0f;
+        style.Colors[ImGuiCol_WindowBg].w = 1.0f;
+    }
+
     // Setup Platform/Renderer backends
     ImGui_ImplWin32_InitForOpenGL(hwnd);
     ImGui_ImplOpenGL3_Init();
 
+    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
+    {
+        ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+
+        // Store the hdc for this new window
+        assert(platform_io.Renderer_CreateWindow == NULL);
+        platform_io.Renderer_CreateWindow = Win32_CreateWindow;
+        assert(platform_io.Renderer_DestroyWindow == NULL);
+        platform_io.Renderer_DestroyWindow = Win32_DestroyWindow;
+        assert(platform_io.Renderer_SwapBuffers == NULL);
+        platform_io.Renderer_SwapBuffers = Win32_SwapBuffers;
+
+        // We need to activate the context before drawing
+        assert(platform_io.Platform_RenderWindow == NULL);
+        platform_io.Platform_RenderWindow = Win32_RenderWindow;
+    }
     // Load Fonts
     // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
     // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
@@ -154,6 +222,15 @@ int main(int, char**)
         glClear(GL_COLOR_BUFFER_BIT);
         ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
 
+        // Update and Render additional Platform Windows
+        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
+        {
+            ImGui::UpdatePlatformWindows();
+            ImGui::RenderPlatformWindowsDefault();
+            // Restore the OpenGL rendering context to the main window DC, since platform windows might have changed it.
+            wglMakeCurrent(g_MainWindow.hDC, g_hRC);
+        }
+
         // Present
         ::SwapBuffers(g_MainWindow.hDC);
     }