619 lines
16 KiB
C++
619 lines
16 KiB
C++
//---------------------------------------------------------------------------
|
|
|
|
#include "ComboBoxComponent.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
#define CP_ITEM_SLECTED RGB(67, 73, 80)
|
|
#define CP_ITEM_UNSLECTED RGB(39, 42, 47)
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TComboBoxItem::TComboBoxItem(String Caption, TItemClickEvent OnItemClick)
|
|
{
|
|
FCaption = Caption;
|
|
FOnItemClick = OnItemClick;
|
|
FTag = 0;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TComboBoxItem::DrawItem(TCanvas *Canvas, TRect Rect, bool Selected)
|
|
{
|
|
if(Selected)
|
|
Canvas->Brush->Color = CP_ITEM_SLECTED;
|
|
else
|
|
Canvas->Brush->Color = CP_ITEM_UNSLECTED;
|
|
|
|
/* 绘制背景 */
|
|
Canvas->FillRect(Rect);
|
|
|
|
/* 绘制文字 */
|
|
int var_TextRectTop = Rect.Top + (Rect.Height() - Canvas->TextHeight(FCaption)) / 2;
|
|
|
|
TRect var_TextRect(4, var_TextRectTop, Rect.Right - 4, Rect.Bottom);
|
|
|
|
Canvas->TextRect(var_TextRect, FCaption);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
//---------------------------------------------------------------------------
|
|
//#define CP_BORDER RGB(29, 31, 35)
|
|
#define CP_BORDER RGB(106, 111, 117)
|
|
#define CP_BACKGRND RGB(39, 42, 47)
|
|
|
|
#define CP_BORDER_HL RGB(30, 32, 36)
|
|
#define CP_BACKGRND_HL RGB(67, 73, 80)
|
|
|
|
#define CP_TXT_NOR RGB(213, 221, 232)
|
|
#define CP_TXT_DISABLE RGB(100, 108, 119)
|
|
#define CP_BREAK RGB(100, 108, 119)
|
|
#define CP_BOARD_FILL RGB(76, 82, 91)
|
|
|
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TDropListView::TDropListView(TComponent *Owner) : TWinControl(Owner)
|
|
{
|
|
m_Canvas = new TControlCanvas();
|
|
m_Canvas->Control = this;
|
|
m_Canvas->Font->Color = RGB(156, 170, 189);
|
|
|
|
m_ItemRectList = new TList();
|
|
m_ItemList = new TList();
|
|
|
|
FOnHide = NULL;
|
|
FOnShow = NULL;
|
|
|
|
FItemHeight = 16;
|
|
FItemWidth = 99;
|
|
FDefItemIndex = -1;
|
|
FShowItemsCount = 10;
|
|
DoShowItemsChange();
|
|
|
|
m_CurrentItemIndex = 0;
|
|
m_RealShowCount = 0;
|
|
|
|
m_BeginIndex = 0;
|
|
|
|
m_ScrollBar = NULL;
|
|
|
|
SetDesignVisible(false);
|
|
Ctl3D = false;
|
|
ParentBackground = false;
|
|
ParentBiDiMode = false;
|
|
ParentColor = false;
|
|
ParentCustomHint = false;
|
|
ParentDoubleBuffered = false;
|
|
ParentFont = true;
|
|
ParentShowHint = false;
|
|
|
|
CreateScrollBar();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
__fastcall TDropListView::~TDropListView()
|
|
{
|
|
if(m_ItemRectList)
|
|
{
|
|
delete m_ItemRectList;
|
|
m_ItemRectList = NULL;
|
|
}
|
|
|
|
if(m_ItemList)
|
|
{
|
|
delete m_ItemList;
|
|
m_ItemList = NULL;
|
|
}
|
|
|
|
if(m_ScrollBar)
|
|
{
|
|
delete m_ScrollBar;
|
|
m_ScrollBar = NULL;
|
|
}
|
|
|
|
if(m_Canvas)
|
|
{
|
|
delete m_Canvas;
|
|
m_Canvas = NULL;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::AddItem(TComboBoxItem* Item)
|
|
{
|
|
m_ItemList->Add(Item);
|
|
|
|
DoItemsCountChange();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TDropListView::CalcListHeight()
|
|
{
|
|
if(ItemsCount == 0)
|
|
return 10;
|
|
else
|
|
return FItemHeight * m_RealShowCount;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::Clear()
|
|
{
|
|
m_ItemList->Clear();
|
|
FDefItemIndex = -1;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::CreateParams(TCreateParams &Params)
|
|
{
|
|
TWinControl::CreateParams(Params);
|
|
|
|
Params.Style = 0;
|
|
|
|
Params.Style = WS_POPUP;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::CreateScrollBar()
|
|
{
|
|
m_ScrollBar = new TDropListScrollBar(NULL);
|
|
m_ScrollBar->Parent = this;
|
|
m_ScrollBar->Visible = false;
|
|
m_ScrollBar->m_pWndCtrl = this;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::CreateWnd()
|
|
{
|
|
TWinControl::CreateWnd();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::SetFontSize(int sz)
|
|
{
|
|
m_Canvas->Font->Size = sz;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::SetFont(String name, int sz)
|
|
{
|
|
m_Canvas->Font->Name = name;
|
|
m_Canvas->Font->Size = sz;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::DoItemClicked(int Index)
|
|
{
|
|
FDefItemIndex = Index;
|
|
GetItem(FDefItemIndex)->OnItemClicked(GetItem(FDefItemIndex), FDefItemIndex);
|
|
Hide();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::DoItemsCountChange()
|
|
{
|
|
m_RealShowCount = MIN(FShowItemsCount, ItemsCount);
|
|
|
|
m_EndIndex = m_BeginIndex + m_RealShowCount;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::DoItemSelect(int Index)
|
|
{
|
|
if(Index != m_CurrentItemIndex)
|
|
{
|
|
/* 还原上一次选中项 */
|
|
if(m_CurrentItemIndex >= m_BeginIndex && m_CurrentItemIndex < m_EndIndex)
|
|
{
|
|
GetItem(m_CurrentItemIndex)->DrawItem(m_Canvas,
|
|
*GetItemRect(m_CurrentItemIndex - m_BeginIndex), false);
|
|
}
|
|
/* 更新当前选择项 */
|
|
m_CurrentItemIndex = Index;
|
|
/* 重绘选中项 */
|
|
GetItem(m_CurrentItemIndex)->DrawItem(m_Canvas,
|
|
*GetItemRect(m_CurrentItemIndex - m_BeginIndex), true);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::DoKeyUpDown(int Index)
|
|
{
|
|
if(Index < m_BeginIndex)
|
|
{
|
|
int var_eIndex = Index + 1;
|
|
|
|
if(var_eIndex < m_RealShowCount)
|
|
ScrollPos(0);
|
|
else
|
|
ScrollPos(var_eIndex - m_RealShowCount);
|
|
}
|
|
|
|
if(Index >= m_EndIndex)
|
|
{
|
|
int var_eIndex = Index + m_RealShowCount;
|
|
|
|
if(var_eIndex > ItemsCount)
|
|
ScrollPos(ItemsCount - m_RealShowCount);
|
|
else
|
|
ScrollPos(var_eIndex - m_RealShowCount);
|
|
}
|
|
|
|
DoItemSelect(Index);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::DoShowItemsChange()
|
|
{
|
|
m_ItemRectList->Clear();
|
|
|
|
for(int i = 0; i < FShowItemsCount; i++)
|
|
{
|
|
int var_ItemTop = i * FItemHeight;
|
|
int var_ItemBottom = var_ItemTop + FItemHeight;
|
|
|
|
m_ItemRectList->Add(new TRect(1, var_ItemTop + 1, FItemWidth, var_ItemBottom - 1));
|
|
}
|
|
|
|
DoItemsCountChange();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::Hide()
|
|
{
|
|
TWinControl::Hide();
|
|
|
|
SetActiveWindow(m_pActiveWnd);
|
|
|
|
if(FOnHide) FOnHide(this);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
int __fastcall TDropListView::GetItemsCount()
|
|
{
|
|
if(m_ItemList)
|
|
return m_ItemList->Count;
|
|
else
|
|
return -1;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TComboBoxItem *__fastcall TDropListView::GetItem(int Index)
|
|
{
|
|
if(ItemsCount == 0 || Index < 0 || Index > ItemsCount)
|
|
return NULL;
|
|
else
|
|
return (TComboBoxItem *)m_ItemList->Items[Index];
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
TRect *__fastcall TDropListView::GetItemRect(int Index)
|
|
{
|
|
return (TRect *)m_ItemRectList->Items[Index];
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
|
|
{
|
|
TWinControl::MouseDown(Button, Shift, X, Y);
|
|
|
|
TRect cl_Rect = GetClientRect();
|
|
|
|
if(X >= 0 && X <= cl_Rect.Right && Y >= 0 && Y <= cl_Rect.Bottom && ItemsCount > 0)
|
|
{
|
|
if(Button == 0 && X < FItemWidth)
|
|
{
|
|
int var_DefItemIndex = Y / FItemHeight + m_BeginIndex;
|
|
|
|
if(m_CurrentItemIndex != var_DefItemIndex)
|
|
DoItemSelect(var_DefItemIndex);
|
|
else
|
|
DoItemClicked(var_DefItemIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Hide();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::MouseMove(TShiftState Shift, int X, int Y)
|
|
{
|
|
TWinControl::MouseMove(Shift, X, Y);
|
|
|
|
if(m_MouseX == X && m_MouseY == Y) return;
|
|
|
|
m_MouseX = X;
|
|
m_MouseY = Y;
|
|
|
|
TRect var_Rect = GetClientRect();
|
|
|
|
if(X >= 0 && X < FItemWidth && Y >= 0 && Y < var_Rect.Bottom && ItemsCount > 0)
|
|
DoItemSelect(Y / FItemHeight + m_BeginIndex);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y)
|
|
{
|
|
TWinControl::MouseUp(Button, Shift, X, Y);
|
|
|
|
TRect cl_Rect = GetClientRect();
|
|
|
|
if(X >= 0 && X <= cl_Rect.Right && Y >= 0 && Y <= cl_Rect.Bottom)
|
|
{
|
|
if(Visible && ItemsCount > 0 && Button == 0 && X < FItemWidth)
|
|
{
|
|
int var_DefItemIndex = Y / FItemHeight + m_BeginIndex;
|
|
|
|
if(m_CurrentItemIndex != var_DefItemIndex)
|
|
DoItemSelect(var_DefItemIndex);
|
|
else
|
|
DoItemClicked(var_DefItemIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(Visible) Hide();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::PaintWindow(HDC DC)
|
|
{
|
|
if(ItemsCount == 0) return;
|
|
|
|
m_Canvas->Lock();
|
|
for(int Index = m_BeginIndex; Index < m_EndIndex; Index++)
|
|
{
|
|
int var_ShowIndex = Index - m_BeginIndex;
|
|
|
|
if(Index == m_CurrentItemIndex)
|
|
GetItem(Index)->DrawItem(m_Canvas, *GetItemRect(var_ShowIndex), true);
|
|
else
|
|
GetItem(Index)->DrawItem(m_Canvas, *GetItemRect(var_ShowIndex), false);
|
|
}
|
|
m_Canvas->Unlock();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::RemoveItem(int Index)
|
|
{
|
|
if(ItemsCount == 0 || Index < 0 || Index > ItemsCount)
|
|
return;
|
|
|
|
if(Index == FDefItemIndex)
|
|
FDefItemIndex = -1;
|
|
else if(Index > FDefItemIndex)
|
|
FDefItemIndex--;
|
|
|
|
m_ItemList->Delete(Index);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::ScrollPos(int Pos)
|
|
{
|
|
if(Pos >= 0 && Pos < ItemsCount)
|
|
{
|
|
int var_bIndex = Pos;
|
|
int var_eIndex = Pos + m_RealShowCount;
|
|
|
|
if(var_eIndex > ItemsCount)
|
|
{
|
|
var_eIndex = ItemsCount;
|
|
var_bIndex = var_eIndex - m_RealShowCount;
|
|
}
|
|
|
|
if(var_bIndex != m_BeginIndex)
|
|
{
|
|
m_BeginIndex = var_bIndex;
|
|
m_EndIndex = var_eIndex;
|
|
|
|
PaintWindow(NULL);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::SetShowItemsCount(int Value)
|
|
{
|
|
if(FShowItemsCount != Value)
|
|
{
|
|
FShowItemsCount = Value;
|
|
|
|
DoShowItemsChange();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::Show()
|
|
{
|
|
TWinControl::Show();
|
|
|
|
m_pActiveWnd = GetActiveWindow();
|
|
SetActiveWindow(Handle);
|
|
|
|
//if(FDefItemIndex == -1)
|
|
//m_CurrentItemIndex = 0;
|
|
//else
|
|
m_CurrentItemIndex = FDefItemIndex;
|
|
|
|
if(m_CurrentItemIndex == -1)
|
|
{
|
|
m_BeginIndex = 0;
|
|
m_EndIndex = m_RealShowCount;
|
|
ScrollPos(0);
|
|
}
|
|
else
|
|
{
|
|
m_BeginIndex = m_CurrentItemIndex;
|
|
m_EndIndex = m_CurrentItemIndex + m_RealShowCount;
|
|
|
|
if(m_EndIndex > ItemsCount)
|
|
{
|
|
m_EndIndex = ItemsCount;
|
|
m_BeginIndex = m_EndIndex - m_RealShowCount;
|
|
}
|
|
|
|
if(m_CurrentItemIndex < m_BeginIndex || m_CurrentItemIndex >= m_EndIndex)
|
|
{
|
|
int var_eIndex = m_CurrentItemIndex + 1;
|
|
|
|
if(var_eIndex < m_RealShowCount)
|
|
ScrollPos(m_BeginIndex);
|
|
else
|
|
ScrollPos(m_EndIndex - m_RealShowCount);
|
|
}
|
|
}
|
|
|
|
if(ItemsCount == 0)
|
|
Height = 10;
|
|
else
|
|
Height = FItemHeight * m_RealShowCount;
|
|
|
|
if(m_ScrollBar)
|
|
{
|
|
m_ScrollBar->Height = Height - 2;
|
|
m_ScrollBar->Left = Width - m_ScrollBar->Width - 1;
|
|
m_ScrollBar->Top = 1;
|
|
|
|
if(m_RealShowCount < ItemsCount)
|
|
{
|
|
m_ScrollBar->Visible = true;
|
|
FItemWidth = m_ScrollBar->Left;
|
|
m_ScrollBar->SetRange(0, ItemsCount - 1);
|
|
m_ScrollBar->SetPageSize(m_RealShowCount);
|
|
m_ScrollBar->SetPosition(m_BeginIndex);
|
|
DoShowItemsChange();
|
|
}
|
|
else
|
|
{
|
|
m_ScrollBar->Visible = false;
|
|
FItemWidth = Width - 1;
|
|
DoShowItemsChange();
|
|
}
|
|
}
|
|
|
|
if(FOnShow) FOnShow(this);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMEraseBkgnd(TWMEraseBkgnd &Message)
|
|
{
|
|
TCanvas* var_BKCanvas = new TCanvas();
|
|
var_BKCanvas->Handle = Message.DC;
|
|
|
|
TRect var_Rect = GetClientRect();
|
|
|
|
var_BKCanvas->Brush->Color = CP_BACKGRND; // 绘制底色
|
|
var_BKCanvas->FillRect(var_Rect);
|
|
|
|
var_BKCanvas->Brush->Color = CP_BORDER; // 绘制边框
|
|
var_BKCanvas->FrameRect(var_Rect);
|
|
|
|
delete var_BKCanvas;
|
|
var_BKCanvas = NULL;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMKeyDown(TWMKeyDown &Message)
|
|
{
|
|
if(ItemsCount == 0) return;
|
|
|
|
if(Message.CharCode == VK_UP)
|
|
{
|
|
int var_Index = m_CurrentItemIndex - 1;
|
|
if(var_Index < 0) var_Index = 0;
|
|
|
|
DoKeyUpDown(var_Index);
|
|
}
|
|
else if(Message.CharCode == VK_DOWN)
|
|
{
|
|
int var_Index = m_CurrentItemIndex + 1;
|
|
if(var_Index >= ItemsCount) var_Index = ItemsCount - 1;
|
|
|
|
DoKeyUpDown(var_Index);
|
|
}
|
|
else if(Message.CharCode == VK_ESCAPE)
|
|
{
|
|
Hide();
|
|
}
|
|
else if(Message.CharCode == VK_RETURN)
|
|
{
|
|
DoItemClicked(m_CurrentItemIndex);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMKillFocus(TMessage &Message)
|
|
{
|
|
Hide();
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMLButtonDown(TWMLButtonDown &Message)
|
|
{
|
|
TWinControl::Dispatch(&Message);
|
|
|
|
if(m_ScrollBar)
|
|
{
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMMouseWheel(TWMMouseWheel &Message)
|
|
{
|
|
UINT nSBCode;
|
|
|
|
if(Message.WheelDelta < 0)
|
|
{
|
|
nSBCode = SB_LINEDOWN;
|
|
}
|
|
else
|
|
{
|
|
nSBCode = SB_LINEUP;
|
|
}
|
|
|
|
if(m_ScrollBar->Visible)
|
|
Perform(WM_VSCROLL, MAKELONG(nSBCode, 0), NULL);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMPaint(TWMPaint &Message)
|
|
{
|
|
PaintHandler(Message);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMSetFocus(TMessage &Message)
|
|
{
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
void __fastcall TDropListView::WMVScroll(TWMScroll &Message)
|
|
{
|
|
int minpos, maxpos, page, curpos;
|
|
|
|
m_ScrollBar->GetScrollRange(& minpos, & maxpos);
|
|
|
|
page = m_ScrollBar->GetPageSize();
|
|
curpos = m_ScrollBar->GetScrollPos();
|
|
|
|
switch(Message.ScrollCode)
|
|
{
|
|
case SB_TOP:
|
|
curpos = minpos;
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
curpos = maxpos - page + 1;
|
|
break;
|
|
|
|
case SB_ENDSCROLL:
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
if(curpos > minpos)
|
|
{
|
|
curpos--;
|
|
}
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
if(curpos < maxpos - page + 1)
|
|
{
|
|
curpos++;
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
if(curpos > minpos)
|
|
{
|
|
curpos = MAX(minpos, curpos - page);
|
|
}
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
if(curpos < maxpos)
|
|
{
|
|
curpos = MIN(maxpos - page + 1, curpos + page);
|
|
}
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
curpos = Message.Pos;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
curpos = Message.Pos;
|
|
break;
|
|
}
|
|
|
|
if(Message.ScrollBar != m_ScrollBar->Handle)
|
|
{
|
|
m_ScrollBar->SetPosition(curpos);
|
|
}
|
|
|
|
ScrollPos(curpos);
|
|
}
|
|
//---------------------------------------------------------------------------
|