Files
AccompanyCube/ShowBarsPanelUnit.cpp
2026-06-13 00:10:11 +08:00

596 lines
15 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GlobalUnit.h"
#include "ShowBarsPanelUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//String u_strTable[7] = { L"", L"Ⅱ", L"Ⅲ", L"Ⅳ", L"", L"Ⅵ", L"Ⅶ" };
//String u_strEnglishTable[7] = { L"C", L"D", L"E", L"F", L"G", L"A", L"B" };
short u_Adjust[12][12] = {
0, -1, 0 , -1, 0 , 0 , 1 , 0 , -1 ,0, -1, 0,
-1, 0, -1, 0, 0, 1, 0, -1, 0, -1, 0, 0,
0, -1, 0, 0, 1, 0, -1, 0, -1, 0, 0, -1,
-1, 0, 0, 1, 0, -1, 0, -1, 0, 0, -1, 0,
0, 0 , 1, 0 , -1, 0, -1, 0, 0, -1, 0, -1,
0, 1, 0 , -1, 0 , -1, 0 , 0, -1, 0, -1, 0,
1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, 0,
0 , -1, 0, -1, 0, 0, -1, 0, -1, 0, 0, 1,
-1, 0, -1, 0, 0, -1, 0, -1, 0, 0, 1, 0,
0, -1, 0, 0, -1, 0, -1, 0 , 0 , 1, 0 , -1,
-1, 0, 0, -1, 0, -1, 0, 0, 1, 0, -1, 0,
0, 0 , -1, 0 , -1, 0, 0, 1, 0, -1, 0 , -1
};
BYTE u_MainChord[12][12] ={
0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6,
1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 0,
1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 1,
2, 2, 3, 3, 4, 5, 5, 6, 6, 0, 1, 1,
2, 3, 3, 4, 5, 5, 6, 6, 0, 1, 1, 2,
3, 3, 4, 5, 5, 6, 6, 0, 1, 1, 2, 2,
3, 4, 5, 5, 6, 6, 0, 1, 1, 2, 2, 3,
4, 5, 5, 6, 6, 0, 1, 1, 2, 2, 3, 3,
5, 5, 6, 6, 0, 1, 1, 2, 2, 3, 3, 4,
5, 6, 6, 0, 1, 1, 2, 2, 3, 3, 4, 5,
6, 6, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5,
6, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6
};
//---------------------------------------------------------------------------
__fastcall TShowBarsPanel::TShowBarsPanel(TComponent* AOwner)
: Vcl::Extctrls::TPanel(AOwner)
{
m_nBarWidth = m_nDataWidth = POINTS_PER_BAR;
m_nBarHeight = 55;
m_nDataHeight = 30;
m_nLeftOriBound = m_nLeftBound = 15;
m_nRightBound = 20;
m_nTopBound = 1;
// m_sFont7 = int(7 * 96.0 / g_yDpi + 0.5),
// m_sFont8 = int(8 * 96.0 / g_yDpi + 0.5),
// m_sFont9 = int(9 * 96.0 / g_yDpi + 0.5),
// m_sFont14 = int(14 * 96.0 / g_yDpi + 0.5),
// m_sFont16 = int(16 * 96.0 / g_yDpi + 0.5);
m_bPlaying = false;
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::CreateWnd(void)
{
Vcl::Extctrls::TPanel::CreateWnd();
if( !ParentBackground ){
m_sbVert = new TSkinScrollBar(this);
m_sbVert->Parent = this;
m_sbVert->m_pWndCtrl = this;
m_sbVert->Visible = false;
m_sbVert->Left = ClientWidth - m_sbVert->Width - 1;
m_sbVert->Top = 1;
m_sbVert->Height = ClientHeight-2;
m_imgBackground = new TBitmap();
m_imgBackground->LoadFromResourceName(int(HInstance), L"CustomPanelBackground");
m_imgBarTitle = new TBitmap();
m_imgBarTitle->LoadFromResourceName(int(HInstance), L"BarTitle");
m_nTitleHeight = m_imgBarTitle->Height;
m_nBarDrawHeight = m_nTitleHeight + m_nDataHeight;
m_nRowGapHeight = m_nBarHeight - m_nBarDrawHeight;
Canvas->Font->Name = "黑体";
Canvas->Font->Size = g_szFont8;
Canvas->Font->Color = RGB(60,43,23);
InitialVars(0);
}
else{
m_imgBackground = NULL;
m_imgBarTitle = NULL;
}
}
//---------------------------------------------------------------------------
__fastcall TShowBarsPanel::~TShowBarsPanel()
{
if( m_imgBackground )
delete m_imgBackground;
if( m_imgBarTitle )
delete m_imgBarTitle;
if( m_sbVert )
delete m_sbVert;
}
//---------------------------------------------------------------------------
void TShowBarsPanel::InitialVars(int nBarNum)
{
if( m_nColumnNum==0 )
CalcViewArea();
m_nBeginShowRow = 0;
m_nBarNum = nBarNum;
m_nRowNum = m_nBarNum / m_nColumnNum;
if( m_nBarNum % m_nColumnNum>0 ){
m_nRowNum++;
}
if( m_nRowNum>m_nRowShow ){
if( !m_sbVert->Visible ){
m_sbVert->Visible = true;
}
m_sbVert->SetRange( 0, m_nRowNum-1 );
m_sbVert->SetPageSize( m_nRowShow );
m_sbVert->SetPosition( 0 );
}
else {
m_sbVert->Visible = false;
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
}
Invalidate();
}
//---------------------------------------------------------------------------
void TShowBarsPanel::SetPlayPoint( int iBar, int iPoint )
{
int iRow, iCol;
TRect rectOld(0,0,0,0), rectNew(0,0,0,0);
iRow = m_iPlayBar / m_nColumnNum - m_nBeginShowRow;
iCol = m_iPlayBar % m_nColumnNum;
if( iRow>=0 ){
rectOld.left = iCol * m_nBarWidth + m_iPlayPoint + m_nLeftBound;
rectOld.right = rectOld.left + 1;
rectOld.top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight;
rectOld.bottom = rectOld.top + m_nBarDrawHeight;
}
m_iPlayBar = iBar;
m_iPlayPoint = iPoint;
iRow = m_iPlayBar / m_nColumnNum - m_nBeginShowRow;
iCol = m_iPlayBar % m_nColumnNum;
rectNew.left = iCol * m_nBarWidth + m_iPlayPoint + m_nLeftBound;
rectNew.right = rectNew.left + 1;
rectNew.top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight;
rectNew.bottom = rectNew.top + m_nBarDrawHeight;
if( iRow<0 ){
ScrollView( iRow + m_nBeginShowRow );
}
else if( iRow>(m_nRowShow-1) ){
int nRowScroll = min( m_nRowShow+m_nBeginShowRow-1, m_nRowNum-iRow ); // 显示到第2行
ScrollView( nRowScroll );
}
else{
InvalidateRect( Handle, &rectOld, false );
InvalidateRect( Handle, &rectNew, false );
}
}
//---------------------------------------------------------------------------
void TShowBarsPanel::InvalidateBar( int iBar, int iBeginPoint, int iEndPoint, int iArea )
{
int iRow, iCol;
TRect rectDraw;
iRow = iBar / m_nColumnNum - m_nBeginShowRow;
iCol = iBar % m_nColumnNum;
rectDraw.left = iCol * m_nBarWidth + m_nLeftBound + iBeginPoint;
rectDraw.right = iCol * m_nBarWidth + m_nLeftBound + iEndPoint+1;
int nBarTop = iRow * m_nBarHeight + m_nTopBound;
rectDraw.bottom = nBarTop + m_nRowGapHeight;
rectDraw.top = rectDraw.bottom + m_nTitleHeight;
if( iArea & BAR_HEADER ){
rectDraw.top = nBarTop;
}
else if( iArea & BAR_TITLE ){
rectDraw.top = nBarTop + m_nRowGapHeight;
}
if( iArea & BAR_DATA ){
rectDraw.bottom = nBarTop + m_nBarHeight;
}
else if( iArea & BAR_TITLE ){
rectDraw.bottom = nBarTop + m_nRowGapHeight + m_nTitleHeight;
}
InvalidateRect( Handle, &rectDraw, false );
}
//---------------------------------------------------------------------------
void TShowBarsPanel::ScrollView( int nPos, bool bRedraw )
{
if( m_nBeginShowRow!=nPos ){
m_nBeginShowRow = nPos;
BarPosChanged();
Invalidate();
}
if( bRedraw ){
m_sbVert->SetPosition( nPos );
}
}
//---------------------------------------------------------------------------
void TShowBarsPanel::CalcViewArea()
{
if( ClientWidth>0 && ClientHeight>0 ){
m_nColumnNum = (ClientWidth - m_nLeftOriBound - m_nRightBound) / m_nBarWidth;
m_nRowShow = (ClientHeight - m_nTopBound - 1) / m_nBarHeight;
m_nLeftBound = (( ClientWidth - m_nRightBound ) % m_nBarWidth)/2 ;
}
}
//---------------------------------------------------------------------------
void TShowBarsPanel::DrawBars()
{
int rowTop = m_nTopBound, nBarCount = 0;
Canvas->Pen->Color = COLOR_BORDER;
if( m_nBeginShowRow>0 ){
nBarCount = m_nBeginShowRow * m_nColumnNum;
}
for( int i=m_nBeginShowRow; i<m_nRowNum && i<m_nBeginShowRow+m_nRowShow; i++ ){
int right, barTop = rowTop + m_nRowGapHeight;
if( m_nBarNum - nBarCount >= m_nColumnNum ){ //显示整满行
right = m_nColumnNum * m_nBarWidth + m_nLeftBound;
}
else{ //显示非整行
right = (m_nBarNum - nBarCount) * m_nBarWidth + m_nLeftBound;
}
//绘制第一个小节线
Canvas->MoveTo( m_nLeftBound, barTop );
Canvas->LineTo( m_nLeftBound, barTop + m_nBarDrawHeight );
for( int j=0; j<m_nColumnNum && nBarCount<m_nBarNum; j++ ){
String strText;
int iBarLeft = j*m_nBarWidth + m_nLeftBound;
//绘制小节栏
Canvas->Draw( iBarLeft+1, barTop, m_imgBarTitle );
//绘制小节序号
strText = IntToStr(nBarCount+1);
SetBarTitle( nBarCount, strText );
Canvas->Brush->Style = bsClear;
Canvas->TextOut( iBarLeft + 8, barTop + 1, strText );
DrawBarBkgnd( nBarCount, iBarLeft+1, barTop+m_nTitleHeight );
//绘制小节线
Canvas->MoveTo( iBarLeft + m_nBarWidth, barTop );
Canvas->LineTo( iBarLeft + m_nBarWidth, barTop + m_nBarDrawHeight );
DrawBarContext( nBarCount, iBarLeft, barTop+m_nTitleHeight );
//绘制播放线
if( m_iPlayBar==nBarCount ){
TColor clrOld = Canvas->Pen->Color;
Canvas->Pen->Color = g_clrPlayLine;
Canvas->MoveTo( iBarLeft + m_iPlayPoint, barTop );
Canvas->LineTo( iBarLeft + m_iPlayPoint, barTop + m_nBarDrawHeight );
Canvas->Pen->Color = clrOld;
}
DrawBarOperation( nBarCount, iBarLeft, rowTop );
nBarCount++;
}
// 绘制音频栏下框
Canvas->MoveTo( m_nLeftBound, rowTop + m_nBarHeight );
Canvas->LineTo( right+1, rowTop + m_nBarHeight );
rowTop += m_nBarHeight;
}
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::Paint()
{
if( !ParentBackground ){
DrawBars();
}
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::WMEraseBkgnd(Winapi::Messages::TWMEraseBkgnd &Message)
{
if( m_imgBackground ){
TCanvas* tempCanvas = new TCanvas;
tempCanvas->Handle = Message.DC;
//绘制底图
int cx = ClientWidth/m_imgBackground->Width + 1;
int cy = ClientHeight/m_imgBackground->Height + 1;
for (int i=0; i<cx; i++)
for (int j=0; j<cy; j++)
tempCanvas->Draw(i*m_imgBackground->Width,
j*m_imgBackground->Height,
m_imgBackground);
//绘制外边框
tempCanvas->Brush->Color = COLOR_BORDER;
TRect rect = GetClientRect();
tempCanvas->FrameRect(rect);
delete tempCanvas;
Message.Result = true;
}
else{
DefaultHandler( &Message );
}
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::WMSize(Winapi::Messages::TWMSize &Message)
{
DefaultHandler( &Message );
if( ParentBackground )
return;
int nOriBeginShowRow = m_nBeginShowRow,
nOriRowNum = m_nRowNum,
nOriColumnNum = m_nColumnNum;
int iFirstShowBar = 0;
if( m_nBarNum>0 && m_nBeginShowRow>0 ){ //保存原显示的第一个小节
iFirstShowBar = m_nBeginShowRow * m_nColumnNum;
}
CalcViewArea();
if( m_sbVert ){
m_sbVert->Left = ClientWidth - m_sbVert->Width - 1;
m_sbVert->Top = 1;
m_sbVert->Height = ClientHeight - 2;
}
if( m_iPlayBar>=0 && m_bPlaying ){
iFirstShowBar = m_iPlayBar - m_nColumnNum; //显示到第2行
}
if( iFirstShowBar<0 ){
iFirstShowBar = 0;
}
if( m_nBarNum>0 ){
m_nRowNum = m_nBarNum / m_nColumnNum + 1;
if( m_nBarNum % m_nColumnNum==0 ){
m_nRowNum--;
}
if( m_nRowNum>m_nRowShow ){ //显示滚动条
m_sbVert->Visible = true;
m_sbVert->SetRange( 0, m_nRowNum-1 );
m_sbVert->SetPageSize( m_nRowShow );
m_sbVert->SetPosition( 0 );
int iRowScroll = 0;
if( iFirstShowBar>0 ){
iRowScroll = min( iFirstShowBar / m_nColumnNum, m_nRowNum-m_nRowShow );
if( iRowScroll<0 ){
iRowScroll = 0;
}
}
ScrollView( iRowScroll );
}
else{
m_nBeginShowRow = 0;
m_sbVert->Visible = false;
}
}
if( m_nRowNum!=nOriRowNum || m_nColumnNum!=nOriRowNum || m_nBeginShowRow!=nOriBeginShowRow ){
BarPosChanged();
Invalidate();
}
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::WMVScroll(Winapi::Messages::TWMScroll &Message)
{
int minpos, maxpos, page, curpos;
m_sbVert->GetScrollRange(&minpos, &maxpos);
page = m_sbVert->GetPageSize();
// Get the current position of scroll box.
curpos = m_sbVert->GetScrollPos();
// Determine the new position of scroll box.
switch (Message.ScrollCode)
{
case SB_TOP: // Scroll to far top.
curpos = minpos;
break;
case SB_BOTTOM: // Scroll to far bottom.
curpos = maxpos-page+1;
break;
case SB_ENDSCROLL: // End scroll.
break;
case SB_LINEUP: // Scroll left.
if (curpos > minpos)
curpos--;
break;
case SB_LINEDOWN: // Scroll right.
if (curpos < maxpos-page+1)
curpos++;
break;
case SB_PAGEUP: // Scroll one page left.
if (curpos > minpos)
curpos = max(minpos, curpos-page);
break;
case SB_PAGEDOWN: // Scroll one page right.
if( curpos<maxpos )
curpos = min(maxpos-page+1, curpos+page);
break;
case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
curpos = Message.Pos; // of the scroll box at the end of the drag operation.
break;
case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the
curpos = Message.Pos; // position that the scroll box has been dragged to.
break;
}
// Set the new position of the thumb (scroll box).
if( Message.ScrollBar!=m_sbVert->Handle )
m_sbVert->SetPosition(curpos);
ScrollView(curpos, FALSE);
Message.Result = true;
}
//---------------------------------------------------------------------------
void __fastcall TShowBarsPanel::WMMouseWheel(TWMMouseWheel &Message)
{
if( m_sbVert->Visible ){
UINT nSBCode;
if( Message.WheelDelta>0 ) nSBCode = SB_LINEUP;
else nSBCode = SB_LINEDOWN;
Perform( WM_VSCROLL, MAKELONG(nSBCode,0), NULL );
}
}
//---------------------------------------------------------------------------
DWORD TShowBarsPanel::HitTest( int X, int Y, int& iHitType, bool bAbsorb, bool bIgnoreBound )
{
if( bIgnoreBound ){
if( X <= m_nLeftBound )
X = m_nLeftBound + 1;
if( X >= m_nColumnNum*m_nBarWidth+m_nLeftBound )
X = m_nColumnNum*m_nBarWidth+m_nLeftBound - 1;
if( Y <= m_nTopBound )
Y = m_nTopBound + 1;
if( Y >= (m_nRowNum-m_nBeginShowRow)*m_nBarHeight+m_nTopBound )
Y = (m_nRowNum-m_nBeginShowRow)*m_nBarHeight+m_nTopBound - 1;
}
else if( X <= m_nLeftBound || X >= m_nColumnNum*m_nBarWidth+m_nLeftBound ||
Y <= m_nTopBound || Y >= (m_nRowNum-m_nBeginShowRow)*m_nBarHeight+m_nTopBound ){
iHitType = -1;
return -1;
}
int iRow = ( Y - m_nTopBound ) / m_nBarHeight + m_nBeginShowRow;
int iCol = ( X - m_nLeftBound ) / m_nBarWidth;
int iBar = iRow * m_nColumnNum + iCol;
int deltaY = ( Y - m_nTopBound ) % m_nBarHeight;
int deltaX = ( X - m_nLeftBound ) % m_nBarWidth;
int nAbsorbWidth = bAbsorb ? CELL_ABSORB_WIDTH : 0;
if( iBar<m_nBarNum && iBar>=0 ){
if( deltaY<m_nRowGapHeight ){
iHitType = 0;
}
else if( deltaY<m_nBarHeight-m_nDataHeight ){
iHitType = 1;
}
else{
iHitType = 2;
}
if( m_nBarWidth-deltaX<nAbsorbWidth && iBar<m_nBarNum-1 ){ // 小节线左侧
return MAKELONG( iBar+1, 0 );
}
else if( deltaX<nAbsorbWidth ){ // 小节线右侧
return MAKELONG( iBar, 0 );
}
else{
return MAKELONG( iBar, deltaX );
}
}
else if( bIgnoreBound && iBar>=m_nBarNum ){
iHitType = 2;
return MAKELONG( m_nBarNum-1, deltaX );
}
else{
iHitType = -1;
}
return -1;
}
//-----------------------------------------------------------------------------
void __fastcall TShowBarsPanel::DrawChord( TRect& rcDraw, int iChord )
{
int iMainKey, iAjustKey, iType; //调级数、升降、大小
GetChordKey( iChord, iMainKey, iAjustKey, iType );
UniDrawChord(Canvas, rcDraw, iMainKey, iAjustKey, iType);
}
//-----------------------------------------------------------------------------
void TShowBarsPanel::GetChordKey( int iChord, int& iMainKey, int& iAjustKey, int& iType )
{
int iKey = ( iChord / CHORD_TYPE_NUM ) % KEY_NUM;
iType = iChord % CHORD_TYPE_NUM;
if( g_iShowType ){
iMainKey = u_MainChord[g_iMelodyKey][iKey];
iAjustKey = u_Adjust[g_iMelodyKey][iKey];
}
else{
iAjustKey = 0;
switch( iKey ){
case 0:
iMainKey = 0;
break;
case 1:
iAjustKey = -1;
case 2:
iMainKey = 1;
break;
case 3:
iAjustKey = -1;
case 4:
iMainKey = 2;
break;
case 6:
iAjustKey = 1;
case 5:
iMainKey = 3;
break;
case 7:
iMainKey = 4;
break;
case 8:
iAjustKey = -1;
case 9:
iMainKey = 5;
break;
case 10:
iAjustKey = -1;
case 11:
iMainKey = 6;
break;
}
}
}
//-----------------------------------------------------------------------------