Files
AC_Pro/ListPanel.cpp
2026-06-13 00:05:19 +08:00

568 lines
15 KiB
C++

//---------------------------------------------------------------------------
#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; i<m_ItemRectList->Count; i++ ){
delete m_ItemRectList->Items[i];
}
m_ItemRectList->Clear();
delete m_ItemRectList;
m_ItemRectList = NULL;
}
*/
for( int i=0; i<m_ItemList->Count; 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; i<m_ItemList->Count; 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_EndIndex ){
SetItemStatus( FSelectedItemIndex-m_BeginIndex, IS_UNSELECTED );
}
if( Index<0 || Index>=m_ItemList->Count ){
FSelectedItemIndex = -1;
}
else{
FSelectedItemIndex = Index;
int posScroll = m_BeginIndex;
if( Index<m_BeginIndex ){
posScroll = Index;
}
else 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();
}
//---------------------------------------------------------------------------