1// Dear ImGui: standalone example application for Win32 + OpenGL 3
2
3// Learn about Dear ImGui:
4// - FAQ https://dearimgui.com/faq
5// - Getting Started https://dearimgui.com/getting-started
6// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
7// - Introduction, links and more at the top of imgui.cpp
8
9// This is provided for completeness, however it is strongly recommended you use OpenGL with SDL or GLFW.
10
11#include "imgui.h"
12#include "imgui_impl_opengl3.h"
13#include "imgui_impl_win32.h"
14#ifndef WIN32_LEAN_AND_MEAN
15#define WIN32_LEAN_AND_MEAN
16#endif
17#include <windows.h>
18#include <GL/GL.h>
19#include <tchar.h>
20
21// Data stored per platform window
22struct WGL_WindowData { HDC hDC; };
23
24// Data
25static HGLRC g_hRC;
26static WGL_WindowData g_MainWindow;
27static int g_Width;
28static int g_Height;
29
30// Forward declarations of helper functions
31bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data);
32void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data);
33void ResetDeviceWGL();
34LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
35
36// Support function for multi-viewports
37// Unlike most other backend combination, we need specific hooks to combine Win32+OpenGL.
38// We could in theory decide to support Win32-specific code in OpenGL backend via e.g. an hypothetical ImGui_ImplOpenGL3_InitForRawWin32().
39static void Hook_Renderer_CreateWindow(ImGuiViewport* viewport)
40{
41 assert(viewport->RendererUserData == NULL);
42
43 WGL_WindowData* data = IM_NEW(WGL_WindowData);
44 CreateDeviceWGL((HWND)viewport->PlatformHandle, data);
45 viewport->RendererUserData = data;
46}
47
48static void Hook_Renderer_DestroyWindow(ImGuiViewport* viewport)
49{
50 if (viewport->RendererUserData != NULL)
51 {
52 WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData;
53 CleanupDeviceWGL((HWND)viewport->PlatformHandle, data);
54 IM_DELETE(p: data);
55 viewport->RendererUserData = NULL;
56 }
57}
58
59static void Hook_Platform_RenderWindow(ImGuiViewport* viewport, void*)
60{
61 // Activate the platform window DC in the OpenGL rendering context
62 if (WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData)
63 wglMakeCurrent(data->hDC, g_hRC);
64}
65
66static void Hook_Renderer_SwapBuffers(ImGuiViewport* viewport, void*)
67{
68 if (WGL_WindowData* data = (WGL_WindowData*)viewport->RendererUserData)
69 ::SwapBuffers(data->hDC);
70}
71
72// Main code
73int main(int, char**)
74{
75 // Create application window
76 //ImGui_ImplWin32_EnableDpiAwareness();
77 WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr };
78 ::RegisterClassExW(&wc);
79 HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+OpenGL3 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr);
80
81 // Initialize OpenGL
82 if (!CreateDeviceWGL(hwnd, &g_MainWindow))
83 {
84 CleanupDeviceWGL(hwnd, &g_MainWindow);
85 ::DestroyWindow(hwnd);
86 ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
87 return 1;
88 }
89 wglMakeCurrent(g_MainWindow.hDC, g_hRC);
90
91 // Show the window
92 ::ShowWindow(hwnd, SW_SHOWDEFAULT);
93 ::UpdateWindow(hwnd);
94
95 // Setup Dear ImGui context
96 IMGUI_CHECKVERSION();
97 ImGui::CreateContext();
98 ImGuiIO& io = ImGui::GetIO(); (void)io;
99 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
100 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
101 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
102 io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
103
104 // Setup Dear ImGui style
105 ImGui::StyleColorsDark();
106 //ImGui::StyleColorsClassic();
107
108 // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
109 ImGuiStyle& style = ImGui::GetStyle();
110 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
111 {
112 style.WindowRounding = 0.0f;
113 style.Colors[ImGuiCol_WindowBg].w = 1.0f;
114 }
115
116 // Setup Platform/Renderer backends
117 ImGui_ImplWin32_InitForOpenGL(hwnd);
118 ImGui_ImplOpenGL3_Init();
119
120 // Win32+GL needs specific hooks for viewport, as there are specific things needed to tie Win32 and GL api.
121 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
122 {
123 ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
124 IM_ASSERT(platform_io.Renderer_CreateWindow == NULL);
125 IM_ASSERT(platform_io.Renderer_DestroyWindow == NULL);
126 IM_ASSERT(platform_io.Renderer_SwapBuffers == NULL);
127 IM_ASSERT(platform_io.Platform_RenderWindow == NULL);
128 platform_io.Renderer_CreateWindow = Hook_Renderer_CreateWindow;
129 platform_io.Renderer_DestroyWindow = Hook_Renderer_DestroyWindow;
130 platform_io.Renderer_SwapBuffers = Hook_Renderer_SwapBuffers;
131 platform_io.Platform_RenderWindow = Hook_Platform_RenderWindow;
132 }
133
134 // Load Fonts
135 // - 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.
136 // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
137 // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
138 // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
139 // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
140 // - Read 'docs/FONTS.md' for more instructions and details.
141 // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
142 //io.Fonts->AddFontDefault();
143 //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
144 //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
145 //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
146 //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
147 //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
148 //IM_ASSERT(font != nullptr);
149
150 // Our state
151 bool show_demo_window = true;
152 bool show_another_window = false;
153 ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
154
155 // Main loop
156 bool done = false;
157 while (!done)
158 {
159 // Poll and handle messages (inputs, window resize, etc.)
160 // See the WndProc() function below for our to dispatch events to the Win32 backend.
161 MSG msg;
162 while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
163 {
164 ::TranslateMessage(&msg);
165 ::DispatchMessage(&msg);
166 if (msg.message == WM_QUIT)
167 done = true;
168 }
169 if (done)
170 break;
171 if (::IsIconic(hwnd))
172 {
173 ::Sleep(10);
174 continue;
175 }
176
177 // Start the Dear ImGui frame
178 ImGui_ImplOpenGL3_NewFrame();
179 ImGui_ImplWin32_NewFrame();
180 ImGui::NewFrame();
181
182 // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
183 if (show_demo_window)
184 ImGui::ShowDemoWindow(p_open: &show_demo_window);
185
186 // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
187 {
188 static float f = 0.0f;
189 static int counter = 0;
190
191 ImGui::Begin(name: "Hello, world!"); // Create a window called "Hello, world!" and append into it.
192
193 ImGui::Text(fmt: "This is some useful text."); // Display some text (you can use a format strings too)
194 ImGui::Checkbox(label: "Demo Window", v: &show_demo_window); // Edit bools storing our window open/close state
195 ImGui::Checkbox(label: "Another Window", v: &show_another_window);
196
197 ImGui::SliderFloat(label: "float", v: &f, v_min: 0.0f, v_max: 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
198 ImGui::ColorEdit3(label: "clear color", col: (float*)&clear_color); // Edit 3 floats representing a color
199
200 if (ImGui::Button(label: "Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
201 counter++;
202 ImGui::SameLine();
203 ImGui::Text(fmt: "counter = %d", counter);
204
205 ImGui::Text(fmt: "Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
206 ImGui::End();
207 }
208
209 // 3. Show another simple window.
210 if (show_another_window)
211 {
212 ImGui::Begin(name: "Another Window", p_open: &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
213 ImGui::Text(fmt: "Hello from another window!");
214 if (ImGui::Button(label: "Close Me"))
215 show_another_window = false;
216 ImGui::End();
217 }
218
219 // Rendering
220 ImGui::Render();
221 glViewport(0, 0, g_Width, g_Height);
222 glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
223 glClear(GL_COLOR_BUFFER_BIT);
224 ImGui_ImplOpenGL3_RenderDrawData(draw_data: ImGui::GetDrawData());
225
226 // Update and Render additional Platform Windows
227 if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
228 {
229 ImGui::UpdatePlatformWindows();
230 ImGui::RenderPlatformWindowsDefault();
231
232 // Restore the OpenGL rendering context to the main window DC, since platform windows might have changed it.
233 wglMakeCurrent(g_MainWindow.hDC, g_hRC);
234 }
235
236 // Present
237 ::SwapBuffers(g_MainWindow.hDC);
238 }
239
240 ImGui_ImplOpenGL3_Shutdown();
241 ImGui_ImplWin32_Shutdown();
242 ImGui::DestroyContext();
243
244 CleanupDeviceWGL(hwnd, &g_MainWindow);
245 wglDeleteContext(g_hRC);
246 ::DestroyWindow(hwnd);
247 ::UnregisterClassW(wc.lpszClassName, wc.hInstance);
248
249 return 0;
250}
251
252// Helper functions
253bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data)
254{
255 HDC hDc = ::GetDC(hWnd);
256 PIXELFORMATDESCRIPTOR pfd = { 0 };
257 pfd.nSize = sizeof(pfd);
258 pfd.nVersion = 1;
259 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
260 pfd.iPixelType = PFD_TYPE_RGBA;
261 pfd.cColorBits = 32;
262
263 const int pf = ::ChoosePixelFormat(hDc, &pfd);
264 if (pf == 0)
265 return false;
266 if (::SetPixelFormat(hDc, pf, &pfd) == FALSE)
267 return false;
268 ::ReleaseDC(hWnd, hDc);
269
270 data->hDC = ::GetDC(hWnd);
271 if (!g_hRC)
272 g_hRC = wglCreateContext(data->hDC);
273 return true;
274}
275
276void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data)
277{
278 wglMakeCurrent(nullptr, nullptr);
279 ::ReleaseDC(hWnd, data->hDC);
280}
281
282// Forward declare message handler from imgui_impl_win32.cpp
283extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
284
285// Win32 message handler
286// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
287// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
288// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
289// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
290LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
291{
292 if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
293 return true;
294
295 switch (msg)
296 {
297 case WM_SIZE:
298 if (wParam != SIZE_MINIMIZED)
299 {
300 g_Width = LOWORD(lParam);
301 g_Height = HIWORD(lParam);
302 }
303 return 0;
304 case WM_SYSCOMMAND:
305 if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
306 return 0;
307 break;
308 case WM_DESTROY:
309 ::PostQuitMessage(0);
310 return 0;
311 }
312 return ::DefWindowProcW(hWnd, msg, wParam, lParam);
313}
314

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of imgui/examples/example_win32_opengl3/main.cpp