//--------------------------------------------------------------------------- #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); } //---------------------------------------------------------------------------