Files
EzUI/sources/ComboBox.cpp
2026-01-29 09:45:03 +08:00

225 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ComboBox.h"
namespace ezui {
Control* ComboBox::Add(Control* childCtl)
{
return __super::Add(childCtl);
}
void ComboBox::Remove(Control* childCtl, bool freeCtrl)
{
__super::Remove(childCtl, freeCtrl);
}
void ComboBox::Init()
{
this->m_textBox.SetReadOnly(true);
this->Add(&m_textBox);
this->Add(&m_UpDown);
m_UpDown.EventHandler = [&](Control* sd, EventArgs& arg)->void {
if (arg.EventType == Event::OnPaint) {
//绘制
auto& args = (PaintEventArgs&)arg;
auto fSzie = sd->GetFontSize() * 0.5f;
int width = fSzie * 1.5f;
Rect rect(0, 0, width, fSzie);
rect.Y = (sd->Height() - fSzie) / 2.0f;
rect.X += (sd->Height() - width) / 2.0f;
//args.Graphics.SetColor(Color::Red);
//args.Graphics.DrawRectangle(rect);
PointF p1(rect.GetLeft(), rect.Y);
PointF p2(rect.GetRight(), rect.Y);
PointF p3(rect.GetLeft() + width / 2.0f, rect.GetBottom());
args.Graphics.SetColor(this->GetForeColor());
args.Graphics.DrawLine(p1, p3);
args.Graphics.DrawLine(p2, p3);
}
else if (arg.EventType == Event::OnMouseDown/*&& args.Button == MouseButton::Left*/) {
//单击
if (m_menuWnd == NULL) {
m_menuWnd = new MenuContent(this, &m_UpDown);
m_menuWnd->SetShadow(10);
m_list.Style.BackColor = Color::White;
m_menuWnd->SetLayout(&m_list);
}
for (auto& it : m_list.GetControls()) {
it->SetFixedHeight(Height());
}
int height = this->Height() * m_list.GetControls().size();
if (height == 0) {
height = Height();
}
if (!m_menuWnd->IsVisible()) {
m_menuWnd->SetSize({ Width(), height });
m_menuWnd->Show();
}
else {
m_menuWnd->Hide();
}
}
};
}
ComboBox::ComboBox(Object* parentObject) :HLayout(parentObject)
{
Init();
}
UIString ComboBox::GetText()
{
return this->m_textBox.GetText();
}
int ComboBox::GetCheck()
{
return this->m_index;
}
bool ComboBox::SetCheck(int pos)
{
auto item = m_list.GetControl(pos);
if (item) {
m_textBox.SetText(((Label*)item)->GetText());
m_index = pos;
return true;
}
return false;
}
ComboBox::~ComboBox()
{
m_list.Clear(true);
if (m_menuWnd) {
delete m_menuWnd;
}
}
int ComboBox::AddItem(const UIString& text)
{
Label* lb = new Label;
lb->SetDockStyle(DockStyle::Horizontal);
lb->SetText(text);
m_list.Add(lb);
lb->HoverStyle.BackColor = Color::Gray;
lb->HoverStyle.ForeColor = Color::White;
lb->EventHandler = [&](Control* sd, const EventArgs& args) ->void {
if (args.EventType == Event::OnMouseDown) {
m_index = sd->Parent->IndexOf(sd);
m_textBox.SetText(((Label*)sd)->GetText());
m_textBox.Invalidate();
m_menuWnd->Hide();
}
};
int newIndex = m_list.GetControls().size() - 1;
// 检查是否有待设置的索引
if (m_pendingIndex >= 0 && m_pendingIndex == newIndex) {
SetCheck(m_pendingIndex);
m_pendingIndex = -1; // 清除待设置标志
}
return newIndex;
}
void ComboBox::RemoveItem(int index)
{
Control* lb = m_list.GetControl(index);
m_list.Remove(lb, true);
}
void ComboBox::SetAttribute(const UIString& key, const UIString& value)
{
do
{
if (key == "item") {
// 添加下拉选项,支持多个选项用逗号分隔
if (value.find(',') != UIString::npos) {
// 解析多个选项
size_t start = 0;
size_t end = value.find(',');
while (end != UIString::npos) {
UIString item = value.substr(start, end - start);
// 去除首尾空格
while (!item.empty() && (item[0] == ' ' || item[0] == '\t')) {
item = item.substr(1);
}
while (!item.empty() && (item[item.length() - 1] == ' ' || item[item.length() - 1] == '\t')) {
item = item.substr(0, item.length() - 1);
}
if (!item.empty()) {
AddItem(item);
}
start = end + 1;
end = value.find(',', start);
}
// 处理最后一个选项
UIString item = value.substr(start);
while (!item.empty() && (item[0] == ' ' || item[0] == '\t')) {
item = item.substr(1);
}
while (!item.empty() && (item[item.length() - 1] == ' ' || item[item.length() - 1] == '\t')) {
item = item.substr(0, item.length() - 1);
}
if (!item.empty()) {
AddItem(item);
}
}
else {
// 单个选项
AddItem(value);
}
break;
}
if (key == "checked" || key == "selected" || key == "index") {
// 设置选中的下标
int index = std::atoi(value.c_str());
if (!SetCheck(index)) {
// 如果设置失败可能是因为还没有添加item保存索引稍后设置
m_pendingIndex = index;
}
break;
}
if (key == "readonly") {
// 设置文本框只读状态
if (value == "true") {
m_textBox.SetReadOnly(true);
break;
}
if (value == "false") {
m_textBox.SetReadOnly(false);
break;
}
}
} while (false);
__super::SetAttribute(key, value);
}
void ComboBox::OnLayout() {
this->m_UpDown.SetFixedSize(Size(Height(), Height()));
__super::OnLayout();
}
ComboBox::MenuContent::MenuContent(Control* ownerCtl, Control* hittestCtl) :PopupWindow(0, 0, ownerCtl), m_hittestCtl(hittestCtl)
{
}
void ComboBox::MenuContent::OnKillFocus(HWND wnd)
{
if (::GetWindow(Hwnd(), GW_OWNER) == wnd) {
POINT pt;
::GetCursorPos(&pt);
// 将鼠标屏幕坐标转换为客户端坐标
::ScreenToClient(::GetWindow(Hwnd(), GW_OWNER), &pt);
Rect _hittestRect = m_hittestCtl->GetClientRect();
if (_hittestRect.Contains(pt.x, pt.y)) {
return;
}
else {
this->Hide();
}
}
else {
this->Hide();
}
}
ComboBox::MenuContent::~MenuContent()
{
}
}