//--------------------------------------------------------------------------- #pragma hdrstop #include "ListPanel.h" #include "GlobalUnit.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #define LP_ITEM_OVER RGB(67, 73, 80) #define LP_ITEM_SELECTED RGB(29, 31, 35) #define LP_ITEM_DEF RGB(47, 50, 57) #define IS_OVER 1 #define IS_SELECTED 2 #define IS_UNSELECTED 3 //--------------------------------------------------------------------------- __fastcall TListPanelItem::TListPanelItem(String Caption, TListPanelItemClick OnItemClick) { FCaption = Caption; FOnItemClick = OnItemClick; Tag = 0; } //--------------------------------------------------------------------------- void __fastcall TListPanelItem::DrawItem(TCanvas *Canvas, TRect Rect, int flag) { switch (flag) { case IS_OVER: Canvas->Brush->Color = LP_ITEM_OVER; break; case IS_SELECTED: Canvas->Brush->Color = LP_ITEM_SELECTED; break; default: Canvas->Brush->Color = LP_ITEM_DEF; } /* 绘制背景 */ Canvas->FillRect(Rect); Canvas->Font->Color = TColor(RGB(201, 214, 229)); /* 绘制文字 */ 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 LP_BORDER RGB(106, 111, 117) #define LP_BACKGRND RGB(47, 50, 57)//39, 42, 47) #define LP_BORDER_HL RGB(30, 32, 36) #define LP_BACKGRND_HL RGB(67, 73, 80) #define LP_TXT_NOR RGB(213, 221, 232) #define LP_TXT_DISABLE RGB(100, 108, 119) #define LP_BREAK RGB(100, 108, 119) #define LP_BOARD_FILL RGB(76, 82, 91) #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define MARGIN 2 //--------------------------------------------------------------------------- __fastcall TListPanel::TListPanel(TComponent *Owner) : TPanel(Owner) { // m_ItemRectList = new TList(); m_ItemList = new TList(); Canvas->Font->Color = LP_TXT_NOR; FItemHeight = 20; FSelectedItemIndex = -1; m_CurrentItemIndex = -1; m_RealShowCount = 0; m_BeginIndex = 0; m_EndIndex = 0; m_IsLButtonDown = false; m_ScrollBar = new TSkinScrollBar(NULL); m_ScrollBar->Visible = false; } //--------------------------------------------------------------------------- __fastcall TListPanel::~TListPanel() { /* if(m_ItemRectList) { for( int i=0; iCount; i++ ){ delete m_ItemRectList->Items[i]; } m_ItemRectList->Clear(); delete m_ItemRectList; m_ItemRectList = NULL; } */ for( int i=0; iCount; i++ ){ delete m_ItemList->Items[i]; } m_ItemList->Clear(); delete m_ItemList; m_ItemList = NULL; if(m_ScrollBar) { delete m_ScrollBar; m_ScrollBar = NULL; } } //--------------------------------------------------------------------------- void __fastcall TListPanel::AddItem(TListPanelItem* Item) { m_ItemList->Add(Item); /* if(HandleAllocated()) { Reset(); } */ } //--------------------------------------------------------------------------- void __fastcall TListPanel::Clear() { for( int i=0; iCount; i++ ){ delete m_ItemList->Items[i]; } m_ItemList->Clear(); FSelectedItemIndex = -1; m_CurrentItemIndex = -1; m_BeginIndex = 0; m_EndIndex = 0; ResetScroll(); // if(HandleAllocated()) { // Reset(); // Repaint(); // } } //--------------------------------------------------------------------------- void __fastcall TListPanel::CreateWnd() { TPanel::CreateWnd(); // 设置滚动条属性 m_ScrollBar->Height = Height - 2; m_ScrollBar->Top = 1; m_ScrollBar->Left = Width - m_ScrollBar->Width - 1; m_ScrollBar->Parent = this; m_ScrollBar->m_pWndCtrl = this; //最大显示数 m_ShowCount = (Height - 2 * MARGIN) / FItemHeight; // 记录显示区域 /* m_ItemRectList->Clear(); m_ItemRectList->Add(new TRect(MARGIN, MARGIN, Width - MARGIN, FItemHeight + MARGIN)); for(int i = 1; i < m_ShowCount; i++) { int var_ItemTop = i * FItemHeight + MARGIN; int var_ItemBottom = var_ItemTop + FItemHeight; m_ItemRectList->Add(new TRect(MARGIN, var_ItemTop, Width - MARGIN, var_ItemBottom)); } */ // 记录Item区域 m_ItemArea = TRect(MARGIN, MARGIN, Width - MARGIN, m_ShowCount * FItemHeight + MARGIN); ResetScroll(); } //--------------------------------------------------------------------------- int __fastcall TListPanel::GetItemsCount() { if(m_ItemList) return m_ItemList->Count; else return -1; } //--------------------------------------------------------------------------- //void __fastcall TListPanel::SetTextFontSize(int sz) //{ // Canvas->Font->Size = sz; //} //--------------------------------------------------------------------------- void __fastcall TListPanel::SetTextFont(String name, int size) { Canvas->Font->Name = name; Canvas->Font->Size = size; } //--------------------------------------------------------------------------- TListPanelItem *__fastcall TListPanel::GetItem(int Index) { if(ItemsCount == 0 || Index < 0 || Index > ItemsCount) return NULL; else return (TListPanelItem *)m_ItemList->Items[Index]; } /*/--------------------------------------------------------------------------- TRect *__fastcall TListPanel::GetItemRect(int Index) { return (TRect *)m_ItemRectList->Items[Index]; } */ //--------------------------------------------------------------------------- void __fastcall TListPanel::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y) { TPanel::MouseDown(Button, Shift, X, Y); if(m_ScrollBar->Visible && Button == 0) { m_IsLButtonDown = true; m_ScrollBar->Enabled = false; } int areaRight = 0; m_ScrollBar->Visible ? areaRight = m_ItemArea.Right - m_ScrollBar->Width - 1 : areaRight = m_ItemArea.Right; if(Button == 0 && X >= m_ItemArea.Left && X < areaRight && Y >= m_ItemArea.Top && Y < m_ItemArea.Bottom && ItemsCount > 0) { int index = (Y - MARGIN) / FItemHeight + m_BeginIndex; if(index < m_ItemList->Count && m_ItemList->Count != 0) { if(FSelectedItemIndex != index) { if(FSelectedItemIndex >= m_BeginIndex && FSelectedItemIndex < m_EndIndex) SetItemStatus(FSelectedItemIndex, IS_UNSELECTED); FSelectedItemIndex = index; SetItemStatus(FSelectedItemIndex, IS_SELECTED); } GetItem(FSelectedItemIndex)->OnItemClicked(this, FSelectedItemIndex); } } } //--------------------------------------------------------------------------- void __fastcall TListPanel::MouseMove(TShiftState Shift, int X, int Y) { TPanel::MouseMove(Shift, X, Y); if(m_IsLButtonDown) return; if(m_MouseX == X && m_MouseY == Y) return; m_MouseX = X; m_MouseY = Y; int areaRight = 0, index = -1; m_ScrollBar->Visible ? areaRight = m_ItemArea.Right - m_ScrollBar->Width - 1 : areaRight = m_ItemArea.Right; if(X >= m_ItemArea.Left && X < areaRight && Y >= m_ItemArea.Top && Y < m_ItemArea.Bottom && ItemsCount > 0) { index = (Y - MARGIN) / FItemHeight + m_BeginIndex; if(index < m_ItemList->Count && m_ItemList->Count != 0) { if(index != m_CurrentItemIndex) { /* 还原上一次选中项 */ if(m_CurrentItemIndex >= m_BeginIndex && m_CurrentItemIndex < m_EndIndex) { m_CurrentItemIndex == FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED) : SetItemStatus(m_CurrentItemIndex, IS_UNSELECTED); } /* 更新当前选择项 */ m_CurrentItemIndex = index; /* 重绘选中项 */ m_CurrentItemIndex == FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED) : SetItemStatus(m_CurrentItemIndex, IS_OVER); } } } if( ( index<0 || index>m_ItemList->Count ) && m_CurrentItemIndex >= m_BeginIndex && m_CurrentItemIndex < m_EndIndex ){ m_CurrentItemIndex==FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED) : SetItemStatus(m_CurrentItemIndex, IS_UNSELECTED); m_CurrentItemIndex = -1; } } //--------------------------------------------------------------------------- void __fastcall TListPanel::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y) { TPanel::MouseUp(Button, Shift, X, Y); if(m_ScrollBar->Visible && Button == 0) { m_IsLButtonDown = false; m_ScrollBar->Enabled = true; } } //--------------------------------------------------------------------------- void __fastcall TListPanel::SetItemStatus(int Index, int flag) { int var_ItemTop = ( Index - m_BeginIndex ) * FItemHeight + MARGIN; TRect rtDraw( MARGIN, var_ItemTop, Width - MARGIN, var_ItemTop + FItemHeight ); GetItem(Index)->DrawItem(Canvas, rtDraw, flag); } //--------------------------------------------------------------------------- void __fastcall TListPanel::SetSelectedItemIndex(int Index) { if(FSelectedItemIndex != Index) { if( FSelectedItemIndex>=m_BeginIndex && FSelectedItemIndex=m_ItemList->Count ){ FSelectedItemIndex = -1; } else{ FSelectedItemIndex = Index; int posScroll = m_BeginIndex; if( Index=m_EndIndex ){ posScroll = Index - m_ShowCount + 1; } if( posScroll==m_BeginIndex ){ SetItemStatus( FSelectedItemIndex-m_BeginIndex, IS_SELECTED ); } else if( m_ScrollBar->Visible ){ ScrollPos( posScroll ); m_ScrollBar->SetPosition(posScroll); } } } } //--------------------------------------------------------------------------- void __fastcall TListPanel::Paint() { Canvas->Lock(); for(int Index = m_BeginIndex; Index < m_EndIndex; Index++) { if(Index == FSelectedItemIndex) SetItemStatus(Index, IS_SELECTED); else if(Index == m_CurrentItemIndex) SetItemStatus(Index, IS_OVER); else SetItemStatus(Index, IS_UNSELECTED); } if( m_ShowCount > ItemsCount ){ int var_Top = ItemsCount * FItemHeight + MARGIN, var_Bottom = var_Top + ( m_ShowCount - ItemsCount ) * FItemHeight; TRect rtDraw( MARGIN, var_Top, Width - MARGIN, var_Bottom ); Canvas->Brush->Color = LP_BACKGRND; Canvas->FillRect(rtDraw); } Canvas->Unlock(); } //--------------------------------------------------------------------------- void __fastcall TListPanel::ResetScroll() { m_RealShowCount = MIN(ItemsCount, m_ShowCount); if( FSelectedItemIndex>=0 ){ if( FSelectedItemIndex < m_BeginIndex ){ m_BeginIndex = FSelectedItemIndex; } else if( FSelectedItemIndex >= m_BeginIndex + m_ShowCount ){ m_BeginIndex = FSelectedItemIndex - m_ShowCount + 1; } } m_EndIndex = min( m_BeginIndex + m_RealShowCount, ItemsCount ); if( ItemsCount > m_ShowCount) { m_ScrollBar->Visible = true; m_ScrollBar->SetRange(0, ItemsCount - 1); m_ScrollBar->SetPageSize(m_ShowCount); m_ScrollBar->SetPosition(m_BeginIndex); } else { m_ScrollBar->Visible = false; } Paint(); } //--------------------------------------------------------------------------- void __fastcall TListPanel::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; Paint(); } } } //--------------------------------------------------------------------------- void __fastcall TListPanel::WMEraseBkgnd(TWMEraseBkgnd &Message) { TCanvas* var_BKCanvas = new TCanvas(); var_BKCanvas->Handle = Message.DC; TRect var_Rect = GetClientRect(); var_BKCanvas->Brush->Color = LP_BACKGRND; // 绘制底色 var_BKCanvas->FillRect(var_Rect); var_BKCanvas->Brush->Color = LP_BORDER; // 绘制边框 var_BKCanvas->FrameRect(var_Rect); delete var_BKCanvas; var_BKCanvas = NULL; } //--------------------------------------------------------------------------- void __fastcall TListPanel::WMMouseWheel(TWMMouseWheel &Message) { UINT nSBCode; if(m_IsLButtonDown) return; if(Message.WheelDelta < 0) { nSBCode = SB_LINEDOWN; } else { nSBCode = SB_LINEUP; } if(m_ScrollBar->Visible) Perform(WM_VSCROLL, MAKELONG(nSBCode, 0), NULL); } //--------------------------------------------------------------------------- void __fastcall TListPanel::CMMouseLeave(TMessage &Message) { m_CurrentItemIndex = -1; Repaint(); } //--------------------------------------------------------------------------- void __fastcall TListPanel::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); } //--------------------------------------------------------------------------- int __fastcall TListPanel::TextWidth(String text) { return Canvas->TextWidth(text); } //--------------------------------------------------------------------------- void __fastcall TListPanel::WMSize(Winapi::Messages::TWMSize &Message) { DefaultHandler( &Message ); m_ScrollBar->Height = Height - 2; m_ScrollBar->Top = 1; m_ScrollBar->Left = Width - m_ScrollBar->Width - 1; //最大显示数 m_ShowCount = (Height - 2 * MARGIN) / FItemHeight; // 记录显示区域 /* m_ItemRectList->Clear(); m_ItemRectList->Add(new TRect(MARGIN, MARGIN, Width - MARGIN, FItemHeight + MARGIN)); for(int i = 1; i < m_ShowCount; i++) { int var_ItemTop = i * FItemHeight + MARGIN; int var_ItemBottom = var_ItemTop + FItemHeight; m_ItemRectList->Add(new TRect(MARGIN, var_ItemTop, Width - MARGIN, var_ItemBottom)); } */ // 记录Item区域 m_ItemArea = TRect(MARGIN, MARGIN, Width - MARGIN, m_ShowCount * FItemHeight + MARGIN); // ResetScroll(); } //---------------------------------------------------------------------------