mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
497 lines
10 KiB
C++
497 lines
10 KiB
C++
#include "stdafx.h"
|
|
#include "ComboBox.h"
|
|
|
|
namespace Forms
|
|
{
|
|
ComboBox::ComboBox()
|
|
: Control(), Items(this), _DrawMode(DrawMode::Normal), _FlatStyle(FlatStyle::Standard), _DropDownStyle(ComboBoxStyle::DropDown), _IntegralHeight(true), _DropDownWidth(-1), _DropDownHeight(-1), _MaxDropDownItems(8), _MaximumLength(SHRT_MAX), _SelectedIndex(-1), _ChildEdit(nullptr), _ChildListBox(nullptr)
|
|
{
|
|
SetStyle(ControlStyles::UserPaint |
|
|
ControlStyles::UseTextForAccessibility |
|
|
ControlStyles::StandardClick, false);
|
|
|
|
// Default back color is different...
|
|
this->_BackColor = Drawing::GetSystemColor(Drawing::SystemColors::Window);
|
|
// We are a ComboBox control.
|
|
this->_RTTI = ControlTypes::ComboBox;
|
|
}
|
|
|
|
DrawMode ComboBox::GetDrawMode()
|
|
{
|
|
return this->_DrawMode;
|
|
}
|
|
|
|
void ComboBox::SetDrawMode(DrawMode Value)
|
|
{
|
|
if (_DrawMode != Value)
|
|
{
|
|
_DrawMode = Value;
|
|
UpdateStyles();
|
|
}
|
|
}
|
|
|
|
uint32_t ComboBox::DropDownWidth()
|
|
{
|
|
if (_DropDownWidth > -1)
|
|
return _DropDownWidth;
|
|
|
|
return _Width;
|
|
}
|
|
|
|
void ComboBox::SetDropDownWidth(uint32_t Value)
|
|
{
|
|
_DropDownWidth = (int32_t)Value;
|
|
|
|
if (GetState(ControlStates::StateCreated))
|
|
SendMessageA(this->_Handle, CB_SETDROPPEDWIDTH, (WPARAM)Value, NULL);
|
|
}
|
|
|
|
uint32_t ComboBox::DropDownHeight()
|
|
{
|
|
if (_DropDownHeight > -1)
|
|
return _DropDownHeight;
|
|
|
|
return 106; // Default drop down height...
|
|
}
|
|
|
|
void ComboBox::SetDropDownHeight(uint32_t Value)
|
|
{
|
|
_DropDownHeight = (int32_t)Value;
|
|
SetIntegralHeight(false);
|
|
}
|
|
|
|
bool ComboBox::DroppedDown()
|
|
{
|
|
if (GetState(ControlStates::StateCreated))
|
|
return (SendMessageA(this->_Handle, CB_GETDROPPEDSTATE, NULL, NULL) != 0);
|
|
|
|
return false;
|
|
}
|
|
|
|
void ComboBox::SetDroppedDown(bool Value)
|
|
{
|
|
if (GetState(ControlStates::StateCreated))
|
|
SendMessageA(this->_Handle, CB_SHOWDROPDOWN, Value ? -1 : 0, NULL);
|
|
}
|
|
|
|
FlatStyle ComboBox::GetFlatStyle()
|
|
{
|
|
return this->_FlatStyle;
|
|
}
|
|
|
|
void ComboBox::SetFlatStyle(FlatStyle Value)
|
|
{
|
|
if (_FlatStyle != Value)
|
|
{
|
|
_FlatStyle = Value;
|
|
UpdateStyles();
|
|
}
|
|
}
|
|
|
|
bool ComboBox::IntegralHeight()
|
|
{
|
|
return this->_IntegralHeight;
|
|
}
|
|
|
|
void ComboBox::SetIntegralHeight(bool Value)
|
|
{
|
|
if (_IntegralHeight != Value)
|
|
{
|
|
_IntegralHeight = Value;
|
|
UpdateStyles();
|
|
}
|
|
}
|
|
|
|
int32_t ComboBox::ItemHeight()
|
|
{
|
|
return (int32_t)SendMessageA(this->_Handle, CB_GETITEMHEIGHT, NULL, NULL);
|
|
}
|
|
|
|
void ComboBox::SetItemHeight(int32_t Value)
|
|
{
|
|
if (_DrawMode == DrawMode::OwnerDrawFixed)
|
|
{
|
|
SendMessageA(this->_Handle, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)Value);
|
|
SendMessageA(this->_Handle, CB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)Value);
|
|
}
|
|
else if (_DrawMode == DrawMode::OwnerDrawVariable)
|
|
{
|
|
SendMessageA(this->_Handle, CB_SETITEMHEIGHT, (WPARAM)-1, (LPARAM)Value);
|
|
|
|
for (uint32_t i = 0; i < Items.Count(); i++)
|
|
SendMessageA(this->_Handle, CB_SETITEMHEIGHT, (WPARAM)i, (LPARAM)Value);
|
|
}
|
|
}
|
|
|
|
uint8_t ComboBox::MaxDropDownItems()
|
|
{
|
|
return this->_MaxDropDownItems;
|
|
}
|
|
|
|
void ComboBox::SetMaxDropDownItems(uint8_t Value)
|
|
{
|
|
this->_MaxDropDownItems = Value;
|
|
}
|
|
|
|
uint32_t ComboBox::MaxLength()
|
|
{
|
|
return this->_MaximumLength;
|
|
}
|
|
|
|
void ComboBox::SetMaxLength(uint32_t Value)
|
|
{
|
|
if (_MaximumLength != Value)
|
|
{
|
|
_MaximumLength = Value;
|
|
|
|
if (GetState(ControlStates::StateCreated))
|
|
SendMessageA(this->_Handle, CB_LIMITTEXT, (WPARAM)Value, NULL);
|
|
}
|
|
}
|
|
|
|
int32_t ComboBox::SelectedIndex()
|
|
{
|
|
if (GetState(ControlStates::StateCreated))
|
|
return (int32_t)SendMessageA(this->_Handle, CB_GETCURSEL, NULL, NULL);
|
|
|
|
return this->_SelectedIndex;
|
|
}
|
|
|
|
void ComboBox::SetSelectedIndex(int32_t Value)
|
|
{
|
|
if (GetState(ControlStates::StateCreated))
|
|
SendMessageA(this->_Handle, CB_SETCURSEL, (WPARAM)Value, NULL);
|
|
else
|
|
_SelectedIndex = Value;
|
|
|
|
OnTextChanged();
|
|
|
|
OnSelectedIndexChanged();
|
|
OnSelectedItemChanged();
|
|
}
|
|
|
|
string ComboBox::SelectedText()
|
|
{
|
|
if (_DropDownStyle == ComboBoxStyle::DropDownList)
|
|
return "";
|
|
|
|
return Text().Substring(SelectionStart(), SelectionLength());
|
|
}
|
|
|
|
void ComboBox::SetSelectedText(const string& Value)
|
|
{
|
|
if (_DropDownStyle != ComboBoxStyle::DropDownList)
|
|
{
|
|
if (GetState(ControlStates::StateCreated))
|
|
SendMessageA(this->_ChildEdit, EM_REPLACESEL, (WPARAM)-1, (LPARAM)(const char*)Value);
|
|
}
|
|
}
|
|
|
|
int32_t ComboBox::SelectionLength()
|
|
{
|
|
int32_t End = 0;
|
|
int32_t Start = 0;
|
|
SendMessageA(this->_Handle, CB_GETEDITSEL, (WPARAM)&Start, (WPARAM)&End);
|
|
|
|
return End - Start;
|
|
}
|
|
|
|
void ComboBox::SetSelectionLength(int32_t Value)
|
|
{
|
|
Select(SelectionStart(), Value);
|
|
}
|
|
|
|
int32_t ComboBox::SelectionStart()
|
|
{
|
|
int32_t Value = 0;
|
|
SendMessageA(this->_Handle, CB_GETEDITSEL, (WPARAM)&Value, NULL);
|
|
|
|
return Value;
|
|
}
|
|
|
|
void ComboBox::SetSelectionStart(int32_t Value)
|
|
{
|
|
Select(Value, SelectionLength());
|
|
}
|
|
|
|
ComboBoxStyle ComboBox::DropDownStyle()
|
|
{
|
|
return this->_DropDownStyle;
|
|
}
|
|
|
|
void ComboBox::SetDropDownStyle(ComboBoxStyle Value)
|
|
{
|
|
if (_DropDownStyle != Value)
|
|
{
|
|
_DropDownStyle = Value;
|
|
|
|
if (GetState(ControlStates::StateCreated))
|
|
UpdateStyles();
|
|
}
|
|
}
|
|
|
|
void ComboBox::Select(int32_t Start, int32_t Length)
|
|
{
|
|
int32_t End = Start + Length;
|
|
SendMessageA(this->_Handle, CB_SETEDITSEL, NULL, MAKELPARAM(Start, End));
|
|
}
|
|
|
|
void ComboBox::OnHandleCreated()
|
|
{
|
|
if (_MaximumLength > 0)
|
|
SendMessageA(this->_Handle, CB_LIMITTEXT, (WPARAM)_MaximumLength, NULL);
|
|
|
|
if (_DropDownStyle != ComboBoxStyle::DropDownList)
|
|
{
|
|
auto Hwnd = GetWindow(this->_Handle, GW_CHILD);
|
|
if (Hwnd != NULL)
|
|
{
|
|
if (_DropDownStyle == ComboBoxStyle::Simple)
|
|
{
|
|
_ChildListBox = Hwnd;
|
|
Hwnd = GetWindow(Hwnd, GW_HWNDNEXT);
|
|
}
|
|
|
|
_ChildEdit = Hwnd;
|
|
}
|
|
}
|
|
|
|
if (_DropDownWidth > -1)
|
|
SendMessageA(this->_Handle, CB_SETDROPPEDWIDTH, (WPARAM)_DropDownWidth, NULL);
|
|
|
|
// If we have items, add them now
|
|
for (auto& Item : Items)
|
|
this->NativeAdd((const char*)Item);
|
|
|
|
if (_SelectedIndex > -1)
|
|
{
|
|
SendMessageA(this->_Handle, CB_SETCURSEL, (WPARAM)_SelectedIndex, NULL);
|
|
_SelectedIndex = -1;
|
|
}
|
|
|
|
// We must call the base event last
|
|
Control::OnHandleCreated();
|
|
}
|
|
|
|
void ComboBox::OnSelectedItemChanged()
|
|
{
|
|
SelectedItemChanged.RaiseEvent(this);
|
|
}
|
|
|
|
void ComboBox::OnSelectedIndexChanged()
|
|
{
|
|
SelectedIndexChanged.RaiseEvent(this);
|
|
}
|
|
|
|
void ComboBox::OnDropDownClosed()
|
|
{
|
|
DropDownClosed.RaiseEvent(this);
|
|
}
|
|
|
|
void ComboBox::WndProc(Message& Msg)
|
|
{
|
|
switch (Msg.Msg)
|
|
{
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORLISTBOX:
|
|
Msg.Result = InitializeDCForWmCtlColor((HDC)Msg.WParam, Msg.Msg);
|
|
break;
|
|
case WM_REFLECT + WM_COMMAND:
|
|
WmReflectCommand(Msg);
|
|
break;
|
|
default:
|
|
Control::WndProc(Msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
CreateParams ComboBox::GetCreateParams()
|
|
{
|
|
auto Cp = Control::GetCreateParams();
|
|
|
|
Cp.ClassName = "COMBOBOX";
|
|
Cp.Style |= WS_VSCROLL | CBS_HASSTRINGS | CBS_AUTOHSCROLL;
|
|
|
|
if (!_IntegralHeight)
|
|
Cp.Style |= CBS_NOINTEGRALHEIGHT;
|
|
|
|
switch (_FlatStyle)
|
|
{
|
|
case FlatStyle::Popup:
|
|
case FlatStyle::Flat:
|
|
Cp.ExStyle |= WS_EX_STATICEDGE;
|
|
default:
|
|
Cp.ExStyle |= WS_EX_CLIENTEDGE;
|
|
break;
|
|
}
|
|
|
|
switch (_DropDownStyle)
|
|
{
|
|
case ComboBoxStyle::Simple:
|
|
Cp.Style |= CBS_SIMPLE;
|
|
break;
|
|
case ComboBoxStyle::DropDown:
|
|
Cp.Style |= CBS_DROPDOWN;
|
|
break;
|
|
case ComboBoxStyle::DropDownList:
|
|
Cp.Style |= CBS_DROPDOWNLIST;
|
|
break;
|
|
}
|
|
|
|
switch (_DrawMode)
|
|
{
|
|
case DrawMode::OwnerDrawFixed:
|
|
Cp.Style |= CBS_OWNERDRAWFIXED;
|
|
break;
|
|
case DrawMode::OwnerDrawVariable:
|
|
Cp.Style |= CBS_OWNERDRAWVARIABLE;
|
|
break;
|
|
}
|
|
|
|
return Cp;
|
|
}
|
|
|
|
uintptr_t ComboBox::InitializeDCForWmCtlColor(HDC Dc, int32_t Message)
|
|
{
|
|
if ((Message == WM_CTLCOLORSTATIC))
|
|
{
|
|
return (uintptr_t)0;
|
|
}
|
|
else if ((Message == WM_CTLCOLORLISTBOX) && GetStyle(ControlStyles::UserPaint))
|
|
{
|
|
SetTextColor(Dc, this->ForeColor().ToCOLORREF());
|
|
SetBkColor(Dc, this->BackColor().ToCOLORREF());
|
|
|
|
return BackColorBrush();
|
|
}
|
|
else
|
|
{
|
|
return Control::InitializeDCForWmCtlColor(Dc, Message);
|
|
}
|
|
}
|
|
|
|
int32_t ComboBox::NativeAdd(const char* Value)
|
|
{
|
|
return (int32_t)SendMessageA(this->_Handle, CB_ADDSTRING, NULL, (LPARAM)Value);
|
|
}
|
|
|
|
void ComboBox::NativeClear()
|
|
{
|
|
string Saved;
|
|
|
|
if (_DropDownStyle != ComboBoxStyle::DropDownList)
|
|
Saved = this->WindowText();
|
|
|
|
SendMessageA(this->_Handle, CB_RESETCONTENT, NULL, NULL);
|
|
|
|
if (!string::IsNullOrEmpty(Saved))
|
|
this->SetWindowText(Saved);
|
|
}
|
|
|
|
int32_t ComboBox::NativeInsert(int32_t Index, const char* Value)
|
|
{
|
|
return (int32_t)SendMessageA(this->_Handle, CB_INSERTSTRING, (WPARAM)Index, (LPARAM)Value);
|
|
}
|
|
|
|
void ComboBox::NativeRemoveAt(int32_t Index)
|
|
{
|
|
if (_DropDownStyle == ComboBoxStyle::DropDownList && SelectedIndex() == Index)
|
|
Invalidate();
|
|
|
|
SendMessageA(this->_Handle, CB_DELETESTRING, (WPARAM)Index, NULL);
|
|
}
|
|
|
|
void ComboBox::WmReflectCommand(Message& Msg)
|
|
{
|
|
switch ((int16_t)HIWORD(Msg.WParam))
|
|
{
|
|
case CBN_EDITCHANGE:
|
|
OnTextChanged();
|
|
break;
|
|
case CBN_SELCHANGE:
|
|
OnSelectedIndexChanged();
|
|
OnSelectedItemChanged();
|
|
break;
|
|
case CBN_CLOSEUP:
|
|
OnDropDownClosed();
|
|
break;
|
|
}
|
|
}
|
|
|
|
ComboBox::ComboBoxItemCollection::ComboBoxItemCollection(ComboBox* Owner)
|
|
: _Owner(Owner), _Items()
|
|
{
|
|
}
|
|
|
|
void ComboBox::ComboBoxItemCollection::Add(const imstring& Value)
|
|
{
|
|
_Items.EmplaceBack(Value);
|
|
|
|
if (_Owner->GetState(ControlStates::StateCreated))
|
|
_Owner->NativeAdd(Value);
|
|
}
|
|
|
|
void ComboBox::ComboBoxItemCollection::Insert(int32_t Index, const imstring& Value)
|
|
{
|
|
_Items.Insert(Index, Value);
|
|
|
|
if (_Owner->GetState(ControlStates::StateCreated))
|
|
_Owner->NativeInsert(Index, Value);
|
|
}
|
|
|
|
void ComboBox::ComboBoxItemCollection::Clear()
|
|
{
|
|
_Items.Clear();
|
|
|
|
if (_Owner->GetState(ControlStates::StateCreated))
|
|
_Owner->NativeClear();
|
|
}
|
|
|
|
bool ComboBox::ComboBoxItemCollection::Contains(const imstring & Value)
|
|
{
|
|
return (IndexOf(Value) > -1);
|
|
}
|
|
|
|
int32_t ComboBox::ComboBoxItemCollection::IndexOf(const imstring& Value)
|
|
{
|
|
auto Str = string(Value);
|
|
auto Res = _Items.IndexOf(Str);
|
|
|
|
if (Res == List<string>::InvalidPosition)
|
|
return -1;
|
|
|
|
return Res;
|
|
}
|
|
|
|
void ComboBox::ComboBoxItemCollection::RemoveAt(int32_t Index)
|
|
{
|
|
if (_Owner->GetState(ControlStates::StateCreated))
|
|
_Owner->NativeRemoveAt(Index);
|
|
|
|
_Items.RemoveAt(Index);
|
|
}
|
|
|
|
void ComboBox::ComboBoxItemCollection::Remove(const imstring& Value)
|
|
{
|
|
auto Index = IndexOf(Value);
|
|
|
|
if (Index > -1)
|
|
RemoveAt(Index);
|
|
}
|
|
|
|
uint32_t ComboBox::ComboBoxItemCollection::Count()
|
|
{
|
|
return _Items.Count();
|
|
}
|
|
|
|
string* ComboBox::ComboBoxItemCollection::begin() const
|
|
{
|
|
return _Items.begin();
|
|
}
|
|
|
|
string* ComboBox::ComboBoxItemCollection::end() const
|
|
{
|
|
return _Items.end();
|
|
}
|
|
}
|