Browse Source

Windows 98 style

Jake Coxon 5 years ago
parent
commit
1945f456f1
7 changed files with 336 additions and 1 deletions
  1. BIN
      MS Sans Serif Bold.ttf
  2. BIN
      MS Sans Serif.ttf
  3. 2 0
      imconfig.h
  4. 110 1
      imgui.cpp
  5. 5 0
      imgui.h
  6. 141 0
      imgui_draw.cpp
  7. 78 0
      imgui_widgets.cpp

BIN
MS Sans Serif Bold.ttf


BIN
MS Sans Serif.ttf


+ 2 - 0
imconfig.h

@@ -13,6 +13,8 @@
 
 #pragma once
 
+#define WIN98
+
 //---- Define assertion handler. Defaults to calling assert().
 // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
 //#define IM_ASSERT(_EXPR)  MyAssert(_EXPR)

+ 110 - 1
imgui.cpp

@@ -2664,8 +2664,12 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border,
     const float border_size = g.Style.FrameBorderSize;
     if (border && border_size > 0.0f)
     {
+#ifdef WIN98
+        WinAddRect(p_min, p_max, true);
+#else
         window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
         window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+#endif
     }
 }
 
@@ -5165,11 +5169,57 @@ static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& visibility
     window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
 }
 
+void ImGui::WinAddRect(const ImVec2& min, const ImVec2& max, bool inset)
+{
+    ImU32 top_left = IM_COL32(255,255,255,255);
+    ImU32 bottom_right = IM_COL32(0,0,0,255);
+    ImU32 top_left_inner = IM_COL32(223,223,223,255);
+    ImU32 bottom_right_inner = IM_COL32(128,128,128,255);
+
+    if (inset) {
+        ImU32 tmp = top_left; top_left = bottom_right; bottom_right = tmp;
+        tmp = top_left_inner; top_left_inner = bottom_right_inner; bottom_right_inner = tmp;
+    }
+
+    // ImU32 fill_col = IM_COL32(192,192,192,255);
+
+    ImDrawList* draw_list = ImGui::GetWindowDrawList();
+    ImVec2 a = min + ImVec2(0.5f, 0.5f);
+    ImVec2 b = max - ImVec2(0.5f, 0.5f);
+
+    draw_list->PathLineTo(ImVec2(a.x, b.y));
+    draw_list->PathLineTo(a);
+    draw_list->PathLineTo(ImVec2(b.x, a.y));
+    draw_list->PathStroke(top_left, false, 1.0f);
+
+    draw_list->PathLineTo(ImVec2(a.x, b.y));
+    draw_list->PathLineTo(b);
+    draw_list->PathLineTo(ImVec2(b.x, a.y));
+    draw_list->PathStroke(bottom_right, false, 1.0f);
+
+
+    draw_list->PathLineTo(ImVec2(a.x, b.y) + ImVec2(1, -1));
+    draw_list->PathLineTo(a + ImVec2(1, 1));
+    draw_list->PathLineTo(ImVec2(b.x, a.y) + ImVec2(-1, 1));
+    draw_list->PathStroke(top_left_inner, false, 1.0f);
+
+    draw_list->PathLineTo(ImVec2(a.x, b.y) + ImVec2(1, -1));
+    draw_list->PathLineTo(b + ImVec2(-1, -1));
+    draw_list->PathLineTo(ImVec2(b.x, a.y) + ImVec2(-1, 1));
+    draw_list->PathStroke(bottom_right_inner, false, 1.0f);
+}
+
+
 static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
 {
     ImGuiContext& g = *GImGui;
     float rounding = window->WindowRounding;
     float border_size = window->WindowBorderSize;
+
+#ifdef WIN98 // window borders
+    if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
+        WinAddRect(window->Pos, window->Pos + window->Size, false);
+#else
     if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
         window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
 
@@ -5187,6 +5237,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
         float y = window->Pos.y + window->TitleBarHeight() - 1;
         window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize);
     }
+#endif
 }
 
 // Draw background and borders
@@ -5294,6 +5345,11 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
     float pad_l = style.FramePadding.x;
     float pad_r = style.FramePadding.x;
     float button_sz = g.FontSize;
+#ifdef WIN98 // draw title bar
+    button_sz = 16.0f;
+    // pad_l = 0.0f;
+    pad_r = 0.0f;
+#endif
     ImVec2 close_button_pos;
     ImVec2 collapse_button_pos;
     if (has_close_button)
