//--------------------------------------------------------------------------- #include #pragma hdrstop #include "ComposeListBoxUnit.h" #include "GlobalUnit.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #define COLOR_BORDER RGB(164,115,70) //--------------------------------------------------------------------------- __fastcall ComposeListBoxUnit::TListBox::TListBox(System::Classes::TComponent* AOwner) : TSkinListBox(AOwner) { m_imgBackground = new TBitmap(); m_imgBackground->LoadFromResourceName(int(HInstance), L"ListBoxBkgrnd"); m_clrBevelRaise = RGB(225,181,120); m_clrBevelLower = RGB(101,101,101); m_clrSelected = RGB( 255, 0, 0 ); m_pFntText = new TFont(); m_pFntText->Name = "黑体"; m_pFntText->Size = int(9 * 96.0 / g_yDpi + 0.5); m_imgDrag = NULL; m_xImgDrag = m_yImgDrag = -100; m_iDragOverPos = m_iDragingStage = -1; m_bDraging = m_bAddStage = false; } //--------------------------------------------------------------------------- __fastcall ComposeListBoxUnit::TListBox::~TListBox() { if( m_imgBackground ){ delete m_imgBackground; } if( m_pFntText ){ delete m_pFntText; } } //--------------------------------------------------------------------------- void __fastcall ComposeListBoxUnit::TListBox::WMPaint(Winapi::Messages::TWMPaint &Message) { DefaultHandler( &Message ); if( Items->Count==0 ){ TRect rectClient(0,0,ClientWidth,ClientHeight); //绘制外边框 Canvas->Brush->Color = COLOR_BORDER; Canvas->FrameRect( rectClient ); //绘制底图 rectClient.left++; rectClient.right--; rectClient.top++; rectClient.bottom--; Canvas->StretchDraw( rectClient, m_imgBackground ); } if( m_bDraging && m_imgDrag ){ //绘制半透明图片 TBlendFunction Blend; Blend.BlendOp = AC_SRC_OVER; Blend.BlendFlags = 0; Blend.AlphaFormat = 0; Blend.SourceConstantAlpha =160; ::AlphaBlend (Canvas->Handle, m_xImgDrag, m_yImgDrag, m_imgDrag->Width, m_imgDrag->Height, m_imgDrag->Canvas->Handle, 0, 0, m_imgDrag->Width, m_imgDrag->Height, Blend ); } } //--------------------------------------------------------------------------- void __fastcall ComposeListBoxUnit::TListBox::DrawItem(int Index, const System::Types::TRect &Rect, Winapi::Windows::TOwnerDrawState State) { TRect rcDraw, rcOrig = Rect; // if( rcOrig.Width()Pen->Color = COLOR_BORDER; //绘制选中框 if( State.Contains(odSelected) ){//|| State.Contains(odFocused) ){ Canvas->Brush->Color = m_clrSelected; Canvas->FrameRect( rcDraw ); } else{ //绘制左边框 Canvas->MoveTo( rcDraw.left, rcDraw.top ); Canvas->LineTo( rcDraw.left, rcDraw.bottom ); //绘制右边框 Canvas->MoveTo( rcDraw.right-1, rcDraw.top ); Canvas->LineTo( rcDraw.right-1, rcDraw.bottom ); if( m_bDraging && m_iDragOverPos==Index ){ //绘制Drop提示 Canvas->Pen->Color = clWhite; for( int i=0; i<2; i++ ){ Canvas->MoveTo( rcDraw.left+1, rcDraw.top ); Canvas->LineTo( rcDraw.right-1, rcDraw.top ); rcDraw.top++; } Canvas->Pen->Color = COLOR_BORDER; Canvas->MoveTo( rcDraw.left+1, rcDraw.top ); Canvas->LineTo( rcDraw.right-1, rcDraw.top ); } else{ //绘制上阴影 Canvas->Pen->Color = m_clrBevelRaise; Canvas->MoveTo( rcDraw.left+1, rcDraw.top ); Canvas->LineTo( rcDraw.right-1, rcDraw.top ); } if( m_bDraging && m_iDragOverPos==Index+1 ){ //绘制Drop提示 Canvas->Pen->Color = clWhite; for( int i=0; i<2; i++ ){ Canvas->MoveTo( rcDraw.left+1, rcDraw.bottom-1 ); Canvas->LineTo( rcDraw.right-1, rcDraw.bottom-1 ); rcDraw.bottom--; } Canvas->Pen->Color = COLOR_BORDER; Canvas->MoveTo( rcDraw.left+1, rcDraw.bottom-1 ); Canvas->LineTo( rcDraw.right-1, rcDraw.bottom-1 ); } else{ //绘制下阴影 Canvas->Pen->Color = COLOR_BORDER; Canvas->MoveTo( rcDraw.left+1, rcDraw.bottom-1 ); Canvas->LineTo( rcDraw.right-1, rcDraw.bottom-1 ); } } rcDraw.left++; rcDraw.right--; rcDraw.top++; rcDraw.bottom--; //绘制底色 COLORREF rColor; DWORD dwItemData = DWORD(Items->Objects[Index]); WORD iVar = HIWORD( dwItemData ); int iInd = LOWORD( dwItemData ); if( iInd>=COMPOSE_ENDING_1 ){ rColor = g_clrEnding[iInd-COMPOSE_ENDING_1]; } else if( iInd>=COMPOSE_INTRO_1 ){ rColor = g_clrIntro[iInd-COMPOSE_INTRO_1]; } else{ rColor = g_clrStage[iVar]; } Canvas->Brush->Color = rColor; Canvas->FillRect( rcDraw ); //绘制列表项文字 TFont * oldFont= Canvas->Font; Canvas->Font = m_pFntText; Canvas->Brush->Style = bsClear; String strText = Items->Strings[Index]; int nTextWidth = Canvas->TextWidth( strText ), nTextHeight = Canvas->TextHeight( strText ); if( nTextWidth>rcDraw.Width()-4 ){ strText = strText.SubString(0, 8) + "..."; nTextWidth = Canvas->TextWidth( strText ); } int x = rcDraw.left + ( rcDraw.Width() - nTextWidth ) / 2, y = rcOrig.top + ( ItemHeight - nTextHeight ) / 2 + 1; Canvas->TextOut( x, y, strText ); Canvas->Font = oldFont; if( Rect.top>Height-ItemHeight ){ //绘制下边框 Canvas->MoveTo( rcDraw.left, Height-1 ); Canvas->LineTo( rcDraw.right, Height-1 ); } if( Index==Items->Count-1 && Rect.bottomWidth = rcBlank.Width(); pTempBMP->Height = m_imgBackground->Height; pTempBMP->Canvas->Draw( 0, 0, m_imgBackground ); int y = rcBlank.top; for( int i=0; iHeight; i++ ){ y += pTempBMP->Height; } //Canvas->StretchDraw( rcBlank, pTempBMP ); Canvas->StretchDraw( rcBlank, m_imgBackground ); delete pTempBMP; //绘制边框 Canvas->Pen->Color = COLOR_BORDER; Canvas->MoveTo( rcBlank.left, rcBlank.top ); Canvas->LineTo( rcBlank.left, rcBlank.bottom-1 ); Canvas->MoveTo( rcBlank.right-1, rcBlank.top ); Canvas->LineTo( rcBlank.right-1, rcBlank.bottom-1 ); Canvas->MoveTo( rcBlank.left, rcBlank.bottom-1 ); Canvas->LineTo( rcBlank.right, rcBlank.bottom-1 ); //绘制底图 rcBlank.left++; rcBlank.right--; rcBlank.bottom--; } } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::SetDragState( bool bDraging ) { if( m_bDraging!=bDraging ){ if( !bDraging ){ RECT rcDrag; rcDrag.left = m_xImgDrag; rcDrag.top = m_yImgDrag; rcDrag.right = m_xImgDrag+m_imgDrag->Width; rcDrag.bottom = m_yImgDrag+m_imgDrag->Height; TRect rcLastItem = ItemRect( Items->Count-1 ); if( rcLastItem.bottom <= m_yImgDrag ){ rcDrag.top = rcLastItem.bottom-1; } m_xImgDrag = m_yImgDrag = -100; InvalidateRect( Handle, &rcDrag, false ); UpdateDragOverPos( -1 ); m_iDragOverPos = m_iDragingStage = -1; m_bAddStage = false; } m_bDraging = bDraging; } } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::SetDragStage( bool bAdd, int iStage ) { m_bAddStage = bAdd; m_iDragingStage = iStage; } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::SetDragImgPos( int X, int Y ) { TPoint ptScreen(X, Y), ptClient = ScreenToClient( ptScreen ); TRect rcClient = GetClientRect(); RECT rcDrag; if( m_bDraging && ( ptClient.x!=m_xImgDrag || ptClient.y!=m_yImgDrag ) ){ rcDrag.left = m_xImgDrag; rcDrag.top = m_yImgDrag; rcDrag.right = m_xImgDrag+m_imgDrag->Width; rcDrag.bottom = m_yImgDrag+m_imgDrag->Height; //原拖动图片在框内 if( rcClient.PtInRect( TPoint(rcDrag.left, rcDrag.top) )|| rcClient.PtInRect( TPoint(rcDrag.left, rcDrag.bottom) ) || rcClient.PtInRect( TPoint(rcDrag.right, rcDrag.bottom) ) || rcClient.PtInRect( TPoint(rcDrag.right, rcDrag.top) ) ){ TRect rcLastItem = ItemRect( Items->Count-1 ); if( rcLastItem.bottom <= m_yImgDrag ){ rcDrag.top = rcLastItem.bottom-1; } InvalidateRect( Handle, &rcDrag, false ); } } m_xImgDrag = ptClient.x, m_yImgDrag = ptClient.y; if( m_bDraging ){ rcDrag.left = m_xImgDrag; rcDrag.top = m_yImgDrag; rcDrag.right = m_xImgDrag + m_imgDrag->Width; rcDrag.bottom = m_yImgDrag + m_imgDrag->Height; //拖动图像在框内 if( rcClient.PtInRect( TPoint(rcDrag.left, rcDrag.top) ) || rcClient.PtInRect( TPoint(rcDrag.left, rcDrag.bottom) ) || rcClient.PtInRect( TPoint(rcDrag.right, rcDrag.bottom) ) || rcClient.PtInRect( TPoint(rcDrag.right, rcDrag.top) ) ){ InvalidateRect( Handle, &rcDrag, false ); } } } //--------------------------------------------------------------------------- BOOL ComposeListBoxUnit::TListBox::SetDragingPoint( int X, int Y ) { BOOL bCanDrop = false; int iNewPos = ItemAtPos( TPoint(X,Y), false ); TRect rcItem; if( Items->Count==0 ){ return true; } if( iNewPos>=0 ){ if( iNewPosCount ){ rcItem = ItemRect( iNewPos ); if( Y > rcItem.top+rcItem.Height()/2 ) iNewPos++; } //检查是否可Drop bCanDrop = true; COMPOSESTAGE* pStage = NULL; if( m_bAddStage ){ if( m_iDragingStage>=COMPOSE_ENDING_1 ){ //拖动的是尾奏 int nStageSize = g_lstComposeStages.size(); if( iNewPosiMelodyStage>=COMPOSE_ENDING_1 ){ //曲式中已有尾奏 bCanDrop = false; } } } else if( iNewPos>0 ){ pStage = g_lstComposeStages[iNewPos-1]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ //放置在尾奏后 bCanDrop = false; } } } else{ if( m_iDragingStage==iNewPos || m_iDragingStage==iNewPos-1 ){ iNewPos = -1; } else{ COMPOSESTAGE* pStage = g_lstComposeStages[m_iDragingStage]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ bCanDrop = false; } else if( iNewPos==Items->Count ){ pStage = g_lstComposeStages[iNewPos-1]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ bCanDrop = false; } } } } } //更新Drop提示 if( !bCanDrop ) iNewPos = -1; UpdateDragOverPos( iNewPos ); return bCanDrop; } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::UpdateDragOverPos( int iNewPos ) { int iOldPos = m_iDragOverPos; TRect rcItem; RECT rcUpdate; if( iOldPos!=iNewPos ){ m_iDragOverPos = iNewPos; if( iOldPos!=-1 ){ //清除原提示 if( iOldPosCount ){ rcItem = ItemRect( iOldPos ); rcUpdate.left = rcItem.Left; rcUpdate.right = rcItem.right; rcUpdate.top = rcItem.top; rcUpdate.bottom = rcItem.bottom; InvalidateRect( Handle, &rcUpdate, false ); } if( iOldPos>0 ){ rcItem = ItemRect( iOldPos-1 ); rcUpdate.left = rcItem.Left; rcUpdate.right = rcItem.right; rcUpdate.top = rcItem.top; rcUpdate.bottom = rcItem.bottom; InvalidateRect( Handle, &rcUpdate, false ); } } if( iNewPos!=-1 ){ //显示提示 if( iNewPosCount ){ rcItem = ItemRect( iNewPos ); rcUpdate.left = rcItem.Left; rcUpdate.right = rcItem.right; rcUpdate.top = rcItem.top; rcUpdate.bottom = rcItem.bottom; InvalidateRect( Handle, &rcUpdate, false ); } if( iNewPos>0 ){ rcItem = ItemRect( iNewPos-1 ); rcUpdate.left = rcItem.Left; rcUpdate.right = rcItem.right; rcUpdate.top = rcItem.top; rcUpdate.bottom = rcItem.bottom; InvalidateRect( Handle, &rcUpdate, false ); } } } } //--------------------------------------------------------------------------- int ComposeListBoxUnit::TListBox::SetDropPoint( int X, int Y ) { int iInsertPos = 0; if( Items->Count>0 ){ iInsertPos = ItemAtPos( TPoint(X,Y), false ); if( iInsertPos>=0 ){ if( iInsertPosCount ){ TRect rcItem = ItemRect( iInsertPos ); if( Y > rcItem.top+rcItem.Height()/2 ) iInsertPos++; } //检查是否可Drop COMPOSESTAGE* pStage = NULL; if( m_bAddStage ){ if( m_iDragingStage>=COMPOSE_ENDING_1 ){ //拖动的是尾奏 int nStageSize = g_lstComposeStages.size(); if( iInsertPosiMelodyStage>=COMPOSE_ENDING_1 ){ //曲式中已有尾奏 iInsertPos = -1; } } } else if( iInsertPos>0 ){ pStage = g_lstComposeStages[iInsertPos-1]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ //放置在尾奏后 iInsertPos = -1; } } } else{ if( m_iDragingStage==iInsertPos || m_iDragingStage==iInsertPos-1 ){ iInsertPos = -1; } else{ COMPOSESTAGE* pStage = g_lstComposeStages[m_iDragingStage]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ iInsertPos = -1; } else if( iInsertPos==Items->Count ){ pStage = g_lstComposeStages[iInsertPos-1]; if( pStage->iMelodyStage>=COMPOSE_ENDING_1 ){ iInsertPos = -1; } } } } } else{ iInsertPos = -1; } } if( iInsertPos>=0 ){ if( m_bAddStage ){ InsertStage( m_iDragingStage, iInsertPos ); } else{ MoveStage( m_iDragingStage, iInsertPos ); } } return iInsertPos; } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::InsertStage( int iStage, int iInsertPos ) { UpdateDragOverPos( -1 ); MELODYSTAGE *pMStage = NULL; COMPOSESTAGE* pCStage = NULL; String strText; DWORD dwItemData; if( iStage>=COMPOSE_ENDING_1 ){ int iEnding = iStage - COMPOSE_ENDING_1; strText.printf( L"(%d小节)", g_arrEndingBarNum[iEnding] ); strText = g_strEnding[iEnding] + strText; dwItemData = iStage; } else if( iStage>=COMPOSE_INTRO_1 ){ int iIntro = iStage - COMPOSE_INTRO_1; strText.printf( L"(%d小节)", g_arrIntroBarNum[iIntro] ); strText = g_strIntro[iIntro] + strText; dwItemData = iStage; } else{ pMStage = g_lstMelodyStages[iStage]; strText = String(GetStageName( iStage ).c_str()) + L"段 " + String(g_strStageVar[pMStage->iVar]); dwItemData = MAKELONG(iStage, pMStage->iVar); } Items->InsertObject( iInsertPos, strText, (TObject*)dwItemData ); Selected[iInsertPos] = true; //重设选中位置 } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::AddStage( int iStage ) { int iInsertPos = 0, nStageSize = g_lstComposeStages.size(); if( nStageSize>0 ){ COMPOSESTAGE* pCStage = g_lstComposeStages[nStageSize-1]; if( pCStage->iMelodyStage>=COMPOSE_ENDING_1 ){ //已有尾奏 if( iStage>=COMPOSE_ENDING_1 ){ if( iStage!=pCStage->iMelodyStage ){ //替换尾奏 DeleteStage( nStageSize-1 ); } else{ return; } } iInsertPos = nStageSize - 1; //添加到尾奏前 } else{ iInsertPos = nStageSize; //添加到最后 } } InsertStage( iStage, iInsertPos ); } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::DeleteStage( int iStage ) { if( iStage>=0 ){ Items->Delete( iStage ); } } //--------------------------------------------------------------------------- void ComposeListBoxUnit::TListBox::MoveStage( int iSource, int iDest ) { UpdateDragOverPos( -1 ); if( iSourceMove( iSource,iDest ); //交换位置 Selected[iDest] = true; //重设选中位置 } //---------------------------------------------------------------------------