175 g_hwnd = glfwGetWin32Window(window);
180 g_origWndProc =
reinterpret_cast<WNDPROC
>(
181 SetWindowLongPtr(g_hwnd, GWLP_WNDPROC,
182 reinterpret_cast<LONG_PTR
>(customWndProc)));
185 MARGINS m = { 0, 0, 0, 1 };
186 DwmExtendFrameIntoClientArea(g_hwnd, &m);
191 constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE_VAL = 33;
192 constexpr DWORD DWMWCP_DONOTROUND_VAL = 1;
193 DwmSetWindowAttribute(g_hwnd, DWMWA_WINDOW_CORNER_PREFERENCE_VAL,
194 &DWMWCP_DONOTROUND_VAL,
sizeof(DWMWCP_DONOTROUND_VAL));
197 SetWindowPos(g_hwnd,
nullptr, 0, 0, 0, 0,
198 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE |
199 SWP_NOZORDER | SWP_NOOWNERZORDER);
210 const ImGuiViewport* vp = ImGui::GetMainViewport();
214 const float frameH = ImGui::GetFrameHeight();
215 g_titleBarHeight = frameH + ImGui::GetStyle().FramePadding.y * 2.0f;
217 ImGui::SetNextWindowPos(vp->WorkPos);
218 ImGui::SetNextWindowSize(ImVec2(vp->WorkSize.x, g_titleBarHeight));
220 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
221 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
222 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
223 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_MenuBarBg));
225 ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar |
226 ImGuiWindowFlags_NoResize |
227 ImGuiWindowFlags_NoMove |
228 ImGuiWindowFlags_NoScrollbar |
229 ImGuiWindowFlags_NoSavedSettings |
230 ImGuiWindowFlags_NoDocking |
231 ImGuiWindowFlags_MenuBar |
232 ImGuiWindowFlags_NoBringToFrontOnFocus;
234 ImGui::Begin(
"##CustomTitleBar",
nullptr, flags);
235 ImGui::PopStyleColor(1);
236 ImGui::PopStyleVar(3);
239 if (ImGui::BeginMenuBar())
244 const float menuStartX = ImGui::GetCursorScreenPos().x - vp->Pos.x;
245 g_menuRect.left =
static_cast<LONG
>(menuStartX);
247 g_menuRect.bottom =
static_cast<LONG
>(g_titleBarHeight);
254 return ImGui::BeginMainMenuBar();
263 const float menuEndX = ImGui::GetCursorScreenPos().x - ImGui::GetMainViewport()->Pos.x;
264 g_menuRect.right =
static_cast<LONG
>(menuEndX);
268 const ImGuiViewport* vp = ImGui::GetMainViewport();
271 const float btnW = ImGui::GetFrameHeight() * 1.6f;
272 const float btnH = g_titleBarHeight;
273 const float controlsWidth = btnW * 3.0f;
276 if (statusText && statusText[0])
278 const float textW = ImGui::CalcTextSize(statusText).x;
279 const float availX = vp->WorkSize.x - controlsWidth - 20.0f;
280 if (availX > textW + 20.0f)
282 ImGui::SameLine(availX - textW);
283 ImGui::TextDisabled(
"%s", statusText);
288 const float startX = vp->WorkSize.x - controlsWidth;
289 ImGui::SameLine(startX);
294 const float btnLeft = ImGui::GetCursorScreenPos().x - vp->Pos.x;
295 g_controlButtonsRect.left =
static_cast<LONG
>(btnLeft);
296 g_controlButtonsRect.top = 0;
297 g_controlButtonsRect.right =
static_cast<LONG
>(btnLeft + controlsWidth);
298 g_controlButtonsRect.bottom =
static_cast<LONG
>(g_titleBarHeight);
303 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
304 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
305 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
306 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
307 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1, 1, 1, 0.15f));
308 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1, 1, 1, 0.25f));
313 ImGui::PushFont(g_iconFont);
319 const char* lblMin = g_hasIconFont ?
"\xEE\xA4\xA1##min" :
" - ##min";
320 const char* lblMax = g_hasIconFont ?
"\xEE\xA4\xA2##max" :
" [] ##max";
321 const char* lblRest = g_hasIconFont ?
"\xEE\xA4\xA3##max" :
" = ##max";
322 const char* lblClose = g_hasIconFont ?
"\xEE\xA2\xBB##close" :
" X ##close";
325 if (ImGui::Button(lblMin, ImVec2(btnW, btnH)))
327 if (g_hwnd) ShowWindow(g_hwnd, SW_MINIMIZE);
332 const bool isMaximised = g_hwnd && IsZoomed(g_hwnd);
333 if (ImGui::Button(isMaximised ? lblRest : lblMax, ImVec2(btnW, btnH)))
335 if (g_hwnd) ShowWindow(g_hwnd, isMaximised ? SW_RESTORE : SW_MAXIMIZE);
340 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.90f, 0.18f, 0.18f, 1.0f));
341 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.75f, 0.10f, 0.10f, 1.0f));
342 if (ImGui::Button(lblClose, ImVec2(btnW, btnH)))
344 if (window) glfwSetWindowShouldClose(window, GLFW_TRUE);
346 ImGui::PopStyleColor(2);
351 ImGui::PopStyleColor(3);
352 ImGui::PopStyleVar(3);
361 if (!IsZoomed(g_hwnd))
363 ImDrawList* fg = ImGui::GetForegroundDrawList();
364 const ImVec2 p0 = vp->Pos;
365 const ImVec2 p1 = ImVec2(vp->Pos.x + vp->Size.x, vp->Pos.y + vp->Size.y);
366 const ImU32 borderCol = ImGui::GetColorU32(ImGuiCol_Border);
367 fg->AddRect(p0, p1, borderCol, 0.0f, 0, 1.0f);
372 if (statusText && statusText[0])
374 float textWidth = ImGui::CalcTextSize(statusText).x;
375 ImGui::SameLine(ImGui::GetWindowWidth() - textWidth - 10.0f);
376 ImGui::TextDisabled(
"%s", statusText);
378 ImGui::EndMainMenuBar();
392 const char* fontPath =
"C:\\Windows\\Fonts\\segmdl2.ttf";
393 if (!std::filesystem::exists(fontPath))
395 g_iconFont =
nullptr;
396 g_hasIconFont =
false;
401 static const ImWchar ranges[] = { 0xE8BB, 0xE8BB, 0xE921, 0xE923, 0 };
404 cfg.PixelSnapH =
true;
408 const float iconSize = pixelSize * 0.55f;
411 cfg.GlyphOffset.y = -std::round(iconSize * 0.4f);
413 g_iconFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(
414 fontPath, iconSize, &cfg, ranges);
415 g_hasIconFont = (g_iconFont !=
nullptr);
418 g_iconFont =
nullptr;
419 g_hasIconFont =
false;