2026-01-24 22:42:46 +08:00
|
|
|
|
#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();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-29 09:45:03 +08:00
|
|
|
|
int newIndex = m_list.GetControls().size() - 1;
|
|
|
|
|
|
// 检查是否有待设置的索引
|
|
|
|
|
|
if (m_pendingIndex >= 0 && m_pendingIndex == newIndex) {
|
|
|
|
|
|
SetCheck(m_pendingIndex);
|
|
|
|
|
|
m_pendingIndex = -1; // 清除待设置标志
|
|
|
|
|
|
}
|
|
|
|
|
|
return newIndex;
|
2026-01-24 22:42:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
void ComboBox::RemoveItem(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
Control* lb = m_list.GetControl(index);
|
|
|
|
|
|
m_list.Remove(lb, true);
|
|
|
|
|
|
}
|
2026-01-29 09:45:03 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
2026-01-24 22:42:46 +08:00
|
|
|
|
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()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|