@@ -5312,6 +5368,38 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
         pad_l += button_sz;
     }
 
+#ifdef WIN98 // windows style title bar
+
+    close_button_pos += ImVec2(0.0f, 2.0f);
+    collapse_button_pos += ImVec2(0.0f, 2.0f);
+
+    ImU32 col_left = IM_COL32(128,128,128,255);
+    ImU32 col_right = IM_COL32(181,181,181,255);
+
+    bool focused = IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
+    if (focused) {
+
+        // Windows98 colors are (0,0,128), (16,132,208)
+        // This code generates the secondary color from the primary while
+        // keeping the original windows colors
+        col_left = GetColorU32(ImGuiCol_TitleBgActive);
+
+        ImVec4 secondary = GetStyleColorVec4(ImGuiCol_TitleBgActive);
+        ImVec4 secondary_hsv;
+        ColorConvertRGBtoHSV(secondary.x, secondary.y, secondary.z, secondary_hsv.x, secondary_hsv.y, secondary_hsv.z);
+        secondary_hsv.x -= 0.1f;
+        if (secondary_hsv.x < 0.0f) secondary_hsv.x += 1.0f;
+        secondary_hsv.y *= 0.92f;
+        secondary_hsv.z *= 1.625f;
+        ColorConvertHSVtoRGB(secondary_hsv.x, secondary_hsv.y, secondary_hsv.z, secondary.x, secondary.y, secondary.z);
+
+        col_right = ColorConvertFloat4ToU32(secondary);
+    }
+
+
+    window->DrawList->AddRectFilledMultiColor(title_bar_rect.Min, title_bar_rect.Max, col_left, col_right, col_right, col_left);
+#endif
+
     // Collapse button (submitting first so it gets priority when choosing a navigation init fallback)
     if (has_collapse_button)
         if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos))
@@ -5346,6 +5434,14 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
         pad_r = ImMax(pad_r, pad_extend * centerness);
     }
 
+#ifdef WIN98 // windows title font
+    if (focused) PushStyleColor(ImGuiCol_Text, IM_COL32(255,255,255,255));
+    else PushStyleColor(ImGuiCol_Text, IM_COL32(192,192,192,255));
+    ImGuiIO& io = ImGui::GetIO();
+    ImFont* font = io.Fonts->Fonts[1]; // Assume the icon font is here. pretty bad
+    PushFont(font);
+#endif
+
     ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
     ImRect clip_r(layout_r.Min.x, layout_r.Min.y, layout_r.Max.x + g.Style.ItemInnerSpacing.x, layout_r.Max.y);
     //if (g.IO.KeyCtrl) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
@@ -5356,6 +5452,11 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
         ImVec2 off = ImVec2(0.0f, IM_FLOOR(-g.FontSize * 0.25f));
         RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);
     }
+
+#ifdef WIN98
+    PopFont();
+    PopStyleColor();
+#endif
 }
 
 void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
@@ -5937,8 +6038,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         }
 
         // Title bar
-        if (!(flags & ImGuiWindowFlags_NoTitleBar))
+        if (!(flags & ImGuiWindowFlags_NoTitleBar)) {
+#ifdef WIN98 // title bar sizing
+            ImRect inset_title_rect = title_bar_rect;
+            inset_title_rect.Min += ImVec2(2.0f, 2.0f);
+            inset_title_rect.Max -= ImVec2(2.0f, 0.0f);
+            RenderWindowTitleBarContents(window, inset_title_rect, name, p_open);
+#else
             RenderWindowTitleBarContents(window, title_bar_rect, name, p_open);
+#endif
+        }
 
         // Pressing CTRL+C while holding on a window copy its content to the clipboard
         // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.

+ 5 - 0
imgui.h

@@ -776,6 +776,11 @@ namespace ImGui
     IMGUI_API void*         MemAlloc(size_t size);
     IMGUI_API void          MemFree(void* ptr);
 
+    // Windows98 functions
+    IMGUI_API void          WinAddRect(const ImVec2& min, const ImVec2& max, bool inset);
+    IMGUI_API void          StyleWin98(ImGuiStyle* dst = NULL);
+
+
 } // namespace ImGui
 
 //-----------------------------------------------------------------------------

+ 141 - 0
imgui_draw.cpp

