mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-24 07:40:22 +01:00
Refactor: moved low-layout helpers to imgui_widgets.cpp (Spacing, Dummy, NewLine, Separator, etc.) (#2036)
This commit is contained in:
parent
cbdce80837
commit
bb3184af74
169
imgui.cpp
169
imgui.cpp
@ -6030,17 +6030,6 @@ ImGuiStorage* ImGui::GetStateStorage()
|
|||||||
return window->DC.StateStorage;
|
return window->DC.StateStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::AlignTextToFramePadding()
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
window->DC.CurrentLineSize.y = ImMax(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
|
|
||||||
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::PushID(const char* str_id)
|
void ImGui::PushID(const char* str_id)
|
||||||
{
|
{
|
||||||
ImGuiWindow* window = GetCurrentWindowRead();
|
ImGuiWindow* window = GetCurrentWindowRead();
|
||||||
@ -6087,148 +6076,6 @@ ImGuiID ImGui::GetID(const void* ptr_id)
|
|||||||
return GImGui->CurrentWindow->GetID(ptr_id);
|
return GImGui->CurrentWindow->GetID(ptr_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Horizontal/vertical separating line
|
|
||||||
void ImGui::Separator()
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
|
|
||||||
// Those flags should eventually be overridable by the user
|
|
||||||
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
|
||||||
IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
|
|
||||||
if (flags & ImGuiSeparatorFlags_Vertical)
|
|
||||||
{
|
|
||||||
VerticalSeparator();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Horizontal Separator
|
|
||||||
if (window->DC.ColumnsSet)
|
|
||||||
PopClipRect();
|
|
||||||
|
|
||||||
float x1 = window->Pos.x;
|
|
||||||
float x2 = window->Pos.x + window->Size.x;
|
|
||||||
if (!window->DC.GroupStack.empty())
|
|
||||||
x1 += window->DC.Indent.x;
|
|
||||||
|
|
||||||
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
|
|
||||||
ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
|
|
||||||
if (!ItemAdd(bb, 0))
|
|
||||||
{
|
|
||||||
if (window->DC.ColumnsSet)
|
|
||||||
PushColumnClipRect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator));
|
|
||||||
|
|
||||||
if (g.LogEnabled)
|
|
||||||
LogRenderedText(NULL, IM_NEWLINE "--------------------------------");
|
|
||||||
|
|
||||||
if (window->DC.ColumnsSet)
|
|
||||||
{
|
|
||||||
PushColumnClipRect();
|
|
||||||
window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::VerticalSeparator()
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
|
|
||||||
float y1 = window->DC.CursorPos.y;
|
|
||||||
float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
|
|
||||||
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2));
|
|
||||||
ItemSize(ImVec2(bb.GetWidth(), 0.0f));
|
|
||||||
if (!ItemAdd(bb, 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
|
|
||||||
if (g.LogEnabled)
|
|
||||||
LogText(" |");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
|
|
||||||
bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
|
|
||||||
{
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
|
||||||
|
|
||||||
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
|
|
||||||
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
|
|
||||||
bool item_add = ItemAdd(bb, id);
|
|
||||||
window->DC.ItemFlags = item_flags_backup;
|
|
||||||
if (!item_add)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool hovered, held;
|
|
||||||
ImRect bb_interact = bb;
|
|
||||||
bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
|
|
||||||
ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
|
|
||||||
if (g.ActiveId != id)
|
|
||||||
SetItemAllowOverlap();
|
|
||||||
|
|
||||||
if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
|
|
||||||
SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW);
|
|
||||||
|
|
||||||
ImRect bb_render = bb;
|
|
||||||
if (held)
|
|
||||||
{
|
|
||||||
ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
|
|
||||||
float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
|
|
||||||
|
|
||||||
// Minimum pane size
|
|
||||||
float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
|
|
||||||
float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
|
|
||||||
if (mouse_delta < -size_1_maximum_delta)
|
|
||||||
mouse_delta = -size_1_maximum_delta;
|
|
||||||
if (mouse_delta > size_2_maximum_delta)
|
|
||||||
mouse_delta = size_2_maximum_delta;
|
|
||||||
|
|
||||||
// Apply resize
|
|
||||||
if (mouse_delta != 0.0f)
|
|
||||||
{
|
|
||||||
if (mouse_delta < 0.0f)
|
|
||||||
IM_ASSERT(*size1 + mouse_delta >= min_size1);
|
|
||||||
if (mouse_delta > 0.0f)
|
|
||||||
IM_ASSERT(*size2 - mouse_delta >= min_size2);
|
|
||||||
*size1 += mouse_delta;
|
|
||||||
*size2 -= mouse_delta;
|
|
||||||
bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
|
|
||||||
MarkItemEdited(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render
|
|
||||||
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
|
|
||||||
window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding);
|
|
||||||
|
|
||||||
return held;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::Spacing()
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
ItemSize(ImVec2(0,0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::Dummy(const ImVec2& size)
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
|
|
||||||
ItemSize(bb);
|
|
||||||
ItemAdd(bb, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImGui::IsRectVisible(const ImVec2& size)
|
bool ImGui::IsRectVisible(const ImVec2& size)
|
||||||
{
|
{
|
||||||
@ -6336,22 +6183,6 @@ void ImGui::SameLine(float pos_x, float spacing_w)
|
|||||||
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
|
window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::NewLine()
|
|
||||||
{
|
|
||||||
ImGuiWindow* window = GetCurrentWindow();
|
|
||||||
if (window->SkipItems)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImGuiContext& g = *GImGui;
|
|
||||||
const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
|
|
||||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
|
||||||
if (window->DC.CurrentLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
|
|
||||||
ItemSize(ImVec2(0,0));
|
|
||||||
else
|
|
||||||
ItemSize(ImVec2(0.0f, g.FontSize));
|
|
||||||
window->DC.LayoutType = backup_layout_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImGui::Indent(float indent_w)
|
void ImGui::Indent(float indent_w)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
Index of this file:
|
Index of this file:
|
||||||
- Widgets: Text, etc.
|
- Widgets: Text, etc.
|
||||||
- Widgets: Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.
|
- Widgets: Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.
|
||||||
|
- Widgets: Low-level Layout helpers: Spacing, Dummy, NewLine, Separator, etc.
|
||||||
- Widgets: ComboBox
|
- Widgets: ComboBox
|
||||||
- Data Type and Data Formatting Helpers
|
- Data Type and Data Formatting Helpers
|
||||||
- Widgets: DragScalar, DragFloat, DragInt, etc.
|
- Widgets: DragScalar, DragFloat, DragInt, etc.
|
||||||
@ -1051,6 +1052,188 @@ void ImGui::Bullet()
|
|||||||
SameLine(0, style.FramePadding.x*2);
|
SameLine(0, style.FramePadding.x*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// WIDGETS: Low-level Layout helpers
|
||||||
|
// - Spacing()
|
||||||
|
// - Dummy()
|
||||||
|
// - NewLine()
|
||||||
|
// - AlignTextToFramePadding()
|
||||||
|
// - Separator()
|
||||||
|
// - VerticalSeparator() [Internal]
|
||||||
|
// - SplitterBehavior() [Internal]
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ImGui::Spacing()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
ItemSize(ImVec2(0,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::Dummy(const ImVec2& size)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
|
||||||
|
ItemSize(bb);
|
||||||
|
ItemAdd(bb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::NewLine()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
|
||||||
|
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||||
|
if (window->DC.CurrentLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
|
||||||
|
ItemSize(ImVec2(0,0));
|
||||||
|
else
|
||||||
|
ItemSize(ImVec2(0.0f, g.FontSize));
|
||||||
|
window->DC.LayoutType = backup_layout_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::AlignTextToFramePadding()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
window->DC.CurrentLineSize.y = ImMax(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
|
||||||
|
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontal/vertical separating line
|
||||||
|
void ImGui::Separator()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
// Those flags should eventually be overridable by the user
|
||||||
|
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
||||||
|
IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
|
||||||
|
if (flags & ImGuiSeparatorFlags_Vertical)
|
||||||
|
{
|
||||||
|
VerticalSeparator();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontal Separator
|
||||||
|
if (window->DC.ColumnsSet)
|
||||||
|
PopClipRect();
|
||||||
|
|
||||||
|
float x1 = window->Pos.x;
|
||||||
|
float x2 = window->Pos.x + window->Size.x;
|
||||||
|
if (!window->DC.GroupStack.empty())
|
||||||
|
x1 += window->DC.Indent.x;
|
||||||
|
|
||||||
|
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
|
||||||
|
ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
|
||||||
|
if (!ItemAdd(bb, 0))
|
||||||
|
{
|
||||||
|
if (window->DC.ColumnsSet)
|
||||||
|
PushColumnClipRect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator));
|
||||||
|
|
||||||
|
if (g.LogEnabled)
|
||||||
|
LogRenderedText(NULL, IM_NEWLINE "--------------------------------");
|
||||||
|
|
||||||
|
if (window->DC.ColumnsSet)
|
||||||
|
{
|
||||||
|
PushColumnClipRect();
|
||||||
|
window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui::VerticalSeparator()
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
if (window->SkipItems)
|
||||||
|
return;
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
|
||||||
|
float y1 = window->DC.CursorPos.y;
|
||||||
|
float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
|
||||||
|
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2));
|
||||||
|
ItemSize(ImVec2(bb.GetWidth(), 0.0f));
|
||||||
|
if (!ItemAdd(bb, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
|
||||||
|
if (g.LogEnabled)
|
||||||
|
LogText(" |");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
|
||||||
|
bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
|
||||||
|
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
|
||||||
|
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
|
||||||
|
bool item_add = ItemAdd(bb, id);
|
||||||
|
window->DC.ItemFlags = item_flags_backup;
|
||||||
|
if (!item_add)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool hovered, held;
|
||||||
|
ImRect bb_interact = bb;
|
||||||
|
bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
|
||||||
|
ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
|
||||||
|
if (g.ActiveId != id)
|
||||||
|
SetItemAllowOverlap();
|
||||||
|
|
||||||
|
if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
|
||||||
|
SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW);
|
||||||
|
|
||||||
|
ImRect bb_render = bb;
|
||||||
|
if (held)
|
||||||
|
{
|
||||||
|
ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
|
||||||
|
float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
|
||||||
|
|
||||||
|
// Minimum pane size
|
||||||
|
float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
|
||||||
|
float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
|
||||||
|
if (mouse_delta < -size_1_maximum_delta)
|
||||||
|
mouse_delta = -size_1_maximum_delta;
|
||||||
|
if (mouse_delta > size_2_maximum_delta)
|
||||||
|
mouse_delta = size_2_maximum_delta;
|
||||||
|
|
||||||
|
// Apply resize
|
||||||
|
if (mouse_delta != 0.0f)
|
||||||
|
{
|
||||||
|
if (mouse_delta < 0.0f)
|
||||||
|
IM_ASSERT(*size1 + mouse_delta >= min_size1);
|
||||||
|
if (mouse_delta > 0.0f)
|
||||||
|
IM_ASSERT(*size2 - mouse_delta >= min_size2);
|
||||||
|
*size1 += mouse_delta;
|
||||||
|
*size2 -= mouse_delta;
|
||||||
|
bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
|
||||||
|
MarkItemEdited(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render
|
||||||
|
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
|
||||||
|
window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding);
|
||||||
|
|
||||||
|
return held;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// WIDGETS: Combo Box
|
// WIDGETS: Combo Box
|
||||||
// - BeginCombo()
|
// - BeginCombo()
|
||||||
|
Loading…
Reference in New Issue
Block a user