代码拉取完成,页面将自动刷新
#pragma once
#include "ControlBase.h"
class ComboBox : public Control
{
#define COMBO_MIN_SCROLL_BLOCK 16
private:
int _underMouseIndex = -1;
public:
virtual UIClass Type() { return UIClass::UI_ComboBox; }
bool IsContainer() override
{
return false;
}
D2D1_COLOR_F UnderMouseBackColor = Colors::SkyBlue;
D2D1_COLOR_F UnderMouseForeColor = Colors::White;
D2D1_COLOR_F ScrollBackColor = Colors::LightGray;
D2D1_COLOR_F ScrollForeColor = Colors::DimGrey;
D2D1_COLOR_F ButtonBackColor = Colors::SkyBlue;
UINT32 ExpandCount = 4;
UINT32 ExpandScroll = 0;
bool Expand = false;
int SelectedIndex = 0;
List<std::wstring> values;
float Boder = 1.5f;
ComboBox(std::wstring text, int x, int y, int width = 120, int height = 24)
{
this->Text = text;
this->Location = POINT{x, y};
this->Size = SIZE{width, height};
this->BackColor = D2D1_COLOR_F{0.75f, 0.75f, 0.75f, 0.75f};
}
SIZE ActualSize() override
{
auto size = this->Size;
if (this->Expand)
{
size.cy += this->Height * this->ExpandCount;
}
return size;
}
void DrawScroll()
{
auto d2d = this->Render;
auto abslocation = this->AbsLocation;
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
auto size = this->ActualSize();
if (this->values.Count > 0)
{
float _render_width = this->Width - 8;
float _render_height = this->Height * this->ExpandCount;
float font_height = d2d->GetTextSize(L"I", font).height;
float row_height = font_height + 2.0f;
int render_count = this->ExpandCount;
if (render_count < this->values.Count)
{
int max_scroll = this->values.Count - render_count;
float scroll_block_height = ((float)render_count / (float)this->values.Count) * (float)_render_height;
if (scroll_block_height < COMBO_MIN_SCROLL_BLOCK)
scroll_block_height = COMBO_MIN_SCROLL_BLOCK;
float scroll_block_move_space = _render_height - scroll_block_height;
float yt = scroll_block_height * 0.5f;
float yb = _render_height - (scroll_block_height * 0.5f);
float per = (float)this->ExpandScroll / (float)max_scroll;
float scroll_tmp_y = per * scroll_block_move_space;
float scroll_block_top = scroll_tmp_y;
d2d->FillRoundRect(abslocation.x + (this->Width - 8.0f), abslocation.y + this->Height, 8.0f, _render_height, this->ScrollBackColor, 4.0f);
d2d->FillRoundRect(abslocation.x + (this->Width - 8.0f), abslocation.y + scroll_block_top + this->Height, 8.0f, scroll_block_height, this->ScrollForeColor, 4.0f);
}
}
}
void Update() override
{
if (this->IsVisual == false)
return;
bool isUnderMouse = this->MostParent->UnderMouse == this;
bool isSelected = this->MostParent->Selected == this;
auto d2d = this->Render;
auto abslocation = this->AbsLocation;
auto size = this->ActualSize();
auto absRect = this->AbsRect;
d2d->PushDrawRect(absRect.left, absRect.top, absRect.right - absRect.left, absRect.bottom - absRect.top);
{
Control *tmpc = this;
List<Control *> need_render_background;
while (tmpc->BackColor.a < 1.0f)
{
tmpc = tmpc->Parent;
need_render_background.Add(tmpc);
}
if (this->BackColor.a < 1.0f)
{
for (int i = need_render_background.Count - 1; i >= 0; i--)
{
d2d->FillRect(abslocation.x, abslocation.y, size.cx, size.cy, need_render_background[i]->BackColor);
if (need_render_background[i]->Image)
{
need_render_background[i]->RenderImage();
}
}
}
d2d->FillRect(abslocation.x, abslocation.y, size.cx, size.cy, this->BackColor);
if (this->Image)
{
this->RenderImage();
}
auto font = this->Font ? this->Font : d2d->DefaultFontObject;
auto textSize = font->GetTextSize(this->Text);
float drawLeft = 0.0f;
float drawTop = 0.0f;
if (this->Height > textSize.height)
{
drawLeft = drawTop = (this->Height - textSize.height) / 2.0f;
}
d2d->DrawString(this->Text, abslocation.x + drawLeft, abslocation.y + drawTop, this->ForeColor, this->Font);
float exbL = abslocation.x + (size.cx - this->Height);
d2d->FillRect(exbL, abslocation.y, this->Height, this->Height, this->ButtonBackColor);
if (this->Expand)
{
float exbT = abslocation.y;
float recSize = this->Height;
float tmpb = recSize * 0.3f;
float tmpc = recSize * 0.7f;
d2d->FillPolygon(
{{exbL + tmpb, exbT + tmpb},
{exbL + tmpc, exbT + tmpb},
{exbL + (recSize * 0.5f), exbT + tmpc},
{exbL + tmpb, exbT + tmpb}},
this->ForeColor);
}
else
{
float exbT = abslocation.y;
float recSize = this->Height;
float tmpb = recSize * 0.3f;
float tmpc = recSize * 0.7f;
d2d->FillPolygon(
{{exbL + tmpb, exbT + tmpb},
{exbL + tmpc, exbT + (recSize * 0.5f)},
{exbL + tmpb, exbT + tmpc},
{exbL + tmpb, exbT + tmpb}},
this->ForeColor);
}
if (this->Expand)
{
for (int i = this->ExpandScroll; i < this->ExpandScroll + this->ExpandCount && i < this->values.Count; i++)
{
if (i == _underMouseIndex)
{
int viewIndex = i - this->ExpandScroll;
d2d->FillRect(abslocation.x,
abslocation.y + ((viewIndex + 1) * this->Height),
this->Width, this->Height, this->UnderMouseBackColor);
d2d->DrawString(
this->values[i],
abslocation.x + drawLeft,
abslocation.y + drawTop + (((i - this->ExpandScroll) + 1) * this->Height),
UnderMouseForeColor, this->Font);
}
else
{
d2d->DrawString(
this->values[i],
abslocation.x + drawLeft,
abslocation.y + drawTop + (((i - this->ExpandScroll) + 1) * this->Height),
this->ForeColor, this->Font);
}
}
this->DrawScroll();
d2d->DrawRect(abslocation.x, abslocation.y, size.cx, this->Height, this->BolderColor, this->Boder);
}
d2d->DrawRect(abslocation.x, abslocation.y, size.cx, size.cy, this->BolderColor, this->Boder);
}
d2d->PopDrawRect();
}
bool ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam, int xof, int yof) override
{
if (WM_LBUTTONDOWN == message)
{
if (this->MostParent->Selected && this->MostParent->Selected != this)
{
auto se = this->MostParent->Selected;
this->MostParent->Selected = this;
se->SingleUpdate();
}
}
switch (message)
{
case WM_DROPFILES:
{
HDROP hDropInfo = HDROP(wParam);
UINT uFileNum = DragQueryFile(hDropInfo, 0xffffffff, NULL, 0);
TCHAR strFileName[MAX_PATH];
List<std::wstring> files;
for (UINT i = 0; i < uFileNum; i++)
{
DragQueryFile(hDropInfo, i, strFileName, MAX_PATH);
files.Add(strFileName);
}
DragFinish(hDropInfo);
if (files.Count > 0)
{
this->OnDropFile(this, files);
}
}
break;
case WM_MOUSEWHEEL: // mouse wheel
{
if (this->Expand)
{
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
{
if (this->ExpandScroll > 0)
{
this->ExpandScroll -= 1;
this->SingleUpdate();
}
}
else
{
if (this->ExpandScroll < this->values.Count - this->ExpandCount)
{
this->ExpandScroll += 1;
this->SingleUpdate();
}
}
}
else
{
if (GET_WHEEL_DELTA_WPARAM(wParam) > 0)
{
if (this->SelectedIndex > 0)
{
this->SelectedIndex -= 1;
this->Text = this->values[this->SelectedIndex];
this->SingleUpdate();
}
}
else
{
if (this->SelectedIndex < this->values.Count - 1)
{
this->SelectedIndex += 1;
this->Text = this->values[this->SelectedIndex];
this->SingleUpdate();
}
}
}
MouseEventArgs event_obj = MouseEventArgs(MouseButtons::MouseButtons_None, 0, xof, yof, GET_WHEEL_DELTA_WPARAM(wParam));
this->OnMouseWheel(this, event_obj);
}
break;
case WM_MOUSEMOVE: // mouse move
{
this->MostParent->UnderMouse = this;
if (this->Expand)
{
bool need_update = false;
if (xof >= 0 && yof >= this->Height)
{
int _yof = int((yof - this->Height) / this->Height);
if (_yof <= this->ExpandCount)
{
int idx = _yof + this->ExpandScroll;
if (idx < this->values.Count)
{
if (idx != this->_underMouseIndex)
{
need_update = true;
}
this->_underMouseIndex = idx;
}
}
}
if (need_update)
this->SingleUpdate();
}
MouseEventArgs event_obj = MouseEventArgs(MouseButtons::MouseButtons_None, 0, xof, yof, HIWORD(wParam));
this->OnMouseMove(this, event_obj);
}
break;
case WM_LBUTTONDOWN: // mouse down
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
{
if (WM_LBUTTONDOWN == message)
{
this->MostParent->Selected = this;
}
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseDown(this, event_obj);
}
break;
case WM_LBUTTONUP: // mouse up
case WM_RBUTTONUP:
case WM_MBUTTONUP:
{
if (WM_LBUTTONUP == message && this->MostParent->Selected == this)
{
if (xof >= 0 && yof >= 0)
{
if (yof > 0 && yof < this->Width)
{
if (xof > (this->Width - this->Height))
{
this->Expand = !this->Expand;
this->MostParent->Update();
this->SingleUpdate();
if (this->Expand)
{
this->MostParent->ForeGroundControls.Add(this);
}
else
{
this->MostParent->ForeGroundControls.Remove(this);
}
this->MostParent->Selected = NULL;
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseUp(this, event_obj);
this->SingleUpdate();
break;
}
if (this->Expand)
{
int _yof = int((yof - this->Height) / this->Height);
if (_yof <= this->ExpandCount)
{
int idx = _yof + this->ExpandScroll;
if (idx < this->values.Count)
{
this->_underMouseIndex = idx;
this->SelectedIndex = this->_underMouseIndex;
this->Text = this->values[this->SelectedIndex];
this->Expand = false;
this->MostParent->Update();
this->SingleUpdate();
}
}
}
}
}
}
this->MostParent->Selected = NULL;
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseUp(this, event_obj);
this->SingleUpdate();
}
break;
case WM_LBUTTONDBLCLK: // mouse double click
{
MouseEventArgs event_obj = MouseEventArgs(FromParamToMouseButtons(message), 0, xof, yof, HIWORD(wParam));
this->OnMouseDoubleClick(this, event_obj);
}
break;
case WM_KEYDOWN: // keyboard down
{
KeyEventArgs event_obj = KeyEventArgs((Keys)(wParam | 0));
this->OnKeyDown(this, event_obj);
}
break;
case WM_KEYUP: // keyboard up
{
KeyEventArgs event_obj = KeyEventArgs((Keys)(wParam | 0));
this->OnKeyUp(this, event_obj);
}
break;
}
return true;
}
};
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。