@@ -174,6 +174,12 @@ using namespace IMGUI_STB_NAMESPACE;
 
 void ImGui::StyleColorsDark(ImGuiStyle* dst)
 {
+#ifdef WIN98
+    // These colors don't make sense with win98 so just call this anyway
+    // also means I don't have to change all the examples
+    StyleWin98(dst);
+    return;
+#endif
     ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
     ImVec4* colors = style->Colors;
 
@@ -229,6 +235,12 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
 
 void ImGui::StyleColorsClassic(ImGuiStyle* dst)
 {
+#ifdef WIN98
+    // These colors don't make sense with win98 so just call this anyway
+    // also means I don't have to change all the examples
+    StyleWin98(dst);
+    return;
+#endif
     ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
     ImVec4* colors = style->Colors;
 
@@ -285,6 +297,13 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
 // Those light colors are better suited with a thicker font than the default one + FrameBorder
 void ImGui::StyleColorsLight(ImGuiStyle* dst)
 {
+#ifdef WIN98
+    // These colors don't make sense with win98 so just call this anyway
+    // also means I don't have to change all the examples
+    StyleWin98(dst);
+    return;
+#endif
+
     ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
     ImVec4* colors = style->Colors;
 
@@ -338,6 +357,128 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
     colors[ImGuiCol_ModalWindowDimBg]       = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
 }
 
+// Windows style config
+#ifdef WIN98
+void ImGui::StyleWin98(ImGuiStyle* dst)
+{
+    ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+    style->FrameBorderSize = 1.0f;
+    style->FramePadding = ImVec2(4.0f, 4.0f);
+    style->WindowMenuButtonPosition = ImGuiDir_Right;
+    style->ScrollbarSize = 16.0f;
+
+    ImVec4* colors = style->Colors;
+
+    colors[ImGuiCol_Text]                   = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
+    colors[ImGuiCol_TextDisabled]           = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
+    colors[ImGuiCol_WindowBg]               = ImVec4(0.75f, 0.75f, 0.75f, 1.00f);
+    colors[ImGuiCol_ChildBg]                = ImVec4(0.75f, 0.75f, 0.75f, 1.00f);
+    colors[ImGuiCol_PopupBg]                = ImVec4(0.75f, 0.75f, 0.75f, 1.00f);
+    colors[ImGuiCol_Border]                 = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
+    colors[ImGuiCol_BorderShadow]           = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+    colors[ImGuiCol_FrameBg]                = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+    colors[ImGuiCol_FrameBgHovered]         = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+    colors[ImGuiCol_FrameBgActive]          = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+    colors[ImGuiCol_TitleBg]                = ImVec4(0.96f, 0.96f, 0.96f, 1.00f);
+    colors[ImGuiCol_TitleBgActive]          = ImVec4(0.00f, 0.00f, 0.50f, 1.00f);
+    colors[ImGuiCol_TitleBgCollapsed]       = ImVec4(1.00f, 1.00f, 1.00f, 0.51f);
+    colors[ImGuiCol_MenuBarBg]              = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
+    colors[ImGuiCol_ScrollbarBg]            = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);
+    colors[ImGuiCol_ScrollbarGrab]          = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
+    colors[ImGuiCol_ScrollbarGrabHovered]   = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
+    colors[ImGuiCol_ScrollbarGrabActive]    = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
+    colors[ImGuiCol_CheckMark]              = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+    colors[ImGuiCol_SliderGrab]             = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
+    colors[ImGuiCol_SliderGrabActive]       = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
+    colors[ImGuiCol_Button]                 = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+    colors[ImGuiCol_ButtonHovered]          = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+    colors[ImGuiCol_ButtonActive]           = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
+    colors[ImGuiCol_Header]                 = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
+    colors[ImGuiCol_HeaderHovered]          = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
+    colors[ImGuiCol_HeaderActive]           = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+    colors[ImGuiCol_Separator]              = ImVec4(0.39f, 0.39f, 0.39f, 0.62f);
+    colors[ImGuiCol_SeparatorHovered]       = ImVec4(0.14f, 0.44f, 0.80f, 0.78f);
+    colors[ImGuiCol_SeparatorActive]        = ImVec4(0.14f, 0.44f, 0.80f, 1.00f);
+    colors[ImGuiCol_ResizeGrip]             = ImVec4(0.80f, 0.80f, 0.80f, 0.56f);
+    colors[ImGuiCol_ResizeGripHovered]      = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+    colors[ImGuiCol_ResizeGripActive]       = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+    colors[ImGuiCol_Tab]                    = ImVec4(0.76f, 0.80f, 0.84f, 0.95f);
+    colors[ImGuiCol_TabHovered]             = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+    colors[ImGuiCol_TabActive]              = ImVec4(0.60f, 0.73f, 0.88f, 0.95f);
+    colors[ImGuiCol_TabUnfocused]           = ImVec4(0.92f, 0.92f, 0.94f, 0.95f);
+    colors[ImGuiCol_TabUnfocusedActive]     = ImVec4(0.74f, 0.82f, 0.91f, 1.00f);
+    colors[ImGuiCol_PlotLines]              = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+    colors[ImGuiCol_PlotLinesHovered]       = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
+    colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+    colors[ImGuiCol_PlotHistogramHovered]   = ImVec4(1.00f, 0.45f, 0.00f, 1.00f);
+    colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
+    colors[ImGuiCol_DragDropTarget]         = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+    colors[ImGuiCol_NavHighlight]           = colors[ImGuiCol_HeaderHovered];
+    colors[ImGuiCol_NavWindowingHighlight]  = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
+    colors[ImGuiCol_NavWindowingDimBg]      = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
+    colors[ImGuiCol_ModalWindowDimBg]       = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
+
+
+    if (dst != NULL) return;
+
+    // Fonts + Icons
+    ImGuiIO& io = ImGui::GetIO();
+    for (int i = 0; i < io.Fonts->ConfigData.size(); i++) {
+        if (strcmp(io.Fonts->ConfigData[i].Name, "MS Sans Serif")) {
+            return;
+        }
+    }
+    ImFont *font = io.Fonts->AddFontFromFileTTF("../../MS Sans Serif.ttf", 12.0f, NULL, io.Fonts->GetGlyphRangesDefault());
+    io.Fonts->AddFontFromFileTTF("../../MS Sans Serif Bold.ttf", 12.0f, NULL, io.Fonts->GetGlyphRangesDefault());
+
+    // Run-length encoding of some icons
+    // In retrorespect I should have used an icon map like FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS
+    unsigned char minimize[] = {86,6,6,6,0};
+    unsigned char close[] = {14,2,4,2,5,2,2,2,7,4,9,2,9,4,7,2,2,2,5,2,4,2,0};
+    unsigned char *run_length[] = {minimize, close};
+
+    int rect_ids[IM_ARRAYSIZE(run_length)];
+    for (int i = 0; i < IM_ARRAYSIZE(run_length); i++) {
+        rect_ids[i] = io.Fonts->AddCustomRectFontGlyph(font, 214 + i, 12, 9, 13+1);
+    }
+
+    io.Fonts->Build();
+
+    unsigned char* tex_pixels = NULL;
+    int tex_width, tex_height;
+    io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
+
+    for (int i = 0; i < IM_ARRAYSIZE(run_length); i++) {
+
+        int rect_id = rect_ids[i];
+        if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id)) {
+            bool black = false;
+            unsigned char* run = run_length[i];
+            int run_size = 0;
+
+            for (int y = 0; y < rect->Height; y++)
+            {
+                ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X);
+                for (int x = rect->Width; x > 0; x--) {
+                    if (black) *p = IM_COL32(255, 0, 0, 255);
+                    p ++;
+                    run_size ++;
+                    if (run_size == *run) {
+                        run_size = 0;
+                        run ++;
+                        black = !black;
+                        if (*run == 0) goto done;
+                    }
+                }
+            }
+            done:;
+        }
+    }
+
+
+}
+#endif
+
 //-----------------------------------------------------------------------------
 // ImDrawList
 //-----------------------------------------------------------------------------

+ 78 - 0
imgui_widgets.cpp

@@ -668,9 +668,19 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
 
     // Render
     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+#ifdef WIN98
+    const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg);
+    window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f);
+
+    WinAddRect(bb.Min, bb.Max, (held && hovered));
+    PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
+    RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
+    PopStyleColor();
+#else
     RenderNavHighlight(bb, id);
     RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
     RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
+#endif
 
     // Automatically close popups
     //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
@@ -762,9 +772,13 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
 
+#ifdef WIN98 // close button size
+    const ImRect bb(pos, pos + ImVec2(16.0f, 14.0f));
+#else
     // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
     // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
     const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
+#endif
     bool is_clipped = !ItemAdd(bb, id);
 
     bool hovered, held;
@@ -775,14 +789,25 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
     // Render
     ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
     ImVec2 center = bb.GetCenter();
+
+#ifdef WIN98 // close button
+    const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg);
+    window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f);
+    WinAddRect(bb.Min, bb.Max, hovered && held);
+#else
     if (hovered)
         window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
+#endif
 
     float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
     ImU32 cross_col = GetColorU32(ImGuiCol_Text);
     center -= ImVec2(0.5f, 0.5f);
+#ifdef WIN98 // close button icon
+    RenderText(bb.Min + ImVec2(2.0f, 2.0f), "\u00D7");
+#else
     window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
     window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
+#endif
 
     return pressed;
 }
@@ -792,7 +817,11 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
 
+#ifdef WIN98 // collapse button size
+    ImRect bb(pos, pos + ImVec2(16.0f, 14.0f));
+#else
     ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
+#endif
     ItemAdd(bb, id);
     bool hovered, held;
     bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
@@ -801,9 +830,19 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
     ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
     ImU32 text_col = GetColorU32(ImGuiCol_Text);
     ImVec2 center = bb.GetCenter();
+
+#ifdef WIN98 // collapse button
+    const ImU32 fill_col = GetColorU32(ImGuiCol_WindowBg);
+    window->DrawList->AddRectFilled(bb.Min, bb.Max, fill_col, 0.0f);
+    WinAddRect(bb.Min, bb.Max, hovered && held);
+
+    // collapse icon
+    RenderText(bb.Min + ImVec2(2.0f, 2.0f), "\u00D6");
+#else
     if (hovered || held)
         window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12);
     RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
+#endif
 
     // Switch to moving the window after mouse is moved beyond the initial drag threshold
     if (IsItemActive() && IsMouseDragging(0))
@@ -888,8 +927,19 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
     const ImGuiStyle& style = g.Style;
     const bool allow_interaction = (alpha >= 1.0f);
 
+#ifdef WIN98
+
+    ImRect bb = bb_frame;
+    float button_size = (axis == ImGuiAxis_X) ? bb.GetHeight() : bb.GetWidth();
+    ImVec2 button_size_rect(button_size, button_size);
+    ImVec2 main_axis((axis == ImGuiAxis_X) ? 1.0f : 0.0f, (axis == ImGuiAxis_X) ? 0.0f : 1.0f);
+    ImVec2 main_axis_button_size = main_axis * button_size;
+
+    bb.Expand(main_axis * -button_size);
+#else
     ImRect bb = bb_frame;
     bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
+#endif
 
     // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
     const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight();
@@ -944,6 +994,33 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
     }
 
     // Render
+#ifdef WIN98 // scrollbar
+
+    ImRect grab_rect;
+    if (axis == ImGuiAxis_X) {
+        grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
+    } else {
+        grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
+    }
+    WinAddRect(grab_rect.Min, grab_rect.Max, false);
+    {
+        const ImGuiID up_id = window->GetID("##scrollup");
+        ImRect button_bounds(bb_frame.Min, bb_frame.Min + button_size_rect);
+        bool held_up = false;
+        bool hovered_up = false;
+        bool pressed_up = ButtonBehavior(button_bounds, up_id, &hovered_up, &held_up, 0);
+        WinAddRect(button_bounds.Min, button_bounds.Max, (held_up && hovered_up));
+    }
+    {
+        const ImGuiID down_id = window->GetID("##scrolldown");
+        ImVec2 pos = bb_frame.Min + main_axis * (((axis == ImGuiAxis_X) ? bb_frame.GetWidth() : bb_frame.GetHeight()) - button_size);
+        ImRect button_bounds(pos, pos + button_size_rect);
+        bool held_down = false;
+        bool hovered_down = false;
+        bool pressed_down = ButtonBehavior(button_bounds, down_id, &hovered_down, &held_down, 0);
+        WinAddRect(button_bounds.Min, button_bounds.Max, (held_down && hovered_down));
+    }
+#else
     const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg);
     const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
     window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, rounding_corners);
@@ -953,6 +1030,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
     else
         grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
     window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
+#endif
 
     return held;
 }