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

7457 lines
199 KiB
C++

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GlobalUnit.h"
#include "MessageDef.h"
#include "ContentPanelUnit.h"
#include "UseStylePanel.h"
#include "ChordPanel.h"
#include "TrackPanel.h"
#include "MidiTrack.h"
#include "SwitchTextureForm.h"
#include "SwitchProgFormUnit.h"
#include "AudioFxFormUnit.h"
#include "VSTPluginFormUnit.h"
#include "ProgressFormUnit.h"
#include "Undo.h"
//#define TRK_HDR_WIDTH 120
#define DOTIP_WIDTH 10
#define CUR_WIDTH 11
#define CUR_HEIGHT 8
#define ABS_POI_PLAY 6
#define ABS_POI_WAVE 4
#define SM_TOP 15
#define SM_SIZE 14
#define SOLO_LEFT -19//101
#define MUTE_LEFT -34//86
#define HOVER_MUTE 0x10000
#define HOVER_SOLO 0x20000
#define TRACK_M_HOVER 0x10
#define TRACK_S_HOVER 0x20
#define IDM_TRKSHOW 0x100
#define IDM_TRKAUD 0x200
#define IDM_TRKMID 0x300
//---------------------------------------------------------------------------
#pragma package(smart_init)
extern TImage * w_imgDrag; //拖动图片
extern bool w_bDraging;
extern int w_iDragMode, //拖动模式
w_xImgDrag, //透明图片位置
w_yImgDrag,
w_xOldDrag, //透明图片上次位置
w_yOldDrag,
w_xOffDrag, //图片左上角与鼠标距离
w_yOffDrag;
extern TCursor crBrush, crBrushAdd, crBrushNo;
const COLORREF clrBackground = RGB(52,56,62), //面板背景
clrBackboard = RGB( 29,31,35 ), //面板边框
clrBarTitle[17] = { RGB(22,24,27),RGB(64,69,76),RGB(44,48,55),
RGB(42,46,53),RGB(41,44,51),RGB(39,42,48),RGB(37,40,46),
RGB(35,38,43),RGB(33,35,40),RGB(31,32,37),RGB(28,30,34),
RGB(26,28,32),RGB(24,25,29),RGB(23,24,26),RGB(21,22,24),
RGB(19,20,22),RGB(22,24,27) }, //小节栏渐变色
clrBarTitleSel[17] = { RGB(152,152,152),RGB(145,144,144),RGB(135,134,134),
RGB(125,123,123),RGB(112,111,111),RGB(99,98,98),RGB(86,84,84),
RGB(73,71,71),RGB(62,60,60),RGB(50,49,49),RGB(39,37,38),
RGB(32,29,30),RGB(30,28,29),RGB(29,27,28),RGB(29,26,27),
RGB(28,25,26),RGB(27,24,25) }, //高亮小节栏渐变色
clrFocus = RGB(247,246,246),
clrFocback = RGB(225,236,255),
clrSelText = RGB(201,214,229),
clrTitleFont = RGB(156,170,189),
clrHeadFont = RGB(52,56,62),
clrSelCell = RGB(83,109,165), //选中和弦
clrPlayLine = RGB(255,0,0), // 播放标示线
clrInsertLine = RGB(228,123,249),//255,0,255), //音频插入线
clrRecordMask = RGB(226,225,225), //屏蔽录音颜色
clrEffectBk = RGB(247,246,246), //音效区域背景
clrWaveBk[3] = {RGB(186,185,185), RGB(216,215,215), RGB(226,225,225)},
clrWave[2] = {RGB(15,229,226), RGB(75,148,147)},
clrSMState[4] = {RGB(186,185,185), RGB(216,215,215),
RGB(248,235,159), RGB(250,244,213)};
//---------------------------------------------------------------------------
__fastcall TContentPanel::TContentPanel(TComponent* AOwner)
: Vcl::Extctrls::TPanel(AOwner)
{
Visible = false;
DoubleBuffered = true;
m_rgnClip = NULL;
m_pStylePanel = NULL;
m_pItem = NULL;
m_sbVert = m_sbHoriz = NULL;
m_imgPlayCursor = m_imgMidiIcon = m_imgWaveIcon = NULL;
m_pTimer = NULL;
m_PopupMenu = NULL;
m_bPlaying = m_bDragReady = m_bDraging = m_bBrush = false;
m_iMode = VIEW_INIT;
m_bVertical = true;
m_nBarWidth = m_nDataWidth = POINTS_PER_BAR;
m_nRowGapHeight = 14;
m_nTitleHeight = 17;
m_nChordHeight = 27;
m_nTrackHeight = 31;
m_nLeftOriBound = m_nLeftBound = 4;//20;
m_nRightBound = 1;//15;
m_nTopBound = 1;
m_nBottomBound = 1;
m_nTrkHdrWidth = MIN_HDR_WIDTH;
m_nBarDrawHeight = m_nTitleHeight + m_nTrackHeight;
m_nBarHeight = m_nRowGapHeight + m_nBarDrawHeight;
m_nChordTxtHeight = 18;
m_iPlayBar = m_iPlayPoint = 0;
m_iDropBar = -1;
m_iCopyAudio = m_iDragAudio = -1;
m_iSelTrackBar = m_iSelTrackPoint = -1;
m_iSelBarStart = m_iSelBarEnd = -1;
m_iSelCellStart = m_iSelCellEnd = -1;
m_iSelPointStart = m_iSelPointEnd = -1;
m_iMouseDownBar = m_iMouseDownPoint = -1;
m_iCopyBarStart = m_iCopyBarEnd = -1;
m_iCopyCellStart = m_iCopyCellEnd = -1;
m_iCopyPointStart = m_iCopyPointEnd = -1;
m_iSelTrack = -1;
m_bCut = false;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::CreateWnd(void)
{
Vcl::Extctrls::TPanel::CreateWnd();
if( m_ApplicationEvents==NULL ){
m_ApplicationEvents = new TApplicationEvents(NULL);
m_ApplicationEvents->OnMessage = DoHandleMessage;
}
OnDblClick = DoubleClick;
if( !m_imgPlayCursor ){
m_imgPlayCursor = new TBitmap();
m_imgPlayCursor->LoadFromResourceName(int(HInstance), L"imgPlayCursor");
}
if( !m_imgMidiIcon ){
m_imgMidiIcon = new TBitmap();
m_imgMidiIcon->LoadFromResourceName(int(HInstance), L"imgMidiIcon");
}
if( !m_imgWaveIcon ){
m_imgWaveIcon = new TBitmap();
m_imgWaveIcon->LoadFromResourceName(int(HInstance), L"imgWaveIcon");
}
m_pngChordUp = new TPngImage();
m_pngChordUp->LoadFromResourceName(int(HInstance), "chordUp");
m_pngChordDown = new TPngImage();
m_pngChordDown->LoadFromResourceName(int(HInstance), "chordDown");
m_pngChord2 = new TPngImage();
m_pngChord2->LoadFromResourceName(int(HInstance), "chord2");
m_pngChord4 = new TPngImage();
m_pngChord4->LoadFromResourceName(int(HInstance), "chord4");
m_pngChord6 = new TPngImage();
m_pngChord6->LoadFromResourceName(int(HInstance), "chord6");
m_pngChord7 = new TPngImage();
m_pngChord7->LoadFromResourceName(int(HInstance), "chord7");
m_pngChordI = new TPngImage();
m_pngChordI->LoadFromResourceName(int(HInstance), "chordI");
m_pngChordV = new TPngImage();
m_pngChordV->LoadFromResourceName(int(HInstance), "chordV");
m_pngChordMaj = new TPngImage();
m_pngChordMaj->LoadFromResourceName(int(HInstance), "chordMaj");
m_pngChordMin = new TPngImage();
m_pngChordMin->LoadFromResourceName(int(HInstance), "chordMin");
m_pngChordSus = new TPngImage();
m_pngChordSus->LoadFromResourceName(int(HInstance), "chordSus");
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_sbHoriz = new TSkinScrollBar(this, false);
m_sbHoriz->Parent = this;
m_sbHoriz->m_pWndCtrl = this;
m_sbHoriz->Visible = false;
m_sbHoriz->Left = m_nTrkHdrWidth;
m_sbHoriz->Top = ClientHeight - m_sbHoriz->Height - 1;
m_sbHoriz->Width = ClientWidth - m_nTrkHdrWidth - 1;
//录音提示
m_iBeatHint = -1;
for( int i=0; i<4; i++ ){
m_imgBeatHint[i] = new TPngImage();
String strHintName = "imgBeatHint" + IntToStr( i+1 );
m_imgBeatHint[i]->LoadFromResourceName(int(HInstance), strHintName );
}
m_wBeatHint = m_imgBeatHint[0]->Width;
m_hBeatHint = m_imgBeatHint[0]->Height;
m_lBeatHint = (ClientWidth - m_wBeatHint) / 2;
m_tBeatHint = (ClientHeight - m_hBeatHint) / 2;
Canvas->Font->Name = "SimHei";
Canvas->Font->Size = g_szFont8;
InitialVars();
g_Midi.InitNoteColor();
}
//---------------------------------------------------------------------------
__fastcall TContentPanel::~TContentPanel()
{
if( m_ApplicationEvents )
delete m_ApplicationEvents;
if( m_rgnClip )
::DeleteObject(m_rgnClip);
if( m_sbVert )
delete m_sbVert;
if( m_sbHoriz )
delete m_sbHoriz;
// if( m_PopupMenu )
// delete m_PopupMenu;
if( m_imgPlayCursor )
delete m_imgPlayCursor;
if( m_imgMidiIcon )
delete m_imgMidiIcon;
if( m_imgWaveIcon )
delete m_imgWaveIcon;
for( int i=0; i<4; i++ ){
if( m_imgBeatHint[i] )
delete m_imgBeatHint[i];
}
if( m_pngChordUp )
delete m_pngChordUp;
if( m_pngChordDown )
delete m_pngChordDown;
if( m_pngChord2 )
delete m_pngChord2;
if( m_pngChord4 )
delete m_pngChord4;
if( m_pngChord6 )
delete m_pngChord6;
if( m_pngChord7 )
delete m_pngChord7;
if( m_pngChordI )
delete m_pngChordI;
if( m_pngChordV )
delete m_pngChordV;
if( m_pngChordMaj )
delete m_pngChordMaj;
if( m_pngChordMin )
delete m_pngChordMin;
if( m_pngChordSus )
delete m_pngChordSus;
ClearShowTracks();
}
//---------------------------------------------------------------------------
void TContentPanel::ClearShowTracks()
{
SelectTrack( -1, -1, -1 );
while( !m_aTracks.empty() ){
delete m_aTracks.back();
m_aTracks.pop_back();
}
}
//---------------------------------------------------------------------------
void TContentPanel::SetMode( int iMode )
{
if( m_iMode!=iMode ){
m_iMode = iMode;
m_iDropBar = -1;
m_iCopyAudio = m_iDragAudio = -1;
m_iSelTrackBar = m_iSelTrackPoint = -1;
SelectRange( -1, -1, -1, -1 );
SelectCopyPos( -1, -1, -1, -1 );
SelectCells( -1, -1, -1, -1 );
SelectCopyCells( -1, -1, -1, -1 );
m_iSelTrack = g_iSelAudio = iMode==MODE_INIT ? 0 : -1;
g_iSelMidiTrack = -1;
((TChordPanel*)m_pChordPanel)->EnableChordModify( false, -1, -1, -1 );
((TUseStylePanel*)m_pStylePanel)->SetSelectStage( -1 );
if( iMode==MODE_INIT && !m_bVertical )
SetScrollMode( true );
else
InvalidateRgn( Handle, NULL, false );
}
}
//---------------------------------------------------------------------------
void TContentPanel::SetScrollMode( bool bVertical )
{
if( m_bVertical!=bVertical ){
m_bVertical = bVertical;
m_iDropBar = -1;
m_iCopyAudio = m_iDragAudio = -1;
m_iSelTrackBar = m_iSelTrackPoint = -1;
SelectRange( -1, -1, -1, -1 );
SelectCopyPos( -1, -1, -1, -1 );
SelectCells( -1, -1, -1, -1 );
SelectCopyCells( -1, -1, -1, -1 );
g_iSelAudio = g_iSelMidiTrack = m_iSelTrack = -1;
((TChordPanel*)m_pChordPanel)->EnableChordModify( false, -1, -1, -1 );
((TUseStylePanel*)m_pStylePanel)->SetSelectStage( -1 );
((TTrackPanel*)m_pTrackPanel)->SetSelTrack( -1, -1 );
ClearShowTracks();
int nBarDrawHeight = m_nTitleHeight;
if( g_lstOpusStages.size()>0 ){
nBarDrawHeight += m_nChordHeight;
}
if( m_iMode==VIEW_INIT ){
TShowTrack* pTrk = new TShowTrack( ST_AUDIO, 0, 0 );
m_aTracks.push_back( pTrk );
}
else{
if( !m_bVertical ){
for( int i=0; i<g_aMidiTracks.size(); i++ ){
if( !g_aMidiTracks[i]->IsHide() ){
m_aTracks.push_back( new TShowTrack( ST_MIDI, i, g_aMidiTracks[i] ) );
}
}
}
for( int i=0; i<g_aAudioTracks.size(); i++ ){
if( !g_aAudioTracks[i]->IsHide() && !g_aAudioTracks[i]->lstBars.empty() ){
m_aTracks.push_back( new TShowTrack( ST_AUDIO, i, g_aAudioTracks[i] ) );
}
}
}
nBarDrawHeight += m_nTrackHeight * m_aTracks.size();
if( nBarDrawHeight!=m_nBarDrawHeight ){
m_nBarDrawHeight = nBarDrawHeight;
m_nBarHeight = m_nRowGapHeight + m_nBarDrawHeight;
}
CalcViewArea();
if( bVertical ){
if( m_nRowNum>m_nRowShow ){
m_sbVert->SetRange( 0, m_nRowNum-1 );
m_sbVert->SetPageSize( m_nRowShow );
m_sbVert->SetPosition( 0 );
/* int iRowScroll = 0;
if( m_iBeginShowBar>0 ){
iRowScroll = min( m_iBeginShowBar / m_nColumnNum, m_nRowNum-m_nRowShow );
if( iRowScroll<0 ){
iRowScroll = 0;
}
}
ScrollView( iRowScroll );
*/
}
else{
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
}
if( m_sbHoriz ){
m_sbHoriz->SetRange( 0, 0, false );
m_sbHoriz->SetPageSize( 0, false );
m_sbHoriz->SetPosition( 0, false );
}
m_iBeginShowBar = 0;
m_iBeginShowTrack = 0;
m_nTrackShow = m_aTracks.size();
}
else{
GenerateCompose();
int nRange = m_nBarNum;
int nDrawWidth = ClientWidth - m_nLeftOriBound - m_nRightBound;
if( nDrawWidth % m_nBarWidth > 0 )
nRange++;
if( nRange>m_nColumnNum ){
m_sbHoriz->SetRange( 0, nRange - 1 );
m_sbHoriz->SetPageSize( m_nColumnNum );
m_sbHoriz->SetPosition( 0 );
/* if( m_iBeginShowBar>0 ){
ScrollView( m_iBeginShowBar, false );
}
*/
}
else{
m_sbHoriz->SetRange( 0, 0, false );
m_sbHoriz->SetPageSize( 0, false );
m_sbHoriz->SetPosition( 0, false );
}
nRange = m_aTracks.size();
int nDrawHeight = ClientHeight - m_nTopBound - m_nBottomBound
- m_nRowGapHeight - m_nTitleHeight - m_nChordHeight;
if( nDrawHeight % m_nTrackHeight > 0 )
nRange++;
if( nRange > m_nTrackShow ){
m_sbVert->SetRange( 0, nRange-1 );
m_sbVert->SetPageSize( m_nTrackShow );
m_sbVert->SetPosition( 0 );
}
else{
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
}
m_nRowNum = m_nRowShow = 1;
m_iBeginShowRow = 0;
}
InvalidateRgn( Handle, NULL, true );
}
ShowPlayPoint();
}
//---------------------------------------------------------------------------
void TContentPanel::InitialVars( bool bClear )
{
ClearShowTracks();
int nBarNum = 0;
if( bClear ){
m_iDropBar = -1;
m_iCopyAudio = m_iDragAudio = -1;
m_iSelBarStart = m_iSelBarEnd = -1;
m_iSelCellStart = m_iSelCellEnd = -1;
m_iSelPointStart = m_iSelPointEnd = -1;
m_iCopyBarStart = m_iCopyBarEnd = -1;
m_iCopyCellStart = m_iCopyCellEnd = -1;
m_iCopyPointStart = m_iCopyPointEnd = -1;
m_iSelTrackBar = m_iSelTrackPoint = -1;
m_iPlayBar = m_iPlayPoint = 0;
m_bCut = false;
m_iBeginShowBar = m_iBeginShowTrack = 0;
}
else{
int nBarDrawHeight = m_nTitleHeight;
if( g_lstOpusStages.size()>0 ){
nBarDrawHeight += m_nChordHeight;
nBarNum = GetBarCount();
}
if( m_iMode==VIEW_INIT && nBarNum==0 ){
TShowTrack* pTrk = new TShowTrack( ST_AUDIO, 0, 0 );
m_aTracks.push_back( pTrk );
}
else{
if( !m_bVertical ){
for( int i=0; i<g_aMidiTracks.size(); i++ ){
if( !g_aMidiTracks[i]->IsHide() ){
m_aTracks.push_back( new TShowTrack( ST_MIDI, i, g_aMidiTracks[i] ) );
}
}
}
for( int i=0; i<g_aAudioTracks.size(); i++ ){
if( !g_aAudioTracks[i]->IsHide() && !g_aAudioTracks[i]->lstBars.empty() ){
m_aTracks.push_back( new TShowTrack( ST_AUDIO, i, g_aAudioTracks[i] ) );
}
}
}
nBarDrawHeight += m_nTrackHeight * m_aTracks.size();
if( nBarDrawHeight!=m_nBarDrawHeight ){
m_nBarDrawHeight = nBarDrawHeight;
m_nBarHeight = m_nRowGapHeight + m_nBarDrawHeight;
}
}
m_nBarNum = nBarNum;
CalcViewArea();
m_nChordTxtWidth = m_nDataWidth/g_nChordNumPerBar;
// m_iBeginShowRow = 0;
// m_iBeginShowTrack = 0;
SetScrollView( m_iBeginShowBar );
InvalidateRgn( Handle, NULL, false );
}
//---------------------------------------------------------------------------
int TContentPanel::GetShowTrackId( int type, int index )
{
for( int i=0; i<m_aTracks.size(); i++ ){
if( m_aTracks[i]->type==type && m_aTracks[i]->index==index )
return i+1;
}
return 0;
}
//---------------------------------------------------------------------------
bool TContentPanel::SetScrollView( int iFirstShowBar )
{
bool bScroll = false;
m_iBeginShowBar = iFirstShowBar;
m_iBeginShowTrack = 0;
if( m_bVertical ){
if( m_nRowNum>m_nRowShow ){ //显示滚动条
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;
}
}
if( iRowScroll!=m_iBeginShowRow )
bScroll = true;
ScrollView( iRowScroll );
}
else {
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
if( m_iBeginShowRow!=0 ){
m_iBeginShowRow = 0;
m_iBeginShowBar = 0;
bScroll = true;
InvalidateRgn( Handle, NULL, false );
}
}
}
else{
int nRange = m_nBarNum;
int nDrawWidth = ClientWidth - m_nLeftOriBound - m_nRightBound;
if( nDrawWidth % m_nBarWidth > 0 )
nRange++;
if( nRange>m_nColumnNum ){ //显示滚动条
m_sbHoriz->SetRange( 0, nRange - 1 );
m_sbHoriz->SetPageSize( m_nColumnNum );
m_sbHoriz->SetPosition( 0 );
if( m_iBeginShowBar>0 ){
ScrollView( m_iBeginShowBar, false );
}
}
else {
m_sbHoriz->SetRange( 0, 0, false );
m_sbHoriz->SetPageSize( 0, false );
m_sbHoriz->SetPosition( 0, false );
}
nRange = m_aTracks.size();
int nDrawHeight = ClientHeight - m_nTopBound - m_nBottomBound
- m_nRowGapHeight - m_nTitleHeight - m_nChordHeight;
if( nDrawHeight % m_nTrackHeight > 0 )
nRange++;
if( nRange > m_nTrackShow ){
m_sbVert->SetRange( 0, nRange-1 );
m_sbVert->SetPageSize( m_nTrackShow );
m_sbVert->SetPosition( 0 );
}
else{
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
}
}
return bScroll;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoHandleMessage(MSG &Msg, bool &Handled)
{
if( !Visible )
return;
if( Msg.message==WM_MOUSEMOVE && Msg.wParam==0 ){
TPoint pt( Msg.pt.x, Msg.pt.y );
pt = ScreenToClient( pt );
if( m_sbVert && m_sbVert->Visible && Msg.hwnd!=m_sbVert->Handle ) //竖直滚动条自动隐藏
m_sbVert->Visible = false;
if( m_sbHoriz && m_sbHoriz->Visible && Msg.hwnd!=m_sbHoriz->Handle ) //水平滚动条自动隐藏
m_sbHoriz->Visible = false;
if( pt.x>=0 && pt.x<Width && pt.y>=0 && pt.y<Height && Msg.hwnd==Handle
&& !m_bBrush ){
if( pt.x<m_nLeftOriBound ){
if( g_iToolPanelShow==0x01 ){
Screen->Cursor = crHSplit;
m_ApplicationEvents->CancelDispatch();
}
}
else if( !m_bVertical && m_nLeftBound>=MIN_HDR_WIDTH && pt.y<m_sbHoriz->Top
&& pt.x>m_nLeftBound-8 && pt.x<m_nLeftBound+2 ){
Screen->Cursor = crHSplit;
m_ApplicationEvents->CancelDispatch();
}
else{
if( Screen->Cursor==crHSplit )
Screen->Cursor = crDefault;
if( m_sbVert->IsOperable() && pt.x >= m_sbVert->Left
&& pt.y >= m_sbVert->Top ){ //竖直滚动条自动显示
m_sbVert->Visible = true;
m_ApplicationEvents->CancelDispatch();
}
if( m_sbHoriz->IsOperable() && pt.x >= m_sbHoriz->Left
&& pt.y >= m_sbHoriz->Top ){ //水平滚动条自动显示
m_sbHoriz->Visible = true;
m_ApplicationEvents->CancelDispatch();
}
}
}
else if( Screen->Cursor==crHSplit && (pt.x<0 || pt.y<0 || pt.y>=Height) ){
Screen->Cursor = crDefault;
}
}
else if( Msg.message==WM_KEYDOWN && Msg.hwnd==Handle
&& Msg.wParam>=VK_PRIOR && Msg.wParam<=VK_DOWN ){
OnDirectionKey( Msg.wParam );
}
}
//---------------------------------------------------------------------------
void TContentPanel::ShowBeatHint( int iBeat )
{
if( m_iBeatHint==iBeat )
return;
if( iBeat<0 || iBeat>3 ){
iBeat = -1;
RECT rectHint;
SetRect( &rectHint, m_lBeatHint, m_tBeatHint,
m_lBeatHint + m_wBeatHint,
m_tBeatHint + m_hBeatHint );
InvalidateRect( Handle, &rectHint, false );
}
else{
Canvas->Draw( m_lBeatHint, m_tBeatHint, m_imgBeatHint[iBeat] );
}
m_iBeatHint = iBeat;
}
// ---------------------------------------------------------------------------
void TContentPanel::SetPlayPoint( int iBar, int iPoint )
{
if( m_iPlayBar==iBar && m_iPlayPoint==iPoint ){
return;
}
if( m_nBarNum==0 ){
m_iPlayBar = m_iPlayPoint = 0;
return;
}
int iRow = m_bVertical ? m_iPlayBar / m_nColumnNum - m_iBeginShowRow : 0;
if( m_nBarNum>0 && iRow>=0 ){
RECT rect;
int iCol = m_bVertical ? m_iPlayBar % m_nColumnNum : m_iPlayBar - m_iBeginShowBar,
left = iCol * m_nBarWidth + m_iPlayPoint + m_nLeftBound,
top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight;
SetRect( &rect, left - 5, top - 8, left - 5 + m_imgPlayCursor->Width,
top - 8 + m_imgPlayCursor->Height );
InvalidateRect( Handle, &rect, false );
int nH = m_nBarDrawHeight;
if( top + m_nBarDrawHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
SetRect( &rect, left, top, left + 1, top + nH );
InvalidateRect( Handle, &rect, false );
}
m_iPlayBar = iBar;
m_iPlayPoint = iPoint;
ShowPlayPoint();
}
//---------------------------------------------------------------------------
void TContentPanel::ShowPlayPoint()
{
int iRow = m_bVertical ? m_iPlayBar / m_nColumnNum - m_iBeginShowRow : 0,
iCol = m_bVertical ? m_iPlayBar % m_nColumnNum : m_iPlayBar - m_iBeginShowBar;
if( m_bVertical && iRow<0 ){
ScrollView( iRow + m_iBeginShowRow );
}
else if( m_bVertical && ( iRow>=m_nRowShow || m_nRowShow>1 && iRow>=m_nRowShow-1 )){
//int nRowScroll = min( m_nRowShow+m_iBeginShowRow-1, m_nRowNum-iRow ); // 显示到第2行
int nRow1 = iRow+m_iBeginShowRow,
nRow2 = m_nRowNum-m_nRowShow+1;
if( m_nRowShow>2 )
nRow1--;
if( nRow1>=0 && nRow2>=0 ){
int nRowScroll = min( nRow1, nRow2 ); // 显示到第2行
ScrollView( nRowScroll );
}
}
else if( !m_bVertical && iCol<0 ){
ScrollView( iCol + m_iBeginShowBar, false );
}
else if( !m_bVertical && iCol>=m_nColumnNum-1 ){
//int nColScroll = min( m_iBeginShowBar+m_nColumnNum-2, m_nBarNum-m_nColumnNum+1 ); // 显示第2小节
int nColScroll = min( m_iPlayBar-2, m_nBarNum-m_nColumnNum+1 ); // 显示第2小节
ScrollView( nColScroll, false );
}
else if( m_nBarNum>0 ){
RECT rect;
int left = iCol * m_nBarWidth + m_iPlayPoint + m_nLeftBound,
top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight;
SetRect( &rect, left - 5, top - 8, left - 5 + m_imgPlayCursor->Width,
top - 8 + m_imgPlayCursor->Height );
InvalidateRect( Handle, &rect, false );
int nH = m_nBarDrawHeight;
if( top + m_nBarDrawHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
SetRect( &rect, left, top, left + 1, top + nH );
InvalidateRect( Handle, &rect, false );
}
}
void TContentPanel::InvalidateBar( int iBar, int iBeginPoint, int iEndPoint, int iArea )
{
if( iBar<m_iBeginShowBar )
return;
int iRow, iCol;
TRect rectDraw;
iRow = m_bVertical ? iBar / m_nColumnNum - m_iBeginShowRow : 0;
iCol = m_bVertical ? iBar % m_nColumnNum : iBar - m_iBeginShowBar;
if( iRow>=m_nRowShow || iCol>=m_nColumnNum )
return;
rectDraw.left = iCol * m_nBarWidth + m_nLeftBound + iBeginPoint - 1;
rectDraw.right = iCol * m_nBarWidth + m_nLeftBound + iEndPoint + 1;
if( rectDraw.right>ClientWidth-m_nRightBound )
rectDraw.right = ClientWidth-m_nRightBound;
int nBarTop = iRow * m_nBarHeight + m_nTopBound,
nDrawBottom = ClientHeight - m_nBottomBound;
bool bData = g_lstOpusStages.size()>0;
if( iArea & BAR_TITLE ){
rectDraw.top = nBarTop + m_nRowGapHeight;
if( rectDraw.top < nDrawBottom ){
rectDraw.bottom = rectDraw.top + m_nTitleHeight;
if( rectDraw.bottom > nDrawBottom )
rectDraw.bottom = nDrawBottom;
InvalidateRect( Handle, &rectDraw, false );
}
}
if( ( iArea & BAR_DATA ) && bData ){
rectDraw.top = nBarTop + m_nRowGapHeight + m_nTitleHeight;
if( rectDraw.top < nDrawBottom ){
rectDraw.bottom = rectDraw.top + m_nChordHeight;
if( rectDraw.bottom > nDrawBottom )
rectDraw.bottom = nDrawBottom;
else if( !( iArea & BAR_TRACK ) )
rectDraw.bottom++;
InvalidateRect( Handle, &rectDraw, false );
}
}
if( iArea & BAR_TRACK ){
int iTrack = ( iArea & 0xFF ) - m_iBeginShowTrack;
if( iTrack>=0 && iTrack<=m_nTrackShow ){
if( iTrack>0 ){
rectDraw.top = nBarTop + m_nRowGapHeight + m_nTitleHeight + (iTrack - 1) * m_nTrackHeight;
if( bData ) rectDraw.top += m_nChordHeight;
rectDraw.bottom = rectDraw.top + m_nTrackHeight + 1;
}
else{
rectDraw.top = nBarTop + m_nRowGapHeight + m_nTitleHeight;
if( bData ) rectDraw.top += m_nChordHeight;
rectDraw.bottom = rectDraw.top + (m_aTracks.size()-m_iBeginShowTrack) * m_nTrackHeight + 1;
}
if( rectDraw.top < nDrawBottom ){
if( rectDraw.bottom > nDrawBottom )
rectDraw.bottom = nDrawBottom;
InvalidateRect( Handle, &rectDraw, false );
}
}
}
}
//---------------------------------------------------------------------------
void TContentPanel::InvalidateBars( int iBarStart, int iBarEnd, int iArea )
{
for( int i=iBarStart; i<=iBarEnd; i++ ){
InvalidateBar( i, 0, m_nBarWidth, iArea );
}
}
//---------------------------------------------------------------------------
void TContentPanel::InvalidateStage( int iStage, int iArea )
{
if( iStage<0 || iStage>=g_lstOpusStages.size() )
return;
int iFirstBar = FirstBar( iStage );
TOpusStage * pStage = g_lstOpusStages[iStage];
InvalidateBars( iFirstBar, iFirstBar + pStage->aBars.size() - 1, iArea );
}
//---------------------------------------------------------------------------
void TContentPanel::InvalidateShowBars( int iArea )
{
int iBarS = m_iBeginShowBar,
iBarE = iBarS + m_nRowNum * m_nColumnNum;
if( iBarE>m_nBarNum )
iBarE = m_nBarNum-1;
InvalidateBars( iBarS, iBarE, iArea );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::OnDirectionKey( WORD key )
{
if( m_nBarNum==0 )
return;
int nSBCode = -1;
int nWMCode = -1;
if( key>=VK_PRIOR && key<=VK_HOME ){
if( m_bVertical && m_sbVert && m_sbVert->IsOperable() )
nWMCode = WM_VSCROLL;
else if( !m_bVertical && m_sbHoriz && m_sbHoriz->IsOperable() )
nWMCode = WM_HSCROLL;
}
else if( key==VK_UP || key==VK_DOWN ){
if( m_sbVert && m_sbVert->IsOperable() )
nWMCode = WM_VSCROLL;
}
else if( key==VK_LEFT || key==VK_RIGHT ){
if( m_sbHoriz && m_sbHoriz->IsOperable() )
nWMCode = WM_HSCROLL;
}
if( nWMCode>=0 ){
if( key==VK_UP || key==VK_LEFT ) nSBCode = SB_LINEUP;
else if( key==VK_DOWN || key==VK_RIGHT ) nSBCode = SB_LINEDOWN;
else if( key==VK_PRIOR ) nSBCode = SB_PAGEUP;
else if( key==VK_NEXT ) nSBCode = SB_PAGEDOWN;
else if( key==VK_HOME ) nSBCode = SB_TOP;
else if( key==VK_END ) nSBCode = SB_BOTTOM;
Perform( nWMCode, MAKELONG(nSBCode,0), NULL );
}
}
//---------------------------------------------------------------------------
void TContentPanel::ScrollView( int nPos, bool bVertical, bool bRedraw )
{
if( bVertical ){
if( m_bVertical ){
m_iBeginShowBar = nPos * m_nColumnNum;
if( m_iBeginShowRow!=nPos ){
m_iBeginShowRow = nPos;
InvalidateRgn( Handle, NULL , false );
}
}
else{
if( m_iBeginShowTrack!=nPos ){
m_iBeginShowTrack = nPos;
InvalidateRgn( Handle, NULL , false );
}
}
if( bRedraw ){
m_sbVert->SetPosition( nPos );
}
}
else{
if( m_iBeginShowBar!=nPos ){
m_iBeginShowBar = nPos;
InvalidateRgn( Handle, NULL , false );
}
if( bRedraw ){
m_sbHoriz->SetPosition( nPos );
}
}
}
//---------------------------------------------------------------------------
void TContentPanel::CalcViewArea()
{
if( ClientWidth>0 && ClientHeight>0 ){
if( m_bVertical ){
m_nColumnNum = (ClientWidth - m_nLeftOriBound - m_nRightBound) / m_nBarWidth;
m_nRowNum = m_nBarNum / m_nColumnNum;
if( m_nBarNum % m_nColumnNum > 0 ){
m_nRowNum++;
}
int nDrawHeight = ClientHeight - m_nTopBound - m_nBottomBound;
m_nRowShow = nDrawHeight / m_nBarHeight;
if( nDrawHeight % m_nBarHeight > m_nRowGapHeight + m_nTitleHeight ){
m_nRowShow++;
m_nRowNum++;
}
m_nLeftBound = m_nLeftOriBound + 3;
m_nTrackShow = m_aTracks.size();
}
else{
m_nLeftBound = m_aTracks.empty() ? m_nLeftOriBound + 3 : m_nTrkHdrWidth;
int nDrawWidth = ClientWidth - m_nLeftBound - m_nRightBound;
m_nColumnNum = nDrawWidth / m_nBarWidth;
if( nDrawWidth % m_nBarWidth > 0 )
m_nColumnNum++;
int nHeight = ClientHeight - m_nTopBound - m_nBottomBound
- m_nRowGapHeight - m_nTitleHeight - m_nChordHeight;
m_nTrackShow = nHeight / m_nTrackHeight;
if( nHeight % m_nTrackHeight > 0 )
m_nTrackShow++;
m_sbHoriz->Left = m_nLeftBound;
m_sbHoriz->Width = ClientWidth - m_nLeftBound - 1;
}
}
else{
DebugPrint( "no area" );
}
}
//---------------------------------------------------------------------------
void TContentPanel::DrawBars()
{
bool bData = !g_lstOpusStages.empty();
bool bTrack = !m_aTracks.empty();
if( !bData && !bTrack )
return;
TRect rtInvalid = Canvas->ClipRect;
int iBeginRow = m_bVertical ? (rtInvalid.top - m_nTopBound) / m_nBarHeight : 0,
iEndRow = m_bVertical ? (rtInvalid.bottom - m_nTopBound) / m_nBarHeight : 1,
iBeginCol = ( rtInvalid.left - m_nLeftBound ) / m_nBarWidth,
iEndCol = ( rtInvalid.right - m_nLeftBound ) / m_nBarWidth;
// if( !m_bVertical ){
if( iBeginCol<0 )
iBeginCol = 0;
if( iEndCol<0 )
iEndCol = 0;
// }
if( iBeginRow<0 )
iBeginRow = 0;
if( iEndCol<m_nColumnNum && (rtInvalid.right - m_nLeftBound ) % m_nBarWidth > 0 )
iEndCol++;
if( m_bVertical && (rtInvalid.bottom - m_nTopBound) % m_nBarHeight > 2 )
iEndRow++;
int rowTop = m_nTopBound + iBeginRow * m_nBarHeight;
iBeginRow += m_iBeginShowRow;
iEndRow += m_iBeginShowRow;
int iSelBarStart = m_iSelBarStart,
iSelBarEnd = m_iSelBarEnd,
iSelPointStart = m_iSelPointStart,
iSelPointEnd = m_iSelPointEnd;
if( iSelBarEnd>=0 && iSelBarStart<0 ){
iSelBarStart = 0;
iSelPointStart = 0;
}
else if( iSelBarStart>=0 && iSelBarEnd<0 ){
iSelBarEnd = m_nBarNum - 1;
iSelPointEnd = m_nDataWidth - 1;
}
if( m_rgnClip )
SelectClipRgn( Canvas->Handle, m_rgnClip );
int iFirstBar(0), iStage(0), nBarCount(0), iLastKey(g_iMelodyKey);
for( int i=iBeginRow; i<m_nRowNum && i<iEndRow; i++ ){
int right, barTop = rowTop + m_nRowGapHeight,
barBottom = min( barTop + m_nBarDrawHeight - m_iBeginShowTrack*m_nTrackHeight,
ClientHeight - m_nBottomBound ),
iBarLeft = m_nLeftBound + iBeginCol * m_nBarWidth;
if( i==iBeginRow || iBeginCol>0 || iEndCol>0 && iEndCol<m_nColumnNum ){
if( m_bVertical )
nBarCount = i * m_nColumnNum + iBeginCol;
else
nBarCount = m_iBeginShowBar + iBeginCol;
if( nBarCount>=m_nBarNum )
break;
if( bData && nBarCount>0 && nBarCount<g_Opus.BarCount() ){
iStage = FindStage( nBarCount-1, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
if( pStage->iSegType>=SEGTYPE_INTRO )
iLastKey = pStage->iSegKey;
else
iLastKey = pStage->aBars[nBarCount-1-iFirstBar]->iBarKey;
}
}
if( m_nBarNum - nBarCount >= m_nColumnNum ){ //显示整满行
right = m_nColumnNum * m_nBarWidth + m_nLeftBound;
}
else{ //显示非整行
right = (m_nBarNum - nBarCount) * m_nBarWidth + m_nLeftBound;
}
//绘制轨道
if( bTrack ){
int iBeginTrk = 0,
iEndTrk = m_aTracks.size();
if( !m_bVertical ){
int iTrackTop = m_nTopBound + m_nRowGapHeight + m_nTitleHeight + m_nChordHeight;
iBeginTrk = (rtInvalid.top - iTrackTop) / m_nTrackHeight;
iEndTrk = (rtInvalid.bottom - iTrackTop) / m_nTrackHeight;
if( iBeginTrk<0 )
iBeginTrk = 0;
if( iEndTrk<0 )
iEndTrk = 0;
else if( iEndTrk<m_nTrackShow && ((rtInvalid.bottom-iTrackTop)%m_nTrackHeight > 0) )
iEndTrk++;
iBeginTrk += m_iBeginShowTrack;
iEndTrk += m_iBeginShowTrack;
if( iBeginTrk>m_aTracks.size() )
iBeginTrk = m_aTracks.size();
if( iEndTrk>m_aTracks.size() )
iEndTrk = m_aTracks.size();
}
bool bBreak = bData,
bDrawHead = !m_bVertical && (rtInvalid.left < m_nLeftBound-4);
int topTrack = barTop + m_nTitleHeight + ( bData ? m_nChordHeight : 0 )
+ (iBeginTrk-m_iBeginShowTrack) * m_nTrackHeight,
leftTrack = bDrawHead ? m_nLeftOriBound : iBarLeft,
num = min( m_nBarNum - nBarCount, iEndCol - iBeginCol );
Canvas->Pen->Style = psSolid;
for( int t=iBeginTrk; t<iEndTrk && topTrack<rtInvalid.bottom; t++ ){
if( bBreak ){
// 绘制隔离线
Canvas->Pen->Color = clrBarTitle[0];
if( bDrawHead ){
Canvas->MoveTo( leftTrack, topTrack );
Canvas->LineTo( m_nLeftBound-4, topTrack );
}
Canvas->MoveTo( iBarLeft+1, topTrack );
Canvas->LineTo( right, topTrack );
bBreak = false;
}
DrawTrack( nBarCount, num, leftTrack, topTrack+1, t );
topTrack += m_nTrackHeight;
bBreak = true;
}
}
Canvas->Font->Name = "SimHei";
Canvas->Font->Size = g_szFont8;
Canvas->Font->Color = clrTitleFont;
//绘制第一个小节线
Canvas->Pen->Color = clrBarTitle[0];
Canvas->MoveTo( m_nLeftBound, barTop );
Canvas->LineTo( m_nLeftBound, barBottom );
for( int j=iBeginCol; j<iEndCol && nBarCount<m_nBarNum; j++ ){
String strText;
Canvas->Pen->Style = psSolid;
if( m_iMode==VIEW_STYLE && m_iSelTrack<0
&& ( m_iSelBarStart==nBarCount || m_iCopyBarStart==nBarCount )){
Canvas->Pen->Color = clrFocus;
if( m_iCopyBarStart==nBarCount ){
Canvas->Brush->Color = clBlack;
Canvas->Pen->Style = psDot;
}
Canvas->MoveTo( iBarLeft, barTop );
Canvas->LineTo( iBarLeft, barBottom );
}
if( ( iSelBarStart<=nBarCount && iSelBarEnd>=nBarCount
|| m_iCopyBarStart<=nBarCount && m_iCopyBarEnd>=nBarCount )
&& m_iMode==VIEW_STYLE && m_iSelTrack<0 ){
int l=iBarLeft+1, r=iBarLeft+m_nBarWidth+1;
//绘制高亮小节栏
DrawBarTitle( l, r, barTop, true );
if( m_iMode==VIEW_STYLE ){
Canvas->Pen->Color = clrFocus;
if( m_iCopyBarStart<=nBarCount && m_iCopyBarEnd>=nBarCount ){
Canvas->Brush->Color = clBlack;
Canvas->Pen->Style = psDot;
}
}
else
Canvas->Pen->Color = clrBarTitle[0];
}
else{
//绘制小节栏
DrawBarTitle( iBarLeft+1, iBarLeft+m_nBarWidth+1, barTop, false );
Canvas->Pen->Color = clrBarTitle[0];
}
// 绘制小节栏上框
Canvas->MoveTo( iBarLeft+1, barTop );
Canvas->LineTo( iBarLeft+m_nBarWidth, barTop );
//绘制小节序号或调号
bool bDrawKey = false;
if( bData && nBarCount<g_Opus.BarCount() ){
if( nBarCount-iFirstBar==g_lstOpusStages[iStage]->aBars.size() ){
iStage++;
iFirstBar = nBarCount;
}
TOpusStage* pStage = g_lstOpusStages[iStage];
int iKey = -1;
if( nBarCount==0 ){
iKey = iLastKey;
bDrawKey = true;
}
else if( pStage->iSegType<=SEGTYPE_FILL ){
iKey = pStage->aBars[nBarCount-iFirstBar]->iBarKey;
bDrawKey = iKey!=iLastKey;
}
else if( nBarCount==iFirstBar ){
iKey = pStage->iSegKey;
bDrawKey = iKey!=iLastKey;
}
if( bDrawKey ){
strText = "1 = ";
strText += g_strMelodyKey[iKey];
iLastKey = iKey;
}
}
if( !bDrawKey )
strText = IntToStr(nBarCount+1);
Canvas->Brush->Style = bsClear;
Canvas->TextOut( iBarLeft + 8, barTop + 4, strText );
Canvas->Brush->Style = bsSolid;
int iBarTop = barTop + m_nTitleHeight;
if( bData && nBarCount<g_Opus.BarCount() ){
DrawBarData( nBarCount, iStage, iFirstBar, iBarLeft, iBarTop );
iBarTop += m_nChordHeight;
}
Canvas->Pen->Style = psSolid;
if( m_iMode==VIEW_STYLE && m_iSelTrack<0
&& ( m_iSelBarEnd==nBarCount || m_iCopyBarEnd==nBarCount )){
Canvas->Pen->Color = clrFocus;
if( m_iCopyBarEnd==nBarCount ){
Canvas->Brush->Color = clBlack;
Canvas->Pen->Style = psDot;
}
}
else{
Canvas->Pen->Color = clrBarTitle[0];
}
//绘制小节线
Canvas->MoveTo( iBarLeft + m_nBarWidth, barTop );
Canvas->LineTo( iBarLeft + m_nBarWidth, barTop + m_nTitleHeight );
if( j==m_nColumnNum-1 || nBarCount==m_nBarNum-1 ){
Canvas->MoveTo( iBarLeft + m_nBarWidth, barTop + m_nTitleHeight );
Canvas->LineTo( iBarLeft + m_nBarWidth, barTop + m_nBarDrawHeight );
}
else if( bData ){
Canvas->MoveTo( iBarLeft + m_nBarWidth, barTop + m_nTitleHeight );
Canvas->LineTo( iBarLeft + m_nBarWidth, barTop + m_nTitleHeight + m_nChordHeight );
}
//绘制播放线
if( m_iPlayBar==nBarCount ){
int iPlayPoint = iBarLeft + m_iPlayPoint;
if( iPlayPoint-5>=rtInvalid.left && iPlayPoint+5<rtInvalid.right
&& barTop-8>=rtInvalid.top ){
Canvas->Draw( iPlayPoint - 5, barTop - 8, m_imgPlayCursor );
}
if( iPlayPoint>=rtInvalid.left && iPlayPoint<rtInvalid.right ){
TColor clrOld = Canvas->Pen->Color;
Canvas->Pen->Color = clrPlayLine;
Canvas->Pen->Style = psSolid;
Canvas->MoveTo( iPlayPoint, barTop+1 );
Canvas->LineTo( iPlayPoint, barBottom );
Canvas->Pen->Color = clrOld;
}
}
//绘制音频插入线
if( g_iSelAudio>=0 && nBarCount==m_iSelTrackBar ){
int l = iBarLeft + m_iSelTrackPoint,
t = iBarTop + ( GetShowTrackId(ST_AUDIO,g_iSelAudio) - 1 ) * m_nTrackHeight,
b = t + m_nTrackHeight;
if( l>=rtInvalid.left && l<rtInvalid.right ){
Canvas->Pen->Color = clrInsertLine;
Canvas->MoveTo( l, t );
Canvas->LineTo( l, b );
}
}
// 绘制小节栏下框
if( barTop+m_nBarDrawHeight <= barBottom ){
Canvas->Pen->Color = clrBarTitle[0];
Canvas->MoveTo( iBarLeft, barTop + m_nBarDrawHeight );
Canvas->LineTo( iBarLeft+m_nBarWidth, barTop + m_nBarDrawHeight );
}
if( w_bDraging ){
Canvas->Pen->Style = psSolid;
TRect rcTip;
rcTip.left = iBarLeft,
rcTip.top = barTop,
rcTip.right = iBarLeft+m_nBarWidth,
rcTip.bottom = barTop + m_nBarDrawHeight - 1;
if( rcTip.bottom > barBottom ){
rcTip.bottom = barBottom;
}
if( nBarCount==m_iDropBar ){
rcTip.right = rcTip.left + DOTIP_WIDTH;
Canvas->Brush->Color = clrFocback;
Canvas->FillRect( rcTip );
Canvas->Pen->Color = clrFocus;
Canvas->MoveTo( rcTip.left, rcTip.top );
Canvas->LineTo( rcTip.right, rcTip.top );
Canvas->MoveTo( rcTip.left, rcTip.bottom );
Canvas->LineTo( rcTip.right, rcTip.bottom );
Canvas->MoveTo( rcTip.right, rcTip.top );
Canvas->LineTo( rcTip.right, rcTip.bottom );
}
if( nBarCount==m_iDropBar-1 ){
rcTip.left = rcTip.right - DOTIP_WIDTH;
Canvas->Brush->Color = clrFocback;
Canvas->FillRect( rcTip );
Canvas->Pen->Color = clrFocus;
Canvas->MoveTo( rcTip.left, rcTip.top );
Canvas->LineTo( rcTip.right, rcTip.top );
Canvas->MoveTo( rcTip.left, rcTip.bottom );
Canvas->LineTo( rcTip.right, rcTip.bottom );
Canvas->MoveTo( rcTip.left, rcTip.top );
Canvas->LineTo( rcTip.left, rcTip.bottom );
}
}
nBarCount++;
iBarLeft += m_nBarWidth;
}
rowTop += m_nBarHeight;
}
}
//---------------------------------------------------------------------------
void TContentPanel::DrawBarTitle( int l, int r, int t, bool bSel )
{
Canvas->Pen->Style = psSolid;
for( int i=0; i<m_nTitleHeight; i++ ){
if( bSel )
Canvas->Pen->Color = clrBarTitleSel[i];
else
Canvas->Pen->Color = clrBarTitle[i];
Canvas->MoveTo( l, t+i );
Canvas->LineTo( r, t+i );
}
}
//---------------------------------------------------------------------------
void TContentPanel::DrawBarData( int iBar, int iStage, int iFirstBar, int leftBar, int topBar )
{
TColor clrOld = Canvas->Brush->Color;
//背景
TRect rectBar;
rectBar.left = leftBar + 1;
rectBar.right = leftBar + m_nDataWidth;
rectBar.top = topBar;
rectBar.bottom = rectBar.top + m_nChordHeight;
COLORREF clrNormal;
TOpusStage* pStage = g_lstOpusStages[iStage];
{
int ty = pStage->iSegType,
iNo = g_iSegColorMode==0 ? pStage->iSegNo : pStage->aTracks.size();
bool bInc = g_iSegColorMode==0 ? true
: iNo>0 && pStage->aTracks[0]->iChanNo==9;
Canvas->Brush->Color = GetSegmentColor( ty, iNo, bInc );
}
Canvas->FillRect( rectBar );
//和弦选中框
if( m_iMode==VIEW_CHORD ){
if ( iBar>=m_iSelBarStart && iBar<=m_iSelBarEnd ){ //绘制选中和弦框
int l = leftBar,
r = leftBar + m_nDataWidth,
t = topBar,
b = topBar + m_nChordHeight - 1;
BYTE rF = 227, gF = 24, bF = 19,
rD = 110, gD = 108, bD = 105,
rL = 230, gL = 226, bL = 217;
if( iBar==m_iSelBarStart ) //左框位置
l += m_iSelCellStart * m_nChordTxtWidth;
if( iBar==m_iSelBarEnd ){ //右框位置
r = leftBar + (m_iSelCellEnd+1) * m_nChordTxtWidth;
if( m_iSelCellEnd==g_nChordNumPerBar-1 )
r--;
}
for( int i=0; i<4; i++ ){
if( i==0 )
Canvas->Pen->Color = RGB(rF, gF, bF);
if( i<2 ){
//绘制下框
if( i>0 ){
Canvas->Pen->Color = RGB(rL, gL, bL);
rL -= 10, gL -= 10, bL -= 10;
}
Canvas->MoveTo( l+i, b-i );
Canvas->LineTo( r-i+1, b-i );
if( iBar==m_iSelBarEnd ){ //绘制右框
Canvas->MoveTo( r-i, t+i );
Canvas->LineTo( r-i, b-i+1 );
}
}
if( i>0 ){
Canvas->Pen->Color = RGB(rD, gD, bD);
rD += 30, gD += 30, bD += 30;
}
//绘制上框
Canvas->MoveTo( l+i, t+i );
Canvas->LineTo( r-i+1, t+i );
if( iBar==m_iSelBarStart ){ //绘制左框
Canvas->MoveTo( l+i, t+i );
Canvas->LineTo( l+i, b-i+1 );
}
}
}
if( iBar>=m_iCopyBarStart && iBar<=m_iCopyBarEnd ){
int l = leftBar,
r = leftBar + m_nDataWidth,
t = topBar,
b = topBar + m_nChordHeight - 1;
Canvas->Brush->Color = clWhite;
Canvas->Pen->Style = psDot;
Canvas->Pen->Color = clRed;
if( iBar==m_iCopyBarStart ){ //绘制左框
l += m_iCopyCellStart * m_nChordTxtWidth;
if( m_iCopyCellStart==0 ){
Canvas->Brush->Color = clBlack;
}
Canvas->MoveTo( l, t );
Canvas->LineTo( l, b );
if( m_iCopyCellStart==0 ){
Canvas->Brush->Color = clWhite;
}
}
if( iBar==m_iCopyBarEnd ){ //绘制右框
r = leftBar + (m_iCopyCellEnd+1) * m_nChordTxtWidth;
if( m_iCopyCellEnd==g_nChordNumPerBar-1 )
r--;
Canvas->MoveTo( r, t );
Canvas->LineTo( r, b );
}
//绘制上下框
Canvas->MoveTo( l, t );
Canvas->LineTo( r, t );
Canvas->MoveTo( l, b );
Canvas->LineTo( r, b );
}
}
//和弦
if( pStage->iSegType>=SEGTYPE_INTRO ) //前间尾奏无需绘制和弦
return;
TBar * pBar = pStage->aBars[iBar-iFirstBar];
TRect rectDest;
rectDest.top = topBar + ( m_nChordHeight - m_nChordTxtHeight ) / 2;
rectDest.bottom = rectDest.top + m_nChordTxtHeight;
int iPreKey = -1, iPreType = -1;
for( int i=0; i<g_nChordNumPerBar; i++ ){
if( iBar==m_iSelBarStart && i==m_iSelCellStart
|| iBar==m_iCopyBarStart && i==m_iCopyCellStart
|| pBar->aChords.iKey[i] != iPreKey
|| pBar->aChords.iType[i] != iPreType ){
rectDest.left = leftBar + i * m_nChordTxtWidth;
rectDest.right = rectDest.left + m_nChordTxtWidth;
DrawChord( rectDest, pBar->iBarKey, pBar->aChords.iKey[i],
pBar->aChords.iType[i] );
iPreKey = pBar->aChords.iKey[i];
iPreType = pBar->aChords.iType[i];
}
}
//画笔还原
Canvas->Brush->Color = clrOld;
}
//---------------------------------------------------------------------------
void TContentPanel::DrawTrack( int iBarS, int nBarNum, int left, int top, int iTrack )
{
bool bDrawHead = !m_bVertical && (left < m_nLeftBound-4);
int leftBar = bDrawHead ? m_nLeftBound : left;
TColor clrOld = Canvas->Brush->Color;
TShowTrack* pST = m_aTracks[iTrack];
COLORREF clrUnselect = clrWaveBk[0],
clrSelect = clrWaveBk[1],
clrHigh = clWhite;
Canvas->Font->Name = "Tohoma";
Canvas->Font->Size = g_szFont9;
// Canvas->Font->Color = clrHeadFont;
if( bDrawHead ){
TRect rectHead( m_nLeftOriBound, top, m_nLeftBound-4, top+m_nTrackHeight-1 );
if( m_iSelTrack==iTrack )
Canvas->Brush->Color = clrSelect;
else
Canvas->Brush->Color = clrUnselect;
Canvas->FillRect( rectHead );
TBitmap* pImg = pST->type==ST_MIDI ? m_imgMidiIcon : m_imgWaveIcon;
Canvas->Draw( m_nLeftOriBound + 2, top + 2, pImg );
String strText;
if( pST->type==ST_MIDI ){
strText = IntToStr( pST->index + 1 ) + " ";
TMidiTrack* pMT = (TMidiTrack*)pST->pTrack;
strText += GetProgName( pMT->bank, pMT->chno, pMT->prog );
}
else{
strText = "音轨 " + IntToStr( pST->index==0 ? 1 : pST->index );
}
//----处理字符过长------
int nWidth = m_nLeftBound - m_nLeftOriBound - pImg->Width - 12 - 16;
if( Canvas->TextWidth( strText )>nWidth ){
UnicodeString strShorty = strText;
while( Canvas->TextWidth( strShorty )>nWidth ){
strShorty = strShorty.SubString( 1, strShorty.Length()-2 );
}
strText = strShorty;
strText+="...";
}
//-----------
Canvas->Brush->Style = bsClear;
Canvas->Font->Color = clrHeadFont;
Canvas->TextOut( m_nLeftOriBound + pImg->Width + 4, top + 2, strText );
Canvas->Brush->Style = bsSolid;
if( pST->iHover & TRACK_S_HOVER ){
if( pST->pTrack->IsSolo() )
Canvas->Brush->Color = clrSMState[3];
else
Canvas->Brush->Color = clrSMState[1];
}
else if( pST->pTrack->IsSolo() )
Canvas->Brush->Color = clrSMState[2];
else
Canvas->Brush->Color = clrSMState[0];
TRect rtSM( m_nTrkHdrWidth+SOLO_LEFT, top+SM_TOP, m_nTrkHdrWidth+SOLO_LEFT+SM_SIZE, top+SM_TOP+SM_SIZE );
Canvas->FillRect( rtSM );
Canvas->Brush->Color = clrHeadFont;
Canvas->FrameRect( rtSM );
Canvas->Font->Name = "SimHei";
Canvas->Font->Size = g_szFont8;
Canvas->Brush->Style = bsClear;
Canvas->TextOut( rtSM.left + 4, rtSM.top + 2, "S" );
Canvas->Brush->Style = bsSolid;
rtSM.left = m_nTrkHdrWidth+MUTE_LEFT;
rtSM.right = m_nTrkHdrWidth+MUTE_LEFT + SM_SIZE;
if( pST->iHover & TRACK_M_HOVER ){
if( pST->pTrack->IsMute() )
Canvas->Brush->Color = clrSMState[3];
else
Canvas->Brush->Color = clrSMState[1];
}
else if( pST->pTrack->IsMute() )
Canvas->Brush->Color = clrSMState[2];
else
Canvas->Brush->Color = clrSMState[0];
Canvas->FillRect( rtSM );
Canvas->Brush->Color = clrHeadFont;
Canvas->FrameRect( rtSM );
Canvas->Brush->Style = bsClear;
Canvas->TextOut( rtSM.left + 4, rtSM.top + 2, "M" );
Canvas->Brush->Style = bsSolid;
}
if( nBarNum==0 )
return;
//背景
TRect rectBar;
rectBar.left = leftBar;
rectBar.right = rectBar.left + nBarNum * m_nDataWidth;
rectBar.top = top;
rectBar.bottom = rectBar.top + m_nTrackHeight - 1;
if( rectBar.bottom > ClientHeight - m_nBottomBound )
rectBar.bottom = ClientHeight - m_nBottomBound;
int iBarE = iBarS + nBarNum - 1;
if( m_iMode==VIEW_INIT ){
if( iBarS==0 ){
TRect rtNor = rectBar;
rtNor.right = rectBar.left + m_nDataWidth;
Canvas->Brush->Color = clrSelect;
Canvas->FillRect( rtNor );
rectBar.left += m_nDataWidth;
}
if( rectBar.right>rectBar.left ){
Canvas->Brush->Color = clrHigh;
if( rectBar.right > ClientWidth - m_nRightBound )
rectBar.right = ClientWidth - m_nRightBound;
Canvas->FillRect( rectBar );
}
}
else if( m_iMode==VIEW_CHORD || m_iSelBarStart<0 && m_iSelBarEnd<0 || iBarE<m_iSelBarStart
|| ( m_iSelBarEnd>=0 && iBarS>m_iSelBarEnd ) ){
if( m_iSelTrack==iTrack )
Canvas->Brush->Color = clrSelect;
else
Canvas->Brush->Color = clrUnselect;
if( rectBar.right > ClientWidth - m_nRightBound )
rectBar.right = ClientWidth - m_nRightBound;
Canvas->FillRect( rectBar );
}
else{
if( m_iSelTrack==iTrack )
Canvas->Brush->Color = clrSelect;
else
Canvas->Brush->Color = clrUnselect;
if( iBarS<=m_iSelBarStart ){
TRect rtNor = rectBar;
rtNor.right = rectBar.left + ( m_iSelBarStart - iBarS ) * m_nDataWidth
+ m_iSelPointStart;
if( rtNor.right>rtNor.left ){
if( rtNor.right > ClientWidth - m_nRightBound )
rtNor.right = ClientWidth - m_nRightBound;
Canvas->FillRect( rtNor );
rectBar.left = rtNor.right;
}
}
if( m_iSelBarEnd>=0 && iBarE>=m_iSelBarEnd ){
TRect rtNor = rectBar;
rtNor.left = rectBar.right - ( iBarE - m_iSelBarEnd + 1 ) * m_nDataWidth
+ m_iSelPointEnd;
if( rtNor.right>rtNor.left ){
if( rtNor.right > ClientWidth - m_nRightBound )
rtNor.right = ClientWidth - m_nRightBound;
Canvas->FillRect( rtNor );
rectBar.right = rtNor.left;
}
}
if( rectBar.right>rectBar.left ){
if( m_iDragAudio<0 && ( m_iSelTrack==iTrack || m_iSelTrack<0 )
|| pST->type==ST_AUDIO && m_iDragAudio==pST->index )
Canvas->Brush->Color = clrHigh;
if( rectBar.right > ClientWidth - m_nRightBound )
rectBar.right = ClientWidth - m_nRightBound;
Canvas->FillRect( rectBar );
}
}
if( pST->type==ST_AUDIO )
DrawRowWave( iBarS, nBarNum, leftBar, top, pST->index );
else
DrawRowMidi( iBarS, nBarNum, leftBar, top, pST->index );
//画笔还原
Canvas->Brush->Color = clrOld;
}
//---------------------------------------------------------------------------
void TContentPanel::DrawRowWave( int iBarS, int nBarNum, int left, int top, int iWave )
{
//绘制波形
TAudioTrack* pTrack = g_aAudioTracks[iWave];
int iBarE = iBarS + nBarNum - 1,
lWave = left,
hE = 1;
int mid = top + m_nTrackHeight/2 + 1;
for( int i=0; i<nBarNum; i++ ){
int iWvBar = iBarS + i;
TWaveBar *pBar = pTrack->lstBars[iWvBar];
for( int k=0; k<POINTS_PER_BAR; k++ ){
if( pBar->aVols[k]>0 && pBar->aVols[k]<=0x80008000 ){
DWORD wLeft = LOWORD(pBar->aVols[k]),
wRight = HIWORD(pBar->aVols[k]);
int yBottom = mid + ((14 * wRight )/0x8000),
yTop = mid - ((14 * wLeft )/0x8000);
if( yBottom>yTop ){
if( m_iMode==VIEW_INIT || m_iMode!=VIEW_CHORD
&&( m_iDragAudio==iWave || m_iDragAudio<0
&& ( g_iSelAudio==iWave || m_iSelTrack<0 )
&& m_iSelBarStart>=0 && m_iSelBarEnd>=0 )
&&( iWvBar>m_iSelBarStart
|| iWvBar==m_iSelBarStart && k>=m_iSelPointStart )
&& ( m_iSelBarStart>0 && m_iSelBarEnd<0
|| iWvBar<m_iSelBarEnd
|| iWvBar==m_iSelBarEnd && k<m_iSelPointEnd ) )
Canvas->Pen->Color = clrWave[0];
else
Canvas->Pen->Color = clrWave[1];
Canvas->MoveTo( lWave+k, yTop );
Canvas->LineTo( lWave+k, yBottom );
}
}
}
lWave += m_nDataWidth;
}
//绘制复制边框
if( m_iCopyAudio==iWave && iBarS<=m_iCopyBarEnd && iBarE>=m_iCopyBarStart ){
int l = left,
r = left + nBarNum * m_nDataWidth,
t = top,
b = top + m_nTrackHeight - 2;
Canvas->Pen->Style = psDot;
Canvas->Pen->Color = clRed;
if( iBarS<=m_iCopyBarStart ){ //绘制左框
l += ( m_iCopyBarStart - iBarS ) * m_nDataWidth + m_iCopyPointStart;
Canvas->MoveTo( l, t );
Canvas->LineTo( l, b );
}
if( iBarE>=m_iCopyBarEnd ){ //绘制右框
r -= ( iBarE - m_iCopyBarEnd + 1 ) * m_nDataWidth - m_iCopyPointEnd;
Canvas->MoveTo( r, t );
Canvas->LineTo( r, b );
}
//绘制上下框
Canvas->MoveTo( l, t );
Canvas->LineTo( r, t );
Canvas->MoveTo( l, b );
Canvas->LineTo( r, b );
Canvas->Pen->Style = psSolid;
}
}
//---------------------------------------------------------------------------
void TContentPanel::DrawRowMidi( int iBarS, int nBarNum, int left, int top, int iTrack )
{
//绘制MIDI
TMidiTrack* pTrack = g_aMidiTracks[iTrack];
int iBarE = iBarS + nBarNum,
iTickS = iBarS * POINTS_PER_BAR,
iTickE = iBarE * POINTS_PER_BAR,
iSelS = m_iSelBarStart>=iBarS ? (m_iSelBarStart-iBarS) * POINTS_PER_BAR : -1,
iSelE = m_iSelBarEnd>=iBarS ? (m_iSelBarEnd-iBarS) * POINTS_PER_BAR + m_iSelPointEnd: -1;
int bottom = top + m_nTrackHeight - 3;
for( int i=0; i<pTrack->aNotes.size(); i++ ){
if( pTrack->ptMax < pTrack->ptMin )
continue;
TMidiNote* pNote = pTrack->aNotes[i];
int range = pTrack->ptMax - pTrack->ptMin;
if( range<26 )
range = 26;
if( pNote->tkOn < pNote->tkOff && pNote->tkOn < iTickE && pNote->tkOff > iTickS ){
int iL = max( pNote->tkOn, iTickS ) - iTickS,
iR = min( pNote->tkOff, iTickE ) - iTickS,
iH = bottom - 26 * (pNote->pitch - pTrack->ptMin) / range;
int vol = pNote->volume * pTrack->volume / 100;
Canvas->Pen->Color = g_Midi.GetNoteColor( vol );
if( iL<iSelS ){
int iT = min( iSelS, iR );
if( iT>iL ){
Canvas->MoveTo( iL+left, iH );
Canvas->LineTo( iT+left, iH );
iL = iT;
}
}
if( iSelE>0 && iR>iSelE ){
int iT = max( iSelE, iL );
if( iT<iR ){
Canvas->MoveTo( iT+left, iH );
Canvas->LineTo( iR+left, iH );
iR = iT;
}
}
if( iR > iL ){
if( m_iMode!=VIEW_CHORD && ( iSelS>=0 || iSelE>=0 ) && m_iDragAudio<0
&& ( m_iSelTrack==iTrack || m_iSelTrack<0 ) )
Canvas->Pen->Color = clrWave[0];
Canvas->MoveTo( iL+left, iH );
Canvas->LineTo( iR+left, iH );
}
}
}
}
void __fastcall TContentPanel::Paint()
{
DrawBars();
if( w_bDraging ){
//绘制半透明图片
TBlendFunction Blend;
Blend.BlendOp = AC_SRC_OVER;
Blend.BlendFlags = 0;
Blend.AlphaFormat = 0;
Blend.SourceConstantAlpha =135;
TPoint pt(w_xImgDrag, w_yImgDrag);
pt = ScreenToClient( pt );
::AlphaBlend (Canvas->Handle,
pt.X,
pt.Y,
w_imgDrag->Width,
w_imgDrag->Height,
w_imgDrag->Canvas->Handle,
0,
0,
w_imgDrag->Width,
w_imgDrag->Height,
Blend
);
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMEraseBkgnd(TWMEraseBkgnd &Message)
{
TRect rect = GetClientRect();
TCanvas* tempCanvas = new TCanvas;
tempCanvas->Handle = Message.DC;
//绘制底色
tempCanvas->Brush->Color = clrBackground;
tempCanvas->FillRect( rect );
//绘制外边框
tempCanvas->Brush->Color = clrBackboard;
tempCanvas->FrameRect(rect);
if( !m_bVertical && m_nLeftBound==m_nTrkHdrWidth ){
//绘制轨道头区域
TRect rectHead = rect;
rectHead.right = m_nTrkHdrWidth;
// rectHead.bottom = m_nTopBound+m_nRowGapHeight+m_nTitleHeight+m_nChordHeight;
tempCanvas->Brush->Color = RGB( 58, 62, 69 );
tempCanvas->FillRect( rectHead );
// rectHead.top = rectHead.bottom;
// rectHead.bottom = rect.bottom;
// rectHead.left = TRK_HDR_WIDTH-4;
// tempCanvas->FillRect( rectHead );
tempCanvas->Brush->Color = clrBackboard;
tempCanvas->FrameRect( rectHead );
// rectHead.top = rect.top;
}
delete tempCanvas;
Message.Result = true;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMSize(TWMSize &Message)
{
DefaultHandler( &Message );
CalcViewArea();
if( m_rgnClip ){
::DeleteObject( m_rgnClip );
}
m_rgnClip = ::CreateRectRgn( 0, 0, ClientWidth - m_nRightBound,
ClientHeight - m_nBottomBound );
m_lBeatHint = (ClientWidth - m_wBeatHint) / 2;
m_tBeatHint = (ClientHeight - m_hBeatHint) / 2;
if( !m_sbVert || !m_sbHoriz )
return;
m_sbVert->Left = ClientWidth - m_sbVert->Width - 1;
m_sbVert->Height = ClientHeight - 2;
m_sbHoriz->Top = ClientHeight - m_sbHoriz->Height - 1;
m_sbHoriz->Width = ClientWidth - m_nLeftBound - 1;
if( m_bVertical ){
if( m_nRowNum>m_nRowShow ){
m_sbVert->SetRange( 0, m_nRowNum-1 );
m_sbVert->SetPageSize( m_nRowShow );
m_sbVert->SetPosition( 0 );
int iRowScroll = 0;
if( m_iBeginShowBar>0 ){
iRowScroll = min( m_iBeginShowBar / m_nColumnNum, m_nRowNum-m_nRowShow );
if( iRowScroll<0 ){
iRowScroll = 0;
}
}
ScrollView( iRowScroll );
}
else{
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
if( m_iBeginShowBar>0 )
ScrollView( 0 );
}
}
else{
int nRange = m_aTracks.size();
int nDrawHeight = ClientHeight - m_nTopBound - m_nBottomBound
- m_nRowGapHeight - m_nTitleHeight - m_nChordHeight;
if( nDrawHeight % m_nTrackHeight > 0 )
nRange++;
if( nRange > m_nTrackShow ){
m_sbVert->SetRange( 0, nRange-1 );
m_sbVert->SetPageSize( m_nTrackShow );
m_sbVert->SetPosition( 0 );
int iRowScroll = 0;
if( m_iSelTrack-m_iBeginShowTrack>=m_nTrackShow ){
iRowScroll = m_iSelTrack - m_nTrackShow + 1;
}
else if( m_iBeginShowTrack>0 ){
iRowScroll = min( m_iBeginShowTrack, nRange-m_nTrackShow );
if( iRowScroll<0 ){
iRowScroll = 0;
}
}
ScrollView( iRowScroll );
}
else{
m_sbVert->SetRange( 0, 0, false );
m_sbVert->SetPageSize( 0, false );
m_sbVert->SetPosition( 0, false );
if( m_iBeginShowTrack>0 )
ScrollView( 0 );
}
nRange = m_nBarNum;
int nDrawWidth = ClientWidth - m_nLeftOriBound - m_nRightBound;
if( nDrawWidth % m_nBarWidth > 0 )
nRange++;
if( nRange>m_nColumnNum ){
m_sbHoriz->SetRange( 0, nRange - 1 );
m_sbHoriz->SetPageSize( m_nColumnNum );
m_sbHoriz->SetPosition( 0 );
int iRowScroll = 0;
if( m_iBeginShowBar>0 ){
iRowScroll = min( m_iBeginShowBar, nRange-m_nColumnNum );
if( iRowScroll<0 ){
iRowScroll = 0;
}
}
ScrollView( iRowScroll, false );
}
else{
m_sbHoriz->SetRange( 0, 0, false );
m_sbHoriz->SetPageSize( 0, false );
m_sbHoriz->SetPosition( 0, false );
if( m_iBeginShowBar>0 )
ScrollView( 0, false );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMVScroll(TWMScroll &Message)
{
if( m_sbVert && m_sbVert->IsOperable() )
OnWMScroll( Message, true );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMHScroll(TWMScroll &Message)
{
if( m_sbHoriz && m_sbHoriz->IsOperable() )
OnWMScroll( Message, false );
}
//---------------------------------------------------------------------------
void TContentPanel::OnWMScroll(TWMScroll &Message, bool bVertical)
{
TSkinScrollBar* pSB = bVertical ? m_sbVert : m_sbHoriz;
int minpos, maxpos, page, curpos;
pSB->GetScrollRange(&minpos, &maxpos);
page = pSB->GetPageSize();
// Get the current position of scroll box.
curpos = pSB->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!=pSB->Handle )
pSB->SetPosition(curpos);
ScrollView(curpos, bVertical, FALSE);
Message.Result = true;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMMouseWheel(TWMMouseWheel &Message)
{
if( m_sbVert && m_sbVert->IsOperable() ){
UINT nSBCode;
if( Message.WheelDelta>0 ) nSBCode = SB_LINEUP;
else nSBCode = SB_LINEDOWN;
Perform( WM_VSCROLL, MAKELONG(nSBCode,0), NULL );
}
else if( m_sbHoriz && m_sbHoriz->IsOperable() ){
UINT nSBCode;
if( Message.WheelDelta>0 ) nSBCode = SB_LINEUP;
else nSBCode = SB_LINEDOWN;
Perform( WM_HSCROLL, MAKELONG(nSBCode,0), NULL );
}
}
//---------------------------------------------------------------------------
DWORD TContentPanel::HitTest( int X, int Y, int& iHitType, bool bHead )
{
iHitType = -1;
if( X<0 || X >= m_nColumnNum*m_nBarWidth+m_nLeftBound || Y <= m_nTopBound
|| Y >= ClientHeight - m_nBottomBound
|| Y >= (m_nRowNum-m_iBeginShowRow)*m_nBarHeight+m_nTopBound ){
return -1;
}
else if( X <= m_nLeftBound ){
if( bHead && Y > m_nTopBound+m_nRowGapHeight+m_nTitleHeight+m_nChordHeight ){
int nTop = m_nTopBound+m_nRowGapHeight+m_nTitleHeight+m_nChordHeight;
for( int i=m_iBeginShowTrack; i<m_aTracks.size(); i++ ){
int nBottom = nTop+m_nTrackHeight;
if( Y>=nTop && Y<=nBottom ){
int iBoxType=BAR_LEFT, nSMTop=nTop+SM_TOP,
lBox = 0, tBox = nTop ;
if( Y>=nSMTop && Y<=nSMTop+SM_SIZE ){
if( X>=m_nTrkHdrWidth+MUTE_LEFT
&& X<=m_nTrkHdrWidth+MUTE_LEFT+SM_SIZE ){
iBoxType = HOVER_MUTE;
lBox = m_nTrkHdrWidth+MUTE_LEFT;
tBox += SM_TOP;
}
else if( X>=m_nTrkHdrWidth+SOLO_LEFT
&& X<=m_nTrkHdrWidth+SOLO_LEFT+SM_SIZE ){
iBoxType = HOVER_SOLO;
lBox = m_nTrkHdrWidth+SOLO_LEFT;
tBox += SM_TOP;
}
}
iHitType = i + iBoxType;
return MAKELONG( lBox, tBox );
}
else if( Y<nTop )
break;
nTop = nBottom;
}
return -1;
}
else{
return -1;
}
}
int iRow = ( Y - m_nTopBound ) / m_nBarHeight + m_iBeginShowRow;
int iCol = ( X - m_nLeftBound ) / m_nBarWidth;
int deltaY = ( Y - m_nTopBound ) % m_nBarHeight;
int deltaX = ( X - m_nLeftBound ) % m_nBarWidth;
int iBar = m_bVertical ? iRow * m_nColumnNum + iCol
: iRow==0 ? m_iBeginShowBar + iCol : -1;
if( iBar<m_nBarNum && iBar>=0 ){
if( deltaY<m_nRowGapHeight ){
iHitType = BAR_CURSOR;
}
else if( deltaY<m_nRowGapHeight+m_nTitleHeight ){
iHitType = BAR_TITLE;
}
else if( deltaY<m_nRowGapHeight+m_nTitleHeight+m_nChordHeight ){
iHitType = BAR_DATA;
}
else{
int nWaveBottom = m_nRowGapHeight + m_nTitleHeight + m_nChordHeight;
for( int i=0; i<m_aTracks.size()-m_iBeginShowTrack; i++ ){
nWaveBottom += m_nTrackHeight;
if( deltaY<nWaveBottom ){
iHitType = i + m_iBeginShowTrack + BAR_TRACK;
break;
}
}
}
if( iHitType==BAR_CURSOR ){
if( m_nBarWidth-deltaX<ABS_POI_PLAY && iBar<m_nBarNum-1 ){ // 小节线左侧
return MAKELONG( iBar+1, 0 );
}
else if( deltaX<ABS_POI_PLAY && iCol<m_nColumnNum ){ // 小节线右侧
return MAKELONG( iBar, 0 );
}
}
else if( iHitType==BAR_TRACK ){
if( m_nBarWidth-deltaX<ABS_POI_WAVE && iBar<m_nBarNum-1 ){ // 小节线左侧
return MAKELONG( iBar+1, 0 );
}
else if( deltaX<ABS_POI_WAVE && iCol<m_nColumnNum ){ // 小节线右侧
return MAKELONG( iBar, 0 );
}
}
return MAKELONG( iBar, deltaX );
}
return -1;
}
//-----------------------------------------------------------------------------
int TContentPanel::GetCell( int iPoint )
{
int iCell = g_nChordNumPerBar-1;
for( int i=0; i<g_nChordNumPerBar; i++ ){
if( iPoint < i * m_nChordTxtWidth ){
iCell = i-1;
break;
}
}
return iCell;
}
//-----------------------------------------------------------------------------
void TContentPanel::DrawChord( TRect& rcDraw, int iBarKey, int iKey, int iType )
{
int iOriLeft = rcDraw.left,
iOriTop = rcDraw.top;
int iMainKey, iAjustKey;
GetChordDispalyKey( iKey, iBarKey, iMainKey, iAjustKey );
int wMKey(12), wAKey(0), wTKey(0), wVKey(13), wIKey(8);
if( iAjustKey!=0 ) //左上角标宽度
wAKey = 3;
if( iType>0 ){ //右下角标宽度
if( iType==1 ) //m
wTKey = 7;
else if( iType==2 ) //7
wTKey = 6;
else if( iType==3 || iType==7 ) //m7 M7
wTKey = 11;
else //s2 s4 s6
wTKey = 10;
}
if( !g_bAlphaKey ){
if( iMainKey==0 ){
wMKey = iType>0 ? 6 : 8;
}
else if( iMainKey==1 ){
wIKey = iType>2 ? 5 : 6;
wMKey = iType>0 ? 11 : 14;
}
else if( iMainKey==2 ){
if( iType==0 ){
wIKey = 5;
wMKey = 16;
}
else if( iType<=2 ){
wIKey = 5;
wMKey = 14;
}
else{
wIKey = 4;
wMKey = 12;
}
}
else if( iMainKey==3 ){
wMKey = iType>0 ? 13 : 18;
}
else if( iMainKey==4 ){
wMKey = iType>0 ? 7 : 11;
}
else if( iMainKey==5 ){
if( iType==0 ){
wVKey = 8;
wMKey = 17;
}
else if( iType<=2 ){
wVKey = 7;
wMKey = 14;
}
else{
wVKey = 6;
wMKey = 12;
}
}
else if( iMainKey==6 ){
wIKey = 4;
if( iType==0 ){
wVKey = 6;
wMKey = 19;
}
else if( iType<=2 ){
wVKey = 5;
wMKey = 15;
}
else{
wVKey = 4;
wMKey = 14;
}
}
}
else{
if( iMainKey==5 ) //A升降号靠近
wAKey = 1;
else if( iMainKey==1 || iMainKey==4) //D G宽度稍大
wMKey = 13;
else if( iMainKey==3 && iType>0 ) //F下标靠近
wMKey = 9;
}
int wChord = wMKey + wAKey + wTKey;
int iLeft = iOriLeft + ( rcDraw.Width() - wChord ) / 2;
int iTop = iOriTop - 2;
//绘制升降调
if( iAjustKey!=0 ){
if( iAjustKey==1 )
Canvas->Draw( iLeft, iOriTop, m_pngChordUp );
else
Canvas->Draw( iLeft, iOriTop, m_pngChordDown );
iLeft += wAKey;
if(iMainKey==2 && iType>=3) //bIIIm7可紧凑些
iLeft -= 1;
}
if( g_bAlphaKey ){ //英文字母
TFont *fntOld = new TFont;
fntOld->Assign( Canvas->Font ); //保存原字体
Canvas->Brush->Style = bsClear;
Canvas->Font->Name = "Times New Roman";
Canvas->Font->Quality = TFontQuality::fqClearTypeNatural;
Canvas->Font->Color = RGB(60,43,23);
Canvas->Font->Style = TFontStyles()<<fsItalic<<fsBold;
Canvas->Font->Size = g_szFont16; //字母字体大小
Canvas->TextOut( iLeft, iTop, g_strAlphaTable[iMainKey] );
Canvas->Font->Assign( fntOld ); //恢复原字体
delete fntOld;
}
else{
int l = iLeft;
iTop += 5;
if( iMainKey<4 ){
Canvas->Draw( l, iTop, m_pngChordI ); //I
l += wIKey;
if( iMainKey==3 ){
Canvas->Draw( l, iTop, m_pngChordV ); //IV
}
else if( iMainKey>0 ){
Canvas->Draw( l, iTop, m_pngChordI ); //II
l += wIKey;
if( iMainKey==2 ){
Canvas->Draw( l, iTop, m_pngChordI ); //III
}
}
}
else{
l += 2;
Canvas->Draw( l, iTop, m_pngChordV ); //V
l += wVKey;
if( iMainKey>4 ){
Canvas->Draw( l, iTop, m_pngChordI ); //VI
l += wIKey;
if( iMainKey==6 ){
Canvas->Draw( l, iTop, m_pngChordI ); //VII
l += wIKey;
}
}
}
}
if( iType>0 ){
iTop = iOriTop + 11;
iLeft += wMKey;
if(iMainKey!=3 || iType<3) //#IVm7可紧凑些
iLeft += 1;
//绘制A
if( iType==7 ){ //M
Canvas->Draw( iLeft, iTop, m_pngChordMaj );
iLeft += 8;
}
else if( iType>=4 ){ //s
Canvas->Draw( iLeft, iTop+1, m_pngChordSus );
iLeft += 6;
}
else if( iType==1 || iType==3 ){ //m
Canvas->Draw( iLeft, iTop+2, m_pngChordMin );
iLeft += 8;
}
else if( iType==2 ){
iLeft += 2;
}
//绘制N
if( iType==2 ){ //7
Canvas->Draw( iLeft, iTop, m_pngChord7 );
}
else if( iType==3 || iType==7 ){ //7
if( iMainKey==6 && iAjustKey ) //保证bVII不出格
iLeft--;
Canvas->Draw( iLeft, iTop, m_pngChord7 );
}
else if( iType==4 ){ //2
Canvas->Draw( iLeft, iTop, m_pngChord2 );
}
else if( iType==5 ){ //4
Canvas->Draw( iLeft, iTop, m_pngChord4 );
}
else if( iType==6 ){ //6
Canvas->Draw( iLeft, iTop, m_pngChord6 );
}
}
}
//-----------------------------------------------------------------------------
void TContentPanel::SetSelectRange( int iStartBar, int iStartPoint,
int iEndBar, int iEndPoint, bool bInvalid )
{
SelectRange( iStartBar, iStartPoint, iEndBar, iEndPoint, bInvalid );
}
//-----------------------------------------------------------------------------
void TContentPanel::GetSelectRange( int& iStartBar, int& iStartPoint,
int& iEndBar, int& iEndPoint )
{
iStartBar = m_iSelBarStart;
iStartPoint = m_iSelPointStart;
iEndBar = m_iSelBarEnd;
iEndPoint = m_iSelPointEnd;
}
//-----------------------------------------------------------------------------
void TContentPanel::AddNewBar( int iBar )
{
int iRow, iCol;
m_nBarNum++;
if( m_bVertical ){
m_nRowNum = m_nBarNum / m_nColumnNum;
if( m_nBarNum % m_nColumnNum>0 ){
m_nRowNum++;
}
if( m_nRowNum>m_nRowShow ){
m_sbVert->SetRange( 0, m_nRowNum-1 );
//m_sbVert->SetPageSize( m_nRowShow );
}
iRow = iBar / m_nColumnNum - m_iBeginShowRow;
if( iRow>(m_nRowShow-1) ){
int nRowScroll = min( m_nRowShow+m_iBeginShowRow-1, m_nRowNum-iRow ); // 显示到第2行
ScrollView( nRowScroll );
}
else{
iCol = iBar % m_nColumnNum;
TRect rectNew(0,0,0,0);
rectNew.left = iCol * m_nBarWidth + m_nLeftBound - 1;
rectNew.right = rectNew.left + m_nBarWidth + 2; //包含左右边框
rectNew.top = iRow * m_nBarHeight + m_nTopBound;
rectNew.bottom = rectNew.top + m_nBarHeight + 2; //包含上下边框
InvalidateRect( Handle, &rectNew, FALSE );
}
}
else{
if( m_nBarNum > m_nColumnNum ){
int nRange = m_nBarNum;
int nDrawWidth = ClientWidth - m_nLeftOriBound - m_nRightBound;
if( nDrawWidth % m_nBarWidth > 0 )
nRange++;
m_sbHoriz->SetRange( 0, nRange-1 );
if( iBar >= m_iBeginShowBar + m_nColumnNum ){
}
else{
TRect rectNew(0,0,0,0);
rectNew.left = (iBar-m_iBeginShowBar) * m_nBarWidth + m_nLeftBound - 1;
rectNew.right = rectNew.left + m_nBarWidth + 2; //包含左右边框
rectNew.top = m_nTopBound;
rectNew.bottom = rectNew.top + m_nBarHeight + 2; //包含上下边框
InvalidateRect( Handle, &rectNew, FALSE );
}
}
}
}
//-----------------------------------------------------------------------------
void TContentPanel::DrawDragImg( int mode )
{
w_imgDrag = new TImage(this);
if( mode==DM_ADJUSTWIDTH || mode==DM_ADJUSTHEADER ){
COLORREF clrPixel[2] = { clWhite, clBlack };
w_imgDrag->Width = 4;
w_imgDrag->Height = Height-2;
TRect rcDraw( 0, 0, w_imgDrag->Width, w_imgDrag->Height );
for( int i=0; i<w_imgDrag->Width; i++ ){
for( int j=0; j<w_imgDrag->Height; j++ ){
w_imgDrag->Canvas->Pixels[i][j] = clrPixel[(i+j)%2];
}
}
}
else if( mode==DM_ADJUSTSTAGE ){
w_imgDrag->Width = m_iSelBarEnd > m_iSelBarStart ? 160 : 120;
w_imgDrag->Height = 24;
TRect rcDraw( 0, 0, w_imgDrag->Width, w_imgDrag->Height );
//绘制底色
w_imgDrag->Canvas->Brush->Color = clrBackboard;
w_imgDrag->Canvas->FillRect( rcDraw );
//绘制列表项文字
w_imgDrag->Canvas->Font->Name = g_strTxtFontName;
w_imgDrag->Canvas->Font->Quality = TFontQuality::fqClearTypeNatural;
w_imgDrag->Canvas->Font->Size = g_szFont9;
w_imgDrag->Canvas->Font->Style = TFontStyles()<<fsBold;
w_imgDrag->Canvas->Font->Color = clrSelText;
char str[256];
if( m_iSelBarEnd>m_iSelBarStart )
sprintf( str, "第 %d - %d 小节", m_iSelBarStart+1, m_iSelBarEnd+1 );
else
sprintf( str, "第 %d 小节", m_iSelBarStart+1 );
String strCaption = str;
int Y = rcDraw.Top + ( w_imgDrag->Height - Canvas->TextHeight(strCaption) )/2;
rcDraw.Left += (w_imgDrag->Width - Canvas->TextWidth(strCaption))/2;
w_imgDrag->Canvas->Brush->Style = bsSolid;
w_imgDrag->Canvas->TextRect( rcDraw, rcDraw.Left, Y, strCaption );
}
else if( mode==DM_ADJUSTAUDIO ){
int iBarStart = m_iSelBarStart<0 ? 0 : m_iSelBarStart,
iBarEnd = m_iSelBarEnd<0 ? m_nBarNum-1 : m_iSelBarEnd,
iPointStart = m_iSelPointStart<0 ? 0 : m_iSelPointStart,
iPointEnd = m_iSelPointEnd<0 ? 119 : m_iSelPointEnd,
nWidth = ( iBarEnd - iBarStart ) * POINTS_PER_BAR + iPointEnd - iPointStart;
w_imgDrag->Width = nWidth > POINTS_PER_BAR ? POINTS_PER_BAR : nWidth;
w_imgDrag->Height = 25;
TRect rcDraw( 0, 0, w_imgDrag->Width, w_imgDrag->Height );
//绘制底色
w_imgDrag->Canvas->Brush->Color = clrBackboard;
w_imgDrag->Canvas->FillRect( rcDraw );
//绘制波形
int mid = w_imgDrag->Height/2 + 1,
gap = nWidth / 120;
if( gap<1 )
gap = 1;
w_imgDrag->Canvas->Pen->Color = clrWave[0];
int iPos = 0, p = iPointStart;
for( int i=iBarStart; i<=iBarEnd && iPos<120; i++ ){
TWaveBar *pBar = g_aAudioTracks[g_iSelAudio]->lstBars[i];
while( p<POINTS_PER_BAR && iPos<120 ){
if( pBar->aVols[p]>0 && pBar->aVols[p]<0x80000000 ){
DWORD wLeft = LOWORD(pBar->aVols[p]),
wRight = HIWORD(pBar->aVols[p]),
yBottom = mid + (12 * wRight )/0x8000,
yTop = mid - (12 * wLeft )/0x8000;
if( yBottom>yTop ){
w_imgDrag->Canvas->MoveTo( iPos, yTop );
w_imgDrag->Canvas->LineTo( iPos, yBottom );
}
}
iPos++;
p += gap;
}
if( iPos<120 )
p -= POINTS_PER_BAR;
}
m_iDragAudio = g_iSelAudio;
}
w_bDraging = true;
w_iDragMode = mode;
}
//---------------------------------------------------------------------------
bool TContentPanel::ShowDragImg( bool bShow, int iState )
{
bool bCanDrop = false;
int w = w_imgDrag->Width,
h = w_imgDrag->Height;
TPoint ptOld( w_xOldDrag, w_yOldDrag ),
ptNew( w_xImgDrag, w_yImgDrag );
RECT rtInvalid;
ptOld = ScreenToClient( ptOld );
ptNew = ScreenToClient( ptNew );
if( w_iDragMode==DM_ADJUSTWIDTH || w_iDragMode==DM_ADJUSTHEADER ){
rtInvalid.left = 0;
rtInvalid.right = 0;
rtInvalid.top = 1;
rtInvalid.bottom = Height-1;
if( ptOld.X>0 && ptOld.X<Width
|| ptOld.X+w>0 && ptOld.X+w<Width ){
rtInvalid.left = min( ptOld.X, rtInvalid.left );
rtInvalid.right = max( ptOld.X+w, rtInvalid.right );
}
if( bShow && (ptNew.X>0 && ptNew.X<Width
|| ptNew.X+w>0 && ptNew.X+w<Width )){
rtInvalid.left = min( ptNew.X, rtInvalid.left );
rtInvalid.right = max( ptNew.X+w, rtInvalid.right );
}
if( rtInvalid.left<0 ) rtInvalid.left = 0;
if( rtInvalid.right>Width ) rtInvalid.right = Width;
if( rtInvalid.right>rtInvalid.left ){
InvalidateRect( Handle, &rtInvalid, false );
}
if( !bShow && w_iDragMode==DM_ADJUSTHEADER ){
m_nTrkHdrWidth = ptNew.x;
CalcViewArea();
InvalidateRgn( Handle, NULL, true );
}
}
else if( w_iDragMode==DM_ADJUSTSTYLE || w_iDragMode==DM_ADJUSTSTAGE
|| w_iDragMode==DM_ADJUSTAUDIO ){
TPoint ptMouse( ptNew.X + w_xOffDrag, ptNew.Y + w_yOffDrag );
rtInvalid.left = Width;
rtInvalid.right = 0;
rtInvalid.top = Height;
rtInvalid.bottom = 0;
if( ptOld.Y>0 && ptOld.Y<Height
|| ptOld.Y+h>0 && ptOld.Y+h<Height ){
rtInvalid.top = min( ptOld.Y, rtInvalid.top );
rtInvalid.bottom = max( ptOld.Y+h, rtInvalid.bottom );
}
if( ptOld.X>0 && ptOld.X<Width
|| ptOld.X+w>0 && ptOld.X+w<Width ){
rtInvalid.left = min( ptOld.X, rtInvalid.left );
rtInvalid.right = max( ptOld.X+w, rtInvalid.right );
}
if( bShow ){
if( ptNew.Y>0 && ptNew.Y<Height
|| ptNew.Y+h>0 && ptNew.Y+h<Height ){
rtInvalid.top = min( ptNew.Y, rtInvalid.top );
rtInvalid.bottom = max( ptNew.Y+h, rtInvalid.bottom );
}
if( ptNew.X>0 && ptNew.X<Width
|| ptNew.X+w>0 && ptNew.X+w<Width ){
rtInvalid.left = min( ptNew.X, rtInvalid.left );
rtInvalid.right = max( ptNew.X+w, rtInvalid.right );
}
bCanDrop = HandleHoverEvent( ptMouse );
}
else{
if( ( w_iDragMode==DM_ADJUSTSTYLE || w_iDragMode==DM_ADJUSTSTAGE )
&& ( m_iSelBarStart>=0 || m_iDropBar>=0 )
&& ( !m_pItem || (m_pItem->iType!=SEGTYPE_STYLE
&& m_pItem->iType!=SEGTYPE_TRACK ))){ //处理Drop事件
int iHitType = -1;
DWORD dwHit = HitTest( ptMouse.X, ptMouse.Y, iHitType );
if( iHitType>=BAR_TITLE ){
HandleDropEvent( iState );
SetFocus();
}
}
else if( w_iDragMode==DM_ADJUSTAUDIO ){
HandleDropEvent( iState );
}
if( m_pTimer ){
delete m_pTimer;
m_pTimer = NULL;
}
SetDropBar( -1 );
m_pItem = NULL;
m_bDraging = false;
}
if( rtInvalid.top<0 ) rtInvalid.top = 0;
if( rtInvalid.bottom>Height ) rtInvalid.bottom = Height;
if( rtInvalid.left<0 ) rtInvalid.left = 0;
if( rtInvalid.right>Width ) rtInvalid.right = Width;
if( rtInvalid.bottom>rtInvalid.top && rtInvalid.right>rtInvalid.left ){
InvalidateRect( Handle, &rtInvalid, false );
}
if( bShow ){
SetScrollTimer( ptMouse );
}
}
return bCanDrop;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::WMMouseDown(TWMMouse &Message)
{
ptDown.x = ptDown.y = 0;
m_iMouseDownBar = m_iMouseDownPoint = -1;
if( Message.Keys & MK_RBUTTON ){
if( m_bBrush ){
m_bBrush = false;
Screen->Cursor = crDefault;
}
if( m_bDraging ){
m_bDraging = false;
if( m_iMode==VIEW_TRACK ){
SelectRange( -1, -1, -1, -1 );
}
else{
SelectBars( -1, -1 );
}
}
ReleaseCapture();
m_iMouseDownBar = m_iMouseDownPoint = -1;
m_pItem = NULL;
m_PopupMenu->ClearItems();
if( m_iMode==VIEW_INIT || m_nBarNum==0 )
return;
CMenuItem* pMenuItem = NULL;
int iHitType = -1;
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType, true );
if( iHitType<=BAR_CURSOR ){
if( !m_bVertical ){
pMenuItem = m_PopupMenu->CreateMenu( "新增音频轨道", "", DoTrackAdd, ST_AUDIO );
pMenuItem->Enabled = g_aAudioTracks.size()<MAX_AUDIOTRACK;
m_PopupMenu->CreateMenu( "新增MIDI轨道...","",DoTrackAdd, ST_MIDI );
}
else
return;
}
else{
int iView = VIEW_TRACK;
if( iHitType<BAR_TRACK ){
SelectTrack( -1, -1, -1 );
if( iHitType==BAR_TITLE )
iView = VIEW_STYLE;
else if( iHitType==BAR_DATA )
iView = VIEW_CHORD;
}
if( iView!=m_iMode ){
Application->MainForm->Perform( UM_SETVIEWMODE, iView, 0 );
}
int iHitBar = LOWORD(dwHit);
if( iHitType>=BAR_LEFT ){
int iHitTrack = -1;
if( iHitType>=HOVER_SOLO )
iHitTrack = iHitType - HOVER_SOLO;
else if( iHitType>=HOVER_MUTE )
iHitTrack = iHitType - HOVER_MUTE;
else
iHitTrack = iHitType - BAR_LEFT;
SelectTrack( iHitTrack, -1, -1 );
bool bMute = m_aTracks[iHitTrack]->pTrack->IsMute(),
bSolo = m_aTracks[iHitTrack]->pTrack->IsSolo();
m_PopupMenu->CreateMenu( bMute ? "取消静音" : "静音", "", DoTrackMute );
m_PopupMenu->CreateMenu( bSolo ? "取消独奏" : "独奏", "",DoTrackSolo );
m_PopupMenu->CreateMenu( "删除该轨道", "", DoTrackDel, IDM_TRKSHOW+iHitTrack );
m_PopupMenu->CreateMenu( "隐藏该轨道", "", DoTrackHide, IDM_TRKSHOW+iHitTrack );
m_PopupMenu->CreateMenu( "轨道导出为...","",DoTrackSave );
m_PopupMenu->CreateMenu( "-" );
pMenuItem = m_PopupMenu->CreateMenu( "新增音频轨道", "", DoTrackAdd, ST_AUDIO );
pMenuItem->Enabled = g_aAudioTracks.size()<MAX_AUDIOTRACK;
m_PopupMenu->CreateMenu( "新增MIDI轨道...","",DoTrackAdd, ST_MIDI );
}
else if( iHitType>=BAR_TRACK ){
int iHitTrack = iHitType & 0xFF,
iHitPoint = HIWORD(dwHit);
if( iHitTrack!=m_iSelTrack || m_iSelBarStart<0 && m_iSelBarEnd<0
|| iHitBar<m_iSelBarStart
|| m_iSelBarEnd>=0 && iHitBar>m_iSelBarEnd
|| iHitBar==m_iSelBarStart && iHitPoint<m_iSelPointStart
|| iHitBar==m_iSelBarEnd && iHitPoint>m_iSelPointEnd ){
SelectTrack( iHitTrack, iHitBar, iHitPoint );
}
ptDown.X = Message.XPos;
ptDown.Y = Message.YPos;
bool bMute = m_aTracks[iHitTrack]->pTrack->IsMute(),
bSolo = m_aTracks[iHitTrack]->pTrack->IsSolo();
m_PopupMenu->CreateMenu( bMute ? "取消静音" : "静音", "", DoTrackMute );
m_PopupMenu->CreateMenu( bSolo ? "取消独奏" : "独奏", "",DoTrackSolo );
m_PopupMenu->CreateMenu( "删除该轨道", "", DoTrackDel, IDM_TRKSHOW+iHitTrack );
m_PopupMenu->CreateMenu( "隐藏该轨道", "", DoTrackHide, IDM_TRKSHOW+iHitTrack );
m_PopupMenu->CreateMenu( "轨道导出为...","",DoTrackSave );
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "全选", "Ctrl+A", DoSelectAll );
if( m_aTracks[iHitTrack]->type==ST_AUDIO ){
pMenuItem = m_PopupMenu->CreateMenu( "复制所选音频", "Ctrl+C", DoAudioCopy );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
pMenuItem = m_PopupMenu->CreateMenu( "剪切所选音频", "Ctrl+X", DoAudioCut );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
pMenuItem = m_PopupMenu->CreateMenu( "删除所选音频", "Ctrl+Del", DoAudioDelete );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
if( m_iCopyBarStart>=0 ){
m_PopupMenu->CreateMenu( "-" );
String strText = "粘贴";
strText += m_bCut ? "剪切的音频" : "复制的音频";
pMenuItem = m_PopupMenu->CreateMenu( strText, "Ctrl+V", DoAudioPaste );
pMenuItem->Enabled = m_iCopyBarStart>=0;
}
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "设为录音起点", "", DoSetSelPosStart );
m_PopupMenu->CreateMenu( "设为录音终点", "", DoSetSelPosEnd );
pMenuItem = m_PopupMenu->CreateMenu( "取消录音起点", "", DoDelSelPosStart );
pMenuItem->Enabled = m_iSelBarStart>=0;
pMenuItem = m_PopupMenu->CreateMenu( "取消录音终点", "", DoDelSelPosEnd );
pMenuItem->Enabled = m_iSelBarEnd>=0;
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "插入音频片段...","Ctrl+Ins",DoAudioLoad );
bool bSP = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
CMenuItem *pMSPFx = NULL,
*pMSPVst = NULL,
*pMSP = m_PopupMenu->CreateMenu( "局部音效处理" ),
*pMAdd = m_PopupMenu->CreateMenu( "添加轨道音效" ),
*pMAddFx = pMAdd->AppendMenu( "Fx音效" ),
*pMAddVst = pMAdd->AppendMenu( "VST音效" );
pMSP->Enabled = bSP;
pMAddVst->Enabled = !g_lstVSTFx.empty();
if( bSP ){
pMSPFx = pMSP->AppendMenu( "Fx音效" );
pMSPVst = pMSP->AppendMenu( "VST音效" );
pMSPVst->Enabled = !g_lstVSTFx.empty();
}
for( int i=0; i<MAX_FX_NUM; i++ ){
if( pMSPFx )
pMSPFx->AppendMenu( g_strEffect[i], "", DoAudioFxProcess, i );
if( i<MAX_FX_NUM-1 )
pMAddFx->AppendMenu( g_strEffect[i], "", DoAudioAddFx, i );
}
if( !g_lstVSTFx.empty() ){
for( int i=0; i<g_lstVSTFx.size(); i++ ){
VSTINFO* pVST = g_lstVSTFx[i];
char fname[128],
*name = strrchr( pVST->strFileName, '\\' )+1,
*ext = strrchr( pVST->strFileName, '.' );
if( ext>name ){
strncpy( fname, name, ext-name );
fname[ext-name] = '\0';
}
else
strcpy(fname, name );
if( !pVST->aPlugins.empty() )
strcat( fname, " ..." );
if( pMSPVst )
pMSPVst->AppendMenu( fname, "", DoAudioVstProcess, i );
pMAddVst->AppendMenu( fname, "", DoAudioAddVst, i );
}
}
}
else{
bool bContent=false, bSwitch=false, bInsert=true;
if( m_iSelBarStart>=0 && m_iSelBarEnd>0 ){
TMidiTrack* pMT = (TMidiTrack*)m_aTracks[iHitTrack]->pTrack;
int iBStage = FindStage( m_iSelBarStart, NULL ),
iEStage = FindStage( m_iSelBarEnd, NULL );
for( int i=iBStage; i<=iEStage; i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
if( !bSwitch && pStage->iSegType<=SEGTYPE_FILL )
bSwitch = true;
if( bInsert && pMT->IsDrum() && pStage->aTracks[0]->iChanNo==9 )
bInsert = false;
}
for( int i=0; i<pMT->aStages.size(); i++ ){
int s = pMT->aStages[i];
if( s>=iBStage && s<=iEStage ){
bContent = true;
break;
}
else if( s>iEStage ){
break;
}
}
}
pMenuItem = m_PopupMenu->CreateMenu( "插入织体...", "Ctrl+Ins", DoInsertTexture );
pMenuItem->Enabled = !bContent && bSwitch && bInsert;
pMenuItem = m_PopupMenu->CreateMenu( "删除所选织体", "Ctrl+Del", DoDeleteTexture );
pMenuItem->Enabled = bContent;
pMenuItem = m_PopupMenu->CreateMenu( "更换所选织体...", "", DoSwitchTexture );
pMenuItem->Enabled = bContent && bSwitch;
pMenuItem = m_PopupMenu->CreateMenu( "更换所选乐器/音色...", "", DoSwitchFontProg );
pMenuItem->Enabled = bContent;
m_PopupMenu->CreateMenu( "更换轨道织体...", "", DoTrackSwitchTexture );
m_PopupMenu->CreateMenu( "更换轨道乐器/音色...", "", DoTrackSwitchFontProg );
}
}
else if( iHitType==BAR_DATA ){
int iCell = GetCell( HIWORD(dwHit) );
bool bCanCopy = false;
if( m_iSelBarStart<0 || iHitBar<m_iSelBarStart
|| iHitBar>m_iSelBarEnd
|| iHitBar==m_iSelBarStart && iCell<m_iSelCellStart
|| iHitBar==m_iSelBarEnd && iCell>m_iSelCellEnd ){
int iFirstBar, iHitStage = FindStage( iHitBar, &iFirstBar );
TOpusStage *pHitStage = g_lstOpusStages[iHitStage];
if( pHitStage->iSegType<=SEGTYPE_FILL ){
int iEndBar = iHitBar,
iEndCell = iCell;
if( m_iCopyBarStart>=0 ){
//计算已复制和弦个数
int nChordRemain = (m_iCopyBarEnd - m_iCopyBarStart) * g_nChordNumPerBar
- m_iCopyCellStart + m_iCopyCellEnd + 1 ;
int iStage = iHitStage,
iStartBar = iHitBar,
iStartCell = iCell,
iLastBar = iFirstBar + pHitStage->aBars.size() - 1;
TOpusStage * pStage = pHitStage;
while( true ){
int nCellCount = ( iLastBar - iStartBar + 1 ) * g_nChordNumPerBar
- iStartCell;
if( nCellCount >= nChordRemain ){
iEndBar = iStartBar + nChordRemain / g_nChordNumPerBar;
iEndCell = iStartCell + nChordRemain % g_nChordNumPerBar - 1;
if( iEndCell>=g_nChordNumPerBar ){
iEndBar++;
iEndCell -= g_nChordNumPerBar;
}
else if( iEndCell<0 ){
iEndBar--;
iEndCell = g_nChordNumPerBar - 1;
}
break;
}
else{
iEndBar = iLastBar;
iEndCell = g_nChordNumPerBar - 1;
nChordRemain -= nCellCount;
iStage++;
if( iStage<g_lstOpusStages.size() ){
pStage = g_lstOpusStages[iStage];
if( pStage->iSegType<=SEGTYPE_FILL ){
iStartBar = iLastBar + 1;
iStartCell = 0;
iLastBar = iStartBar + pStage->aBars.size() - 1;
}
else
break;
}
else
break;
}
}
}
SelectCells( iHitBar, iCell, iEndBar, iEndCell );
bCanCopy = true;
}
}
else if( ( iHitBar>m_iSelBarStart || iHitBar==m_iSelBarStart
&& iCell>=m_iSelCellStart )
&& ( iHitBar<m_iSelBarEnd || iHitBar==m_iSelBarEnd
&& iCell<=m_iSelCellEnd ) ){
bCanCopy = true;
}
pMenuItem = m_PopupMenu->CreateMenu( "复制和弦","Ctrl+C",DoChordCopy );
pMenuItem->Enabled = bCanCopy && m_iSelBarStart>=0;
pMenuItem = m_PopupMenu->CreateMenu( "粘贴和弦","Ctrl+V",DoChordPaste );
pMenuItem->Enabled = bCanCopy && m_iCopyBarStart>=0;
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "与前一和弦相同","Ctrl+Del",DoChordDelete );
bool bCanDelete = false;
if( bCanCopy ){
if( m_iSelCellStart>0 ){
bCanDelete = true;
}
else{
int iFirstBar, iSelStage = FindStage( m_iSelBarStart, &iFirstBar );
if( m_iSelBarStart!=iFirstBar ){
bCanDelete = true;
}
else if( iSelStage>0 ){
TOpusStage *pPreStage = g_lstOpusStages[iSelStage-1];
if( pPreStage->iSegType<=SEGTYPE_FILL ){
bCanDelete = true;
}
}
}
}
pMenuItem->Enabled = bCanDelete;
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "导出伴奏...","",DoTrackSave );
}
else if( iHitType==BAR_TITLE ){
bool bCanInsert = m_iCopyBarStart!=-1;
if( iHitBar>=m_iCopyBarStart && iHitBar<=m_iCopyBarEnd ){
SelectBars( m_iCopyBarStart, m_iCopyBarEnd );
}
else if( m_iSelBarStart<0 || iHitBar<m_iSelBarStart || iHitBar>m_iSelBarEnd ){
int iFirstBar,
iStage = FindStage( iHitBar, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
if( pStage->iSegType>=SEGTYPE_INTRO ){
SelectBars( iFirstBar, iFirstBar+pStage->aBars.size()-1 );
}
else{
SelectBars( iHitBar, iHitBar );
}
}
bool bSel = m_iSelBarStart>=0;
bool bCanCopy = bSel;
if( m_iSelBarEnd>=0 ){
int iStage = FindStage( m_iSelBarEnd, NULL );
if( g_lstOpusStages[iStage]->iSegType==SEGTYPE_ENDING )
bCanCopy = false;
}
pMenuItem = m_PopupMenu->CreateMenu( "复制小节","Ctrl+C",DoBarsCopy );
pMenuItem->Enabled = bCanCopy;
pMenuItem = m_PopupMenu->CreateMenu( "剪切小节","Ctrl+X",DoBarsCut );
pMenuItem->Enabled = bCanCopy;
m_PopupMenu->CreateMenu( "-" );
pMenuItem = m_PopupMenu->CreateMenu( "插入空小节","Ctrl+Ins",DoInsertBlankBar );
pMenuItem->Enabled = bSel;
String strText = "插入";
if( m_iCopyBarStart>=0 ){
strText += m_bCut ? "剪切的小节" : "复制的小节";
pMenuItem = m_PopupMenu->CreateMenu( strText,"Ctrl+V",DoBarsInsert );
pMenuItem->Enabled = bSel && m_iCopyBarStart>=0;
}
pMenuItem = m_PopupMenu->CreateMenu( "删除所选小节","Ctrl+Del",DoBarsDelete );
pMenuItem->Enabled = bSel;
m_PopupMenu->CreateMenu( "-" );
pMenuItem = m_PopupMenu->CreateMenu( "改变所选小节调号" );
pMenuItem->Enabled = bSel;
if( bSel ){
for( int i=0; i<KEY_NUM; i++ ){
pMenuItem->AppendMenu( g_strMelodyKey[i], "", DoBarsChangeKey, i );
}
}
pMenuItem = m_PopupMenu->CreateMenu( "添加乐器织体...", "", DoInsertTexture );
bool bTexture = false;
if( /*!m_bVertical &&*/ bSel ){
int iBS = FindStage( m_iSelBarStart, NULL ),
iES = FindStage( m_iSelBarEnd, NULL );
for( int i=iBS; i<=iES; i++ ){
if( g_lstOpusStages[i]->iSegType<SEGTYPE_INTRO ){
bTexture = true;
break;
}
}
}
pMenuItem->Enabled = bTexture;
m_PopupMenu->CreateMenu( "-" );
m_PopupMenu->CreateMenu( "全选", "Ctrl+A", DoSelectAll );
}
}
m_PopupMenu->Parent = this;
m_PopupMenu->Show(Message.XPos,Message.YPos);
return;
}
if( !(Message.Keys & MK_LBUTTON) )
return;
if( Screen->Cursor==crHSplit ){ //调整宽度
int iMode = Message.XPos<m_nLeftOriBound ? DM_ADJUSTWIDTH : DM_ADJUSTHEADER;
DrawDragImg( iMode );
TPoint pt( 0, 1 );
if( iMode==DM_ADJUSTHEADER )
pt.x = m_nLeftBound;
w_xOffDrag = Message.XPos - pt.X;
w_yOffDrag = Message.YPos;
pt = ClientToScreen( pt );
w_xOldDrag = w_xImgDrag = pt.X;
w_yOldDrag = w_yImgDrag = pt.Y;
SetCapture( Handle );
}
else{
SetFocus();
if( m_nBarNum>0 ){
int iHitType = -1;
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType, !m_bBrush );
int iHitBar = LOWORD(dwHit),
iHitPoint = HIWORD(dwHit);
if( m_bBrush ){
if( Screen->Cursor!=crBrushNo && iHitType>BAR_CURSOR && iHitType<BAR_LEFT ){
if( iHitType<BAR_TRACK )
SelectBars( iHitBar, iHitBar );
else{
int iHitTrack = iHitType & 0xFF;
SelectTrack( iHitTrack , -1, -1 );
SelectRange( iHitBar, 0, iHitBar, m_nBarWidth-1 );
}
m_iMouseDownBar = iHitBar;
m_iMouseDownPoint = iHitPoint;
m_bDraging = true;
}
else{
m_bBrush = false;
}
}
else{
if( iHitType==BAR_CURSOR ){ //设置播放位置
SetPlayPoint( iHitBar, iHitPoint );
Application->MainForm->Perform( UM_SHOWPLAYTIME, iHitBar, iHitPoint );
return;
}
//符合条件准备拖动
if( iHitType>=BAR_TITLE ){ //左键点中
int iView = VIEW_TRACK;
if( iHitType<BAR_TRACK ){
SelectTrack( -1, -1, -1 );
if( iHitType==BAR_TITLE )
iView = VIEW_STYLE;
else if( iHitType==BAR_DATA )
iView = VIEW_CHORD;
}
if( iView!=m_iMode ){
Application->MainForm->Perform( UM_SETVIEWMODE, iView, 0 );
}
}
if( iHitType<0 || iHitBar<0 ){
if( m_iMode==VIEW_STYLE ){ //风格模式
SelectBars( -1, -1 );
SelectCopyBars( -1, -1 );
}
else if( m_iMode==VIEW_CHORD ){ //和弦模式
SelectCells( -1, -1, -1, -1 );
SelectCopyCells( -1, -1, -1, -1 );
((TChordPanel*)m_pChordPanel)->EnableChordModify( false, -1, -1, -1 );
}
else{ //轨道模式
SelectTrack( -1, -1, -1 );
SelectRange( -1, -1, -1, -1 );
SelectCopyPos( -1, -1, -1, -1 );
}
}
else if( iHitType>=HOVER_MUTE ){
int iHitTrack = -1, iState = -1;
if( iHitType>=HOVER_SOLO ){
iHitTrack = iHitType - HOVER_SOLO;
iState = TRACK_SOLO;
}
else{
iHitTrack = iHitType - HOVER_MUTE;
iState = TRACK_MUTE;
}
SelectTrack( iHitTrack , -1, -1 );
((TTrackPanel*)m_pTrackPanel)->OnTrackStateChanged( iState );
return;
}
else if( iHitType>=BAR_LEFT ){
int iHitTrack = iHitType & 0xFF;
SelectTrack( iHitTrack , -1, -1 );
return;
}
else if( iHitType>=BAR_TRACK ){
int iHitTrack = iHitType & 0xFF;
if( iHitTrack!=m_iSelTrack || m_iSelBarStart<0 && m_iSelBarEnd<0
|| iHitBar<m_iSelBarStart
|| m_iSelBarEnd>=0 && iHitBar>m_iSelBarEnd
|| iHitBar==m_iSelBarStart && iHitPoint<m_iSelPointStart
|| iHitBar==m_iSelBarEnd && iHitPoint>m_iSelPointEnd ){
SelectTrack( iHitTrack , iHitBar, iHitPoint );
//SelectRange( -1, -1, -1, -1 );
}
m_bDragReady = true;
}
else if( iHitType==BAR_TITLE ){
if( m_iSelBarStart<0 && m_iSelBarEnd<0
|| iHitBar<m_iSelBarStart
|| m_iSelBarEnd>=0 && iHitBar>m_iSelBarEnd ){
SelectBars( iHitBar, iHitBar );
m_bDraging = true;
}
else{
m_bDragReady = true;
}
}
else if( iHitType==BAR_DATA ){
int iHitCell = GetCell( iHitPoint );
int iFirstBar, iStage = FindStage( iHitBar, &iFirstBar );
TOpusStage *pStage = g_lstOpusStages[iStage];
if( pStage->iSegType<=SEGTYPE_FILL ){
SelectCells( iHitBar, iHitCell, iHitBar, iHitCell );
m_iMinSelBar = iFirstBar;
m_iMaxSelBar = iFirstBar + pStage->aBars.size() - 1;
for( int i=iStage-1; i>=0; i-- ){
pStage = g_lstOpusStages[i];
if( pStage->iSegType<=SEGTYPE_FILL )
m_iMinSelBar -= pStage->aBars.size();
else
break;
}
for( int i=iStage+1; i<g_lstOpusStages.size(); i++ ){
pStage = g_lstOpusStages[i];
if( pStage->iSegType<=SEGTYPE_FILL )
m_iMaxSelBar += pStage->aBars.size();
else
break;
}
m_bDraging = true;
}
else{
SelectCells( -1, -1, -1, -1 );
}
}
if( m_bDragReady || m_bDraging ){
ptDown.X = Message.XPos;
ptDown.Y = Message.YPos;
m_iMouseDownBar = iHitBar;
m_iMouseDownPoint = iHitPoint;
SetCapture( Handle );
}
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::UMMouseMove(TWMMouseMove &Message)
{
if( m_bDragReady ){
if( abs(Message.XPos-ptDown.X)>=4
|| abs(Message.YPos-ptDown.Y)>=4 ){ //开始拖动
m_bDragReady = false;
if( m_iMode==VIEW_TRACK ){
int iHitType = -1;
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType );
int iHitBar = LOWORD(dwHit),
iHitPoint = HIWORD(dwHit);
if( iHitType<BAR_TRACK )
return;
if( m_aTracks[m_iSelTrack]->type==ST_AUDIO ){
if( m_iSelBarStart>=0 || m_iSelBarEnd>=0 ){ //移动音频
DrawDragImg( DM_ADJUSTAUDIO );
int left = ptDown.X,
top = ptDown.Y - 10;
TPoint pt( left, top );
pt = ClientToScreen( pt );
w_xOldDrag = w_xImgDrag = pt.X;
w_yOldDrag = w_yImgDrag = pt.Y;
w_xOffDrag = -1;
w_yOffDrag = 10;
SelectCopyPos( -1, -1, -1, -1 );
}
else{
if( iHitBar>m_iMouseDownBar || iHitBar==m_iMouseDownBar
&& iHitPoint>m_iMouseDownPoint )
SelectRange( m_iMouseDownBar, m_iMouseDownPoint, iHitBar, iHitPoint );
else
SelectRange( iHitBar, iHitPoint, m_iMouseDownBar, m_iMouseDownPoint );
}
}
else{
int iStartBar = min( m_iMouseDownBar, iHitBar ),
iEndBar = max( m_iMouseDownBar, iHitBar );
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd )
SelectRange( iStartBar, 0, iEndBar, m_nBarWidth-1 );
}
m_bDraging = true;
}
else if( m_iMode==VIEW_STYLE ){
if( m_iSelBarStart>=0 ){ //调整段落
int iLSBar, iStage = FindStage( m_iSelBarEnd, &iLSBar );
if( g_lstOpusStages[iStage]->iSegType==SEGTYPE_ENDING ){
int iFirstStage = FindStage( m_iSelBarStart, NULL );
if( iFirstStage!=iStage ){
if( m_iMouseDownBar < iLSBar ){
SelectBars( m_iSelBarStart, iLSBar-1 );
}
else{
SelectBars( iLSBar, m_iSelBarEnd );
}
}
}
DrawDragImg( DM_ADJUSTSTAGE );
int left = ptDown.X - 100,
top = ptDown.Y - 20;
TPoint pt( left, top );
pt = ClientToScreen( pt );
w_xOldDrag = w_xImgDrag = pt.X;
w_yOldDrag = w_yImgDrag = pt.Y;
w_xOffDrag = 100;
w_yOffDrag = 20;
m_bDraging = true;
}
}
}
}
else if( m_bDraging ){
int iHitType = -1;
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType );
if( iHitType>=0 ){
int iHitBar = LOWORD(dwHit);
int iStartBar = min( m_iMouseDownBar, iHitBar ),
iEndBar = max( m_iMouseDownBar, iHitBar );
if( m_iMode==VIEW_STYLE ){
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd )
SelectBars( iStartBar, iEndBar );
}
else if( m_iMode==VIEW_CHORD ){
int iStartCell = GetCell( m_iMouseDownPoint ),
iEndCell = iStartCell;
if( iHitBar>m_iMaxSelBar ){
iStartBar = m_iMouseDownBar;
iEndBar = m_iMaxSelBar;
iEndCell = g_nChordNumPerBar - 1;
}
else if( iHitBar<m_iMinSelBar ){
iStartBar = m_iMinSelBar;
iEndBar = m_iMouseDownBar;
iStartCell = 0;
}
else{
int iHitCell = GetCell( HIWORD(dwHit) );
if( iHitBar==m_iMouseDownBar ){
iStartCell = min( iStartCell, iHitCell );
iEndCell = max( iEndCell, iHitCell );
}
else if( iHitBar<m_iMouseDownBar )
iStartCell = iHitCell;
else
iEndCell = iHitCell;
}
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd
|| iStartCell!=m_iSelCellStart
|| iEndCell!=m_iSelCellEnd )
SelectCells( iStartBar, iStartCell, iEndBar, iEndCell );
}
else if( m_aTracks[m_iSelTrack]->type==ST_AUDIO ){
int iHitPoint = HIWORD(dwHit);
int iStartPoint = m_iMouseDownPoint,
iEndPoint = m_iMouseDownPoint;
if( iHitBar==m_iMouseDownBar ){
iStartPoint = min( iStartPoint, iHitPoint );
iEndPoint = max( iEndPoint, iHitPoint );
}
else if( iHitBar<m_iMouseDownBar )
iStartPoint = iHitPoint;
else
iEndPoint = iHitPoint;
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd
|| iStartPoint!=m_iSelPointStart
|| iEndPoint!=m_iSelPointEnd )
SelectRange( iStartBar, iStartPoint, iEndBar, iEndPoint );
}
else{
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd-1 )
SelectRange( iStartBar, 0, iEndBar, m_nBarWidth-1 );
}
}
TPoint ptMouse( Message.XPos, Message.YPos );
SetScrollTimer( ptMouse );
}
else if( m_nBarNum>0/* g_lstOpusStages.size()>0*/ ){
if( !Focused() )
SetFocus();
if( m_bBrush ){
int iCursor = crBrushNo,
iHitType = -1,
iBrushType = m_pItem->iType,
iBrushSegType = m_pItem->GetSegType();
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType, false );
if( iHitType>BAR_CURSOR && iHitType<BAR_LEFT ){
int iHitBar = LOWORD(dwHit),
iHitStage = FindStage( iHitBar, NULL );
TOpusStage * pHitStage = g_lstOpusStages[iHitStage];
int iHitSegType = pHitStage->iSegType;
if( iHitSegType<=SEGTYPE_FILL ){
if( iBrushType==SEGTYPE_SEGMENT && iHitType<BAR_TRACK ){
iCursor = crBrush;
}
else if( iBrushType==SEGTYPE_TRACK && iHitSegType==iBrushSegType ){
if( iHitType<BAR_TRACK ){
bool bAdd = true;
TTrack* pTrack = ((TTrackItem*)m_pItem)->pTrack;
if( pTrack->iChanNo==9 ){
for( int i=0; i<g_aMidiTracks.size(); i++ ){
if( g_aMidiTracks[i]->IsDrum() ){
bAdd = false;
break;
}
}
}
if( bAdd )
iCursor = crBrushAdd;
else
iCursor = crBrush;
}
else{
int iTrack = iHitType & 0xFF;
TShowTrack* pTrk = m_aTracks[iTrack];
if( pTrk->type==ST_MIDI ){
TMidiTrack* pMT = (TMidiTrack*)pTrk->pTrack;
TTrack* pTrack = ((TTrackItem*)m_pItem)->pTrack;
if( pMT->IsDrum() && pTrack->iChanNo==9
|| !pMT->IsDrum() && pTrack->iChanNo!=9 )
iCursor = crBrush;
}
}
}
}
}
Screen->Cursor = iCursor;
}
else if( !m_bVertical && Message.Keys==0 ){
int iHitType = -1, iTrack = -1, iHover = -1;
DWORD dwHit = HitTest( Message.XPos, Message.YPos, iHitType, true );
if( iHitType>=HOVER_SOLO ){
iTrack = iHitType - HOVER_SOLO;
iHover = TRACK_S_HOVER;
if( Hint.IsEmpty() ){
ShowHint = true;
Hint = "独奏开关";
}
else if( Hint.Compare("独奏开关") ){
ShowHint = false;
Hint = "";
}
}
else if( iHitType>=HOVER_MUTE ){
iTrack = iHitType - HOVER_MUTE;
iHover = TRACK_M_HOVER;
if( Hint.IsEmpty() ){
ShowHint = true;
Hint = "静音开关";
}
else if( Hint.Compare("静音开关") ){
ShowHint = false;
Hint = "";
}
}
else{
ShowHint = false;
Hint = "";
}
int nSMTop = m_nTopBound+m_nRowGapHeight+m_nTitleHeight+m_nChordHeight+SM_TOP;
for( int i=m_iBeginShowTrack; i<m_aTracks.size(); i++ ){
RECT rect;
TShowTrack* pTrk = m_aTracks[i];
if( iTrack==i && !(pTrk->iHover & iHover) ){
int lBox = LOWORD( dwHit ),
tBox = HIWORD( dwHit );
pTrk->iHover |= iHover;
SetRect( &rect, lBox, tBox, lBox+SM_SIZE, tBox+SM_SIZE );
InvalidateRect( Handle, &rect, false );
}
if( (pTrk->iHover & TRACK_S_HOVER) && (iTrack!=i || iHover!=TRACK_S_HOVER) ){
pTrk->iHover -= TRACK_S_HOVER;
SetRect( &rect, m_nTrkHdrWidth+SOLO_LEFT, nSMTop,
m_nTrkHdrWidth+SOLO_LEFT+SM_SIZE, nSMTop+SM_SIZE );
InvalidateRect( Handle, &rect, false );
}
if( (pTrk->iHover & TRACK_M_HOVER) && (iTrack!=i || iHover!=TRACK_M_HOVER) ){
pTrk->iHover -= TRACK_M_HOVER;
SetRect( &rect, m_nTrkHdrWidth+MUTE_LEFT, nSMTop,
m_nTrkHdrWidth+MUTE_LEFT+SM_SIZE, nSMTop+SM_SIZE );
InvalidateRect( Handle, &rect, false );
}
nSMTop += m_nTrackHeight;
}
}
}
}
//-----------------------------------------------------------------------------
void __fastcall TContentPanel::UMMouseUp(TWMMouse &Message)
{
TShiftState Shift(Message.Keys);
if( !Shift.Contains(ssLeft) )
return;
if( m_bDragReady || m_bDraging ){
if( m_bDragReady ){
//选中小节或前尾奏段
if( m_iMode==VIEW_STYLE ){
if( m_iSelBarStart<0 || m_iMouseDownBar<m_iSelBarStart
|| m_iMouseDownBar>m_iSelBarEnd ){
int iFirstBar,
iStage = FindStage( m_iMouseDownBar, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
if( pStage->iSegType>=SEGTYPE_INTRO ){
SelectBars( iFirstBar, iFirstBar+pStage->aBars.size()-1 );
}
else
SelectBars( m_iMouseDownBar, m_iMouseDownBar );
}
}
else if( m_iMode==VIEW_CHORD ){
int iCell = GetCell( m_iMouseDownPoint );
if( m_iSelBarStart<0 || m_iMouseDownBar<m_iSelBarStart
|| m_iMouseDownBar>m_iSelBarEnd
|| m_iMouseDownBar==m_iSelBarStart && iCell<m_iSelCellStart
|| m_iMouseDownBar==m_iSelBarEnd && iCell>m_iSelCellEnd ){
int iFirstBar, iDownStage = FindStage( m_iMouseDownBar, &iFirstBar );
TOpusStage *pDownStage = g_lstOpusStages[iDownStage];
if( pDownStage->iSegType<=SEGTYPE_FILL ){
int iEndBar = m_iMouseDownBar,
iEndCell = iCell;
if( m_iCopyBarStart>=0 ){
//计算已复制和弦个数
int nChordRemain = (m_iCopyBarEnd - m_iCopyBarStart) * g_nChordNumPerBar
- m_iCopyCellStart + m_iCopyCellEnd + 1 ;
int iStage = iDownStage,
iStartBar = m_iMouseDownBar,
iStartCell = iCell,
iLastBar = iFirstBar + pDownStage->aBars.size() - 1;
TOpusStage * pStage = pDownStage;
while( true ){
int nCellCount = ( iLastBar - iStartBar + 1 ) * g_nChordNumPerBar
- iStartCell;
if( nCellCount >= nChordRemain ){
iEndBar = iStartBar + nChordRemain / g_nChordNumPerBar;
iEndCell = iStartCell + nChordRemain % g_nChordNumPerBar - 1;
if( iEndCell>=g_nChordNumPerBar ){
iEndBar++;
iEndCell -= g_nChordNumPerBar;
}
else if( iEndCell<0 ){
iEndBar--;
iEndCell = g_nChordNumPerBar - 1;
}
break;
}
else{
iEndBar = iLastBar;
iEndCell = g_nChordNumPerBar - 1;
nChordRemain -= nCellCount;
iStage++;
if( iStage<g_lstOpusStages.size() ){
pStage = g_lstOpusStages[iStage];
if( pStage->iSegType<=SEGTYPE_FILL ){
iStartBar = iLastBar + 1;
iStartCell = 0;
iLastBar = iStartBar + pStage->aBars.size() - 1;
}
else
break;
}
else
break;
}
}
}
SelectCells( m_iMouseDownBar, iCell, iEndBar, iEndCell );
}
}
}
else{
if( m_iSelBarStart<0 || m_iMouseDownBar<m_iSelBarStart
|| m_iMouseDownBar>m_iSelBarEnd
|| m_iMouseDownBar==m_iSelBarStart
&& m_iMouseDownPoint<m_iSelPointStart
|| m_iMouseDownBar==m_iSelBarEnd
&& m_iMouseDownPoint>m_iSelPointEnd ){
SelectRange( -1, -1, -1, -1 );
}
}
}
else if( m_bDraging && m_iSelBarStart>=0 && m_iSelBarEnd>=0 ){
if( m_bBrush ){
if( Message.XPos<0 || Message.XPos>Width
|| Message.YPos<0 || Message.YPos>Height ){
if( m_iMode==VIEW_STYLE )
SelectBars( -1, -1 );
}
else
HandleBrush();
}
else if( m_iMode==VIEW_STYLE || m_iMode==VIEW_TRACK
&& m_aTracks[m_iSelTrack]->type==ST_MIDI ){
int iStartBar = m_iSelBarStart,
iEndBar = m_iSelBarEnd;
int iFirstBar,
iStage = FindStage( iStartBar, &iFirstBar );
TOpusStage* pStage1 = g_lstOpusStages[iStage];
if( pStage1->iSegType>=SEGTYPE_INTRO )
iStartBar = iFirstBar;
iStage = FindStage( iEndBar, &iFirstBar );
TOpusStage* pStage2 = g_lstOpusStages[iStage];
if( pStage1->iSegType>=SEGTYPE_INTRO && pStage1==pStage2
|| pStage2->iSegType>=SEGTYPE_INTRO )
iEndBar = iFirstBar+pStage2->aBars.size()-1;
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd ){
if( m_iMode==VIEW_STYLE )
SelectBars( iStartBar, iEndBar );
else
SelectRange( iStartBar, 0, iEndBar, m_nBarWidth-1, true );
}
}
else if( m_iMode==VIEW_TRACK ){
int iStartPoint = m_iSelBarStart * m_nDataWidth + m_iSelPointStart,
iEndPoint = m_iSelBarEnd * m_nDataWidth + m_iSelPointEnd,
deltaPoint = iEndPoint - iStartPoint;
int minArea = max( 10, (int)(g_nPPB / 4.0 + 0.5) );
if( deltaPoint<minArea ){
if( m_iSelBarStart==m_iMouseDownBar
&& m_iSelPointStart==m_iMouseDownPoint )
SelectRange( m_iSelBarStart, m_iSelPointStart, -1, -1 );
else
SelectRange( -1, -1, m_iSelBarEnd, m_iSelPointEnd );
}
}
}
if( m_iMode==VIEW_CHORD ){
int iKey = -1, iType = -1, iBarKey = -1;
bool bEnable = false;
if( m_iSelBarStart>=0 ){
GetSelectChord( iBarKey, iKey, iType );
bEnable = iKey!=-1;
}
((TChordPanel*)m_pChordPanel)->EnableChordModify( bEnable, iBarKey, iKey, iType );
}
ReleaseCapture();
m_bDragReady = false;
m_bDraging = false;
m_bBrush = false;
m_iMouseDownBar = m_iMouseDownPoint = -1;
m_pItem = NULL;
}
else if( m_bBrush ){
SetCapture( Handle );
}
}
//-----------------------------------------------------------------------------
bool TContentPanel::HandleHoverEvent(TPoint ptMouse)
{
if( g_lstOpusStages.size()==0 || !m_bDraging && !m_pItem
|| (w_iDragMode==DM_ADJUSTSTYLE || w_iDragMode==DM_ADJUSTSTAGE)
&& m_pItem && ( m_pItem->iType==SEGTYPE_STYLE
|| m_pItem->iType==SEGTYPE_TRACK ) ){
return false;
}
bool bCanDrop = false;
int X = ptMouse.X,
Y = ptMouse.Y;
int iHitType = -1;
DWORD dwHit = HitTest( X, Y, iHitType );
if( iHitType>=BAR_TITLE ){
int iHitBar = LOWORD(dwHit),
iHitPoint = HIWORD(dwHit);
if( (w_iDragMode==DM_ADJUSTSTYLE || w_iDragMode==DM_ADJUSTSTAGE) && iHitType<BAR_TRACK ){
int iFirstBar,
iHitStage = FindStage( iHitBar, &iFirstBar );
TOpusStage * pHitStage = g_lstOpusStages[iHitStage];
int iLastBar = iFirstBar + pHitStage->aBars.size() - 1;
int iHitType = pHitStage->iSegType;
if( iHitType==SEGTYPE_FILL )
iHitType = SEGTYPE_VAR;
bool bCanInsert = false;
if( m_pItem ){
int iDropType = m_pItem->GetSegType();
TOpusStage* pLastStage = g_lstOpusStages.back();
if( iDropType==SEGTYPE_FILL )
iDropType = SEGTYPE_VAR;
if( iDropType==iHitType ){
// SelectBars( iFirstBar, iLastBar );
bCanDrop = true;
}
if( iHitBar==m_nBarNum-1 && iHitPoint>90 ){
if( pLastStage->iSegType!=SEGTYPE_ENDING && iDropType>=SEGTYPE_INTRO ){
bCanInsert = true;
}
}
else if( iDropType==SEGTYPE_INTRO ){
bCanInsert = true;
}
}
else{
int iStage = FindStage( m_iSelBarStart, NULL );
TOpusStage* pHoverStage = g_lstOpusStages[iStage];
if( pHoverStage->iSegType<SEGTYPE_ENDING && ( iHitBar<m_iSelBarStart
|| iHitBar>m_iSelBarEnd && iHitType<SEGTYPE_ENDING )){
bCanInsert = true;
}
}
if( bCanInsert && ( iHitType<SEGTYPE_INTRO && ( iHitPoint<30 || iHitPoint>90 )
|| iHitType>=SEGTYPE_INTRO && ( iHitBar==iFirstBar && iHitPoint<30
|| iHitBar==iLastBar && iHitPoint>90 ))){
if( m_pItem )
SelectBars( -1, -1 );
SetDropBar( iHitBar + (iHitPoint>90 ? 1 : 0) );
bCanDrop = true;
}
else{
SetDropBar( -1 );
if( bCanDrop ){
SelectBars( iFirstBar, iLastBar );
}
}
}
else if( w_iDragMode==DM_ADJUSTAUDIO && iHitType>=BAR_TRACK && iHitType<BAR_LEFT ){
int iHitTrack = iHitType & 0xFF;
if( m_aTracks[iHitTrack]->type==ST_AUDIO ){
SelectTrack( iHitTrack, iHitBar, iHitPoint, false );
bCanDrop = true;
}
else{
SelectTrack( -1, -1, -1, false );
}
}
}
if( !bCanDrop ){
if( w_iDragMode==DM_ADJUSTSTYLE || w_iDragMode==DM_ADJUSTSTAGE ){
if( m_pItem )
SelectBars( -1, -1 );
SetDropBar( -1 );
}
else if( w_iDragMode==DM_ADJUSTAUDIO ){
SelectTrack( -1, -1, -1, false );
}
}
return bCanDrop;
}
//-----------------------------------------------------------------------------
void TContentPanel::AudioMove( int iSrcTrack, int iSrcBarStart, int iSrcPointStart,
int iSrcBarEnd, int iSrcPointEnd, bool bCut )
{
if( m_bPlaying )
Parent->Perform( UM_STOP, STOP_CONTENT, 0 );
int nTotalBars = m_nBarNum;
if( iSrcBarStart<0 ){
iSrcBarStart = 0;
iSrcPointStart = 0;
}
if( iSrcBarEnd<0 ){
iSrcBarEnd = nTotalBars;
iSrcPointEnd = 0;
}
int iDestBarStart = m_iSelTrackBar,
iDestPointStart = m_iSelTrackPoint,
iDestBarEnd, iDestPointEnd,
nSrcLen = ( iSrcBarEnd * POINTS_PER_BAR + iSrcPointEnd )
- ( iSrcBarStart * POINTS_PER_BAR + iSrcPointStart );
if( m_iDragAudio<0 && m_iSelBarEnd>=0 ){
iDestBarEnd = m_iSelBarEnd;
iDestPointEnd = m_iSelPointEnd;
}
else{
int nPointsEnd = ( iDestBarStart * POINTS_PER_BAR + iDestPointStart ) + nSrcLen;
iDestBarEnd = nPointsEnd / POINTS_PER_BAR;
if( iDestBarEnd>=nTotalBars ){
iDestBarEnd = nTotalBars;
iDestPointEnd = 0;
}
else{
iDestPointEnd = nPointsEnd % POINTS_PER_BAR;
}
}
int nDestLen = ( iDestBarEnd - iDestBarStart ) * POINTS_PER_BAR
+ (iDestPointEnd - iDestPointStart );
double dblSrcStart = iSrcBarStart + (double)iSrcPointStart / POINTS_PER_BAR,
dblSrcEnd = iSrcBarEnd + (double)iSrcPointEnd / POINTS_PER_BAR,
dblDestStart = iDestBarStart + (double)iDestPointStart / POINTS_PER_BAR,
dblDestEnd = iDestBarEnd + (double)iDestPointEnd / POINTS_PER_BAR;
//Set Undo
DWORD *aBefore=NULL, *aAfter=NULL, *aExtra=NULL;
int iSrcBarBreak = iSrcBarEnd,
iSrcPointBreak = iSrcPointEnd;
int nAT = 1,
*aTrks = &g_iSelAudio;
//int iTracks = g_iSelAudio;
if( bCut && iSrcTrack!=g_iSelAudio ){
// iTracks =-1;//+= ( 1<<iSrcTrack );
nAT = 2;
aTrks = new int[2];
aTrks[0] = g_iSelAudio;
aTrks[1] = iSrcTrack;
}
f_MM_AddUndoBefore( nAT, aTrks );
if( g_iSelAudio>0 ){
if( nSrcLen > nDestLen ){ //超出总长度
double dblDelStart = dblSrcStart + ( dblDestEnd - dblDestStart );
if( bCut ){ //单独删除不复制的部分
int nDelLen = nSrcLen - nDestLen,
nPointsEnd = ( iSrcBarStart * POINTS_PER_BAR + iSrcPointStart ) + nDelLen;
iSrcBarBreak = nPointsEnd / POINTS_PER_BAR;
iSrcPointBreak = nPointsEnd % POINTS_PER_BAR;
// Set Undo
CopyWave( iSrcTrack, iSrcBarBreak, iSrcPointBreak,
iSrcBarEnd, iSrcPointEnd, &aExtra );
MoveAudio( iSrcTrack, dblDelStart, dblSrcEnd, -1, 0, MODE_ERASE );
}
dblSrcEnd = dblDelStart;
}
// Set Undo
CopyWave( g_iSelAudio, iDestBarStart, iDestPointStart,
iDestBarEnd, iDestPointEnd, &aBefore );
}
else{
TAudioTrack* pAudio = CopyAudioTrack( g_iSelAudio, 0, m_nBarNum );
g_Undo.AddUndo( bCut ? UNDO_AUDIO_MOVE : UNDO_AUDIO_COPY,
g_iSelAudio, g_iMelodyKey, -1,
(void*)pAudio, NULL );
}
MoveAudio( iSrcTrack, dblSrcStart, dblSrcEnd,
g_iSelAudio, dblDestStart, bCut ? MODE_MOVE : MODE_COPY );
if( g_iSelAudio>0 ){
f_MM_AddUndoAfter( nAT, aTrks );
// Set Undo
CopyWave( g_iSelAudio, iDestBarStart, iDestPointStart,
iDestBarEnd, iDestPointEnd, &aAfter );
int iBegin = MAKELONG( iDestPointStart, iDestBarStart ),
iEnd = MAKELONG( iDestPointEnd, iDestBarEnd ),
iType = bCut ? UNDO_AUDIO_MOVE : UNDO_AUDIO_COPY;
g_Undo.AddUndo( iType, g_iSelAudio, iBegin, iEnd, (void*)aBefore, (void*)aAfter );
if( bCut ){
int iSrcBegin = MAKELONG( iSrcPointStart, iSrcBarStart ),
iSrcEnd = MAKELONG( iSrcPointEnd, iSrcBarEnd );
g_Undo.SetUndoExtra( iSrcTrack, iSrcBegin, iSrcEnd, (void*)aExtra, NULL );
}
//显示
if( iSrcTrack!=g_iSelAudio )
InvalidateBars( m_iSelBarStart, m_iSelBarEnd,
BAR_TRACK | GetShowTrackId( ST_AUDIO, iSrcTrack ) );
if( m_iDragAudio>0 || m_iSelBarStart<0 ){
/* if( m_iSelBarStart==iDestBarStart && m_iSelBarEnd==iDestBarEnd
&& iDestBarEnd - iDestBarStart > 1 )
InvalidateBars( iDestBarStart+1, iDestBarEnd-1,
BAR_TRACK | GetShowTrackId( ST_AUDIO, g_iSelAudio ) );
*/
SelectRange( iDestBarStart, iDestPointStart, iDestBarEnd, iDestPointEnd, true );
}
else
InvalidateBars( iDestBarStart, iDestBarEnd,
BAR_TRACK | GetShowTrackId( ST_AUDIO, g_iSelAudio ) );
}
if( nAT>1 )
delete[] aTrks;
}
//-----------------------------------------------------------------------------
void TContentPanel::HandleDropEvent( int iState )
{
TUseStylePanel* pStylePanel = (TUseStylePanel*)m_pStylePanel;
if( w_iDragMode==DM_ADJUSTAUDIO ){
if( g_iSelAudio>=0 && m_iSelTrackBar>=0 ){
if( m_iDragAudio!=g_iSelAudio || m_iSelTrackBar!=m_iSelBarStart
|| m_iSelTrackPoint!=m_iSelPointStart ){
TShiftState Shift( iState );
bool bCtrl = Shift.Contains( ssCtrl );
AudioMove( m_iDragAudio, m_iSelBarStart, m_iSelPointStart,
m_iSelBarEnd, m_iSelPointEnd, !bCtrl );
}
}
else{
int iTrack = GetShowTrackId( ST_AUDIO, m_iDragAudio ) - 1;
SelectTrack( iTrack, m_iSelBarStart, m_iSelPointStart, false );
}
m_iDragAudio = -1;
}
else if( m_iSelBarStart>=0 && m_pItem ){ //应用风格到段
int iFirstBar,
iStage = FindStage( m_iSelBarStart, &iFirstBar );
TSegmentItem* pSegItem = (TSegmentItem*)m_pItem;
TOpusStage* pStage = g_lstOpusStages[iStage];
int nBar = pStage->aBars.size();
if( pSegItem->iSegType>=SEGTYPE_INTRO )
nBar = pSegItem->nBars;
if( pStage->aBars.size()!=nBar ){ //段落长度调整
SetPlayPoint( 0, 0 );
Application->MainForm->Perform( UM_SHOWPLAYTIME, 0, 0 );
}
pStylePanel->ReformStage( iStage, pSegItem );
iStage = FindStage( m_iSelBarStart, NULL );
SelectStage( iStage );
}
else if( m_iDropBar>=0 ){
if( m_pItem ){ //插入前尾奏
TSegmentItem* pSegItem = (TSegmentItem*)m_pItem;
int nBarNum = 0;
if( pSegItem->iSegType>=SEGTYPE_INTRO )
nBarNum = pSegItem->nBars;
int iStage = FindStage( m_iDropBar, NULL );
int iPSFirstBar, iPlayStage = FindStage( m_iPlayBar, &iPSFirstBar );
if( iStage>=0 && iPlayStage>=iStage ){
SetPlayPoint( 0, 0 );
Application->MainForm->Perform( UM_SHOWPLAYTIME, 0, 0 );
}
bool bPreChange = g_iPreStage==0;
if( bPreChange ){
DuplicateRawBars();
SendMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
}
f_MM_AddUndoBefore( -1, NULL );
pStylePanel->InsertStage( m_iDropBar, pSegItem );
iStage = FindStage( m_iDropBar, NULL );
SelectBars( m_iDropBar, m_iDropBar+nBarNum-1 );
if( bPreChange )
InitialVars();
f_MM_AddUndoAfter( -1, NULL );
pStylePanel->SetBarsUndo( UNDO_BAR_INSERT, m_iDropBar, nBarNum );
}
else if( m_iSelBarStart>=0 ){
TShiftState Shift( iState );
bool bCtrl = Shift.Contains( ssCtrl );
pStylePanel->MoveBars( m_iSelBarStart, m_iSelBarEnd,
m_iDropBar, bCtrl ? MODE_COPY : MODE_MOVE );
}
}
}
//-----------------------------------------------------------------------------
void TContentPanel::SelectBars( int iStartBar, int iEndBar )
{
int iStart = m_iSelBarStart, iEnd = m_iSelBarEnd;
if( iStart==iStartBar ){
if( iEnd==iEndBar )
return;
else{
iStart = min( iEndBar, iEnd );
iEnd = max( iEndBar, iEnd );
}
}
else if( iEndBar==iEnd ){
iEnd = max( iStartBar, iStart );
iStart = min( iStartBar, iStart );
}
else{
if( iStart<0 || iStartBar<iStart && iStartBar>=0 )
iStart = iStartBar;
if( iEndBar>iEnd )
iEnd = iEndBar;
}
m_iSelBarStart = iStartBar;
m_iSelBarEnd = iEndBar;
if( iStartBar<0 && iEndBar<0 ){
m_iSelCellStart = m_iSelCellEnd = -1;
m_iSelPointStart = m_iSelPointEnd = -1;
//DebugPrint( "Select -1, -1" );
}
else{
if( iStartBar>=0 && m_iSelPointStart<0 ){
m_iSelPointStart = 0;
}
if( iEndBar>=0 && m_iSelPointEnd<0 ){
m_iSelPointEnd = m_nBarWidth-1;
}
}
int iArea = 0;
if( m_iMode==VIEW_STYLE ){
iArea = BAR_TITLE|BAR_DATA|BAR_TRACK;
}
else if( m_iMode==VIEW_CHORD ){
iArea = BAR_DATA;
}
else{
iArea = BAR_TRACK;
}
InvalidateBars( iStart, iEnd, iArea );
}
//-----------------------------------------------------------------------------
void TContentPanel::GetSelectBars( int& iStartBar, int& iEndBar )
{
iStartBar = m_iSelBarStart;
iEndBar = m_iSelBarEnd;
}
//-----------------------------------------------------------------------------
void TContentPanel::SelectCells( int iBarStart, int iCellStart,
int iBarEnd, int iCellEnd )
{
if( iBarStart==m_iSelBarStart && iCellStart==m_iSelCellStart
&& iBarEnd==m_iSelBarEnd && iCellEnd==m_iSelCellEnd )
return;
if( iBarStart!=m_iSelBarStart || iBarEnd!=m_iSelBarEnd ){
m_iSelCellStart = iCellStart;
m_iSelCellEnd = iCellEnd;
if( iBarStart==m_iSelBarStart )
InvalidateBar( iBarStart, 0, m_nBarWidth, BAR_DATA );
if( iBarEnd==m_iSelBarEnd )
InvalidateBar( iBarEnd, 0, m_nBarWidth, BAR_DATA );
SelectBars( iBarStart, iBarEnd );
}
else if( iBarStart==iBarEnd ){
m_iSelCellStart = iCellStart;
m_iSelCellEnd = iCellEnd;
InvalidateBar( iBarStart, 0, m_nBarWidth, BAR_DATA );
}
else{
if( iCellStart!=m_iSelCellStart ){
int l = min( m_iSelCellStart, iCellStart ) * m_nChordTxtWidth,
r = ( max( m_iSelCellStart, iCellStart ) + 1 ) * m_nChordTxtWidth;
m_iSelCellStart = iCellStart;
InvalidateBar( iBarStart, l, r, BAR_DATA );
}
if( iCellEnd!=m_iSelCellEnd ){
int l = min( m_iSelCellEnd, iCellEnd ) * m_nChordTxtWidth,
r = ( max( m_iSelCellEnd, iCellEnd ) + 1 ) * m_nChordTxtWidth;
m_iSelCellEnd = iCellEnd;
InvalidateBar( iBarEnd, l, r, BAR_DATA );
}
}
}
//---------------------------------------------------------------------------
void TContentPanel::SelectCopyCells( int iBarStart, int iCellStart,
int iBarEnd, int iCellEnd )
{
if( m_iCopyBarStart==iBarStart && m_iCopyCellStart==iCellStart
&& m_iCopyBarEnd==iBarEnd && m_iCopyCellEnd==iCellEnd )
return;
int iOldBarStart = m_iCopyBarStart,
iOldBarEnd = m_iCopyBarEnd;
//iOldCellSetart = m_iCopyCellStart,
//iOldCellEnd = m_iCopyCellEnd;
m_iCopyBarStart = iBarStart;
m_iCopyBarEnd = iBarEnd;
m_iCopyCellStart = iCellStart;
m_iCopyCellEnd = iCellEnd;
if( iOldBarStart>=0 ){
if( iBarStart>=0 ){
if( iBarStart<=iOldBarEnd || iBarEnd>=iOldBarStart ){
int iStart = min( iBarStart, iOldBarStart ),
iEnd = max( iBarEnd, iOldBarEnd );
InvalidateBars( iStart, iEnd );
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd );
InvalidateBars( iBarStart, iBarEnd );
}
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd );
}
}
else if( iBarStart>=0 ){
InvalidateBars( iBarStart, iBarEnd );
}
}
//---------------------------------------------------------------------------
void TContentPanel::SelectCopyPos( int iBarStart, int iPointStart, int iBarEnd, int iPointEnd )
{
if( m_iCopyBarStart==iBarStart && m_iCopyPointStart==iPointStart
&& m_iCopyBarEnd==iBarEnd && m_iCopyPointEnd==iPointEnd )
return;
if( iBarStart<0 ){
iBarStart = 0;
iPointStart = 0;
}
if( iBarEnd<0 ){
iBarEnd = g_Opus.BarCount();
iPointEnd = 0;
}
int iOldBarStart = m_iCopyBarStart,
iOldBarEnd = m_iCopyBarEnd;
//iOldPointStart = m_iCopyPointStart,
//iOldPointEnd = m_iCopyPointEnd;
m_iCopyBarStart = iBarStart;
m_iCopyBarEnd = iBarEnd;
m_iCopyPointStart = iPointStart;
m_iCopyPointEnd = iPointEnd;
if( iOldBarStart>=0 ){
int iWave = GetShowTrackId( ST_AUDIO, m_iCopyAudio );
if( m_iCopyAudio==g_iSelAudio && iBarStart>=0 ){
if( iBarStart<=iOldBarEnd || iBarEnd>=iOldBarStart ){
int iStart = min( iBarStart, iOldBarStart ),
iEnd = max( iBarEnd, iOldBarEnd );
InvalidateBars( iStart, iEnd, BAR_TRACK | iWave );
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd, BAR_TRACK | iWave );
InvalidateBars( iBarStart, iBarEnd, BAR_TRACK | iWave );
}
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd, BAR_TRACK | iWave );
}
}
if( iBarStart>=0 ){
m_iCopyAudio = g_iSelAudio;
int iWave = GetShowTrackId( ST_AUDIO, g_iSelAudio );
InvalidateBars( iBarStart, iBarEnd, BAR_TRACK | iWave );
}
else{
m_iCopyAudio = -1;
m_bCut = false;
}
}
//---------------------------------------------------------------------------
void TContentPanel::SetDropBar( int iBar )
{
int iDropOld = m_iDropBar;
if( iBar!=iDropOld ){
m_iDropBar = iBar;
for( int i=1; i>=0; i-- ){
if( iDropOld>=0 )
InvalidateBar( iDropOld - i, 0, m_nBarWidth, BAR_TITLE|BAR_DATA|BAR_TRACK );
if( iBar>=0 )
InvalidateBar( iBar - i, 0, m_nBarWidth, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
}
//-----------------------------------------------------------------------------
void TContentPanel::SelectStage( int iStage )
{
if( iStage>=0 && iStage<g_lstOpusStages.size() ){
TOpusStage* pStage = g_lstOpusStages[iStage];
int iFirstBar = FirstBar( iStage ),
iEndBar = iFirstBar + pStage->aBars.size() - 1;
SelectBars( iFirstBar, iEndBar );
}
}
//-----------------------------------------------------------------------------
void TContentPanel::SetScrollTimer(TPoint ptMouse, bool bVertical)
{
int X = ptMouse.X,
Y = ptMouse.Y;
//判断是否滚动
if( m_bVertical ){
if( m_nRowNum>m_nRowShow && X>m_nLeftBound && X<Width-m_nRightBound ){
short iDirect = 0;
if( Y>Height-m_nRowGapHeight && m_iBeginShowRow<m_nRowNum-m_nRowShow )
iDirect = 1;
else if( Y<m_nTopBound+m_nRowGapHeight && m_iBeginShowRow>0 )
iDirect = -1;
if( iDirect!=0 ){
if( !m_pTimer ){
m_pTimer = new TTimer(this);
m_pTimer->OnTimer = TimerProc;
m_pTimer->Tag = MAKELONG( iDirect, 0 );
m_pTimer->Interval = 500;
m_pTimer->Enabled = true;
}
}
else if( m_pTimer ){
delete m_pTimer;
m_pTimer = NULL;
}
}
}
else{
if( m_aTracks.size()>m_nTrackShow && X>m_nLeftBound && X<Width-m_nRightBound ){
short iDirect = 0;
if( Y>Height-m_nRowGapHeight
&& m_iBeginShowTrack<(int)(m_aTracks.size()-m_nTrackShow) )
iDirect = 1;
else if( Y<m_nTopBound+m_nRowGapHeight && m_iBeginShowTrack>0 )
iDirect = -1;
if( iDirect!=0 ){
if( !m_pTimer ){
m_pTimer = new TTimer(this);
m_pTimer->OnTimer = TimerProc;
m_pTimer->Tag = MAKELONG( iDirect, 0 );
m_pTimer->Interval = 500;
m_pTimer->Enabled = true;
}
}
else if( m_pTimer ){
delete m_pTimer;
m_pTimer = NULL;
}
}
else if( m_nBarNum>m_nColumnNum && Y>m_nTopBound && Y<Height-m_nBottomBound ){
short iDirect = 0;
if( X>Width-m_nRightBound && ( g_iToolPanelShow!=0 || m_bBrush && X<Width+120
|| w_bDraging && X<Width+12 )
&& m_iBeginShowBar<=m_nBarNum-m_nColumnNum )
iDirect = 1;
else if( X<m_nLeftBound && ( g_iToolPanelShow!=1 || m_bBrush && X>-120
|| w_bDraging && X>-12 )
&& m_iBeginShowBar>0 )
iDirect = -1;
if( iDirect!=0 ){
if( !m_pTimer ){
m_pTimer = new TTimer(this);
m_pTimer->OnTimer = TimerProc;
m_pTimer->Tag = MAKELONG( iDirect, 1 );
m_pTimer->Interval = 500;
m_pTimer->Enabled = true;
}
}
else if( m_pTimer ){
delete m_pTimer;
m_pTimer = NULL;
}
}
}
}
//-----------------------------------------------------------------------------
void __fastcall TContentPanel::TimerProc(TObject* Sender)
{
if( w_bDraging || m_bDraging ){
DebugPrint( "On timer." );
if( m_pTimer->Tag!=0 ){
bool bVertical = HIWORD( m_pTimer->Tag )==0;
short iDirect = (short)(LOWORD( m_pTimer->Tag ));
int &iCurPos = bVertical ? (m_bVertical ? m_iBeginShowRow : m_iBeginShowTrack)
: m_iBeginShowBar,
iMaxPos = bVertical ? (m_bVertical ? m_nRowNum-m_nRowShow : m_aTracks.size()-m_nTrackShow)
: m_nBarNum-m_nColumnNum;
ScrollView( iCurPos + iDirect, bVertical );
if( iCurPos<=0 || iCurPos>=iMaxPos ){
delete m_pTimer;
m_pTimer = NULL;
}
else if( m_pTimer->Interval>200 ){
m_pTimer->Interval = 200;
}
}
}
else if( m_pTimer && m_pTimer->Tag!=0 ){
delete m_pTimer;
m_pTimer = NULL;
}
}
//-----------------------------------------------------------------------------
void __fastcall TContentPanel::OnStageChanged( int iStage, int iMode )
{
if( m_bPlaying )
Parent->Perform( UM_STOP, STOP_CONTENT | STOP_USESTYLE, 0 );
int nBarCount = GetBarCount();
if( m_iPlayBar>=nBarCount ){
SetPlayPoint( 0, 0 );
Application->MainForm->Perform( UM_SHOWPLAYTIME, 0, 0 );
}
if( iMode==MODE_DELETE || m_iSelBarEnd>=nBarCount )
SelectBars( -1, -1 );
if( m_iCopyBarStart>=0 && iMode!=MODE_COPY && iMode!=MODE_MOVE ){
SelectCopyBars( -1, -1 );
}
if( iMode==MODE_INIT ){
InitialVars();
//SelectBars( -1, -1 );
SelectRange( -1, -1, -1, -1 );
SelectCopyPos( -1, -1, -1, -1 );
SelectCells( -1, -1, -1, -1 );
SelectCopyCells( -1, -1, -1, -1 );
}
else{
if( iStage>0 )
iStage--;
if( nBarCount!=m_nBarNum ){
if( nBarCount==0 ){
InvalidateRgn( Handle, NULL, false );
}
else if( nBarCount<m_nBarNum ){
InvalidateBars( nBarCount, m_nBarNum-1, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
m_nBarNum = nBarCount;
if( m_bVertical ){
int iFirstShowBar = m_iBeginShowRow * m_nColumnNum;
m_nRowNum = m_nBarNum / m_nColumnNum;
if( m_nBarNum % m_nColumnNum > 0 ){
m_nRowNum++;
}
int nDrawHeight = ClientHeight - m_nTopBound - m_nBottomBound;
if( nDrawHeight % m_nBarHeight > m_nRowGapHeight + m_nTitleHeight ){
m_nRowNum++;
}
if( !SetScrollView( iFirstShowBar ) ){
for( int i=iStage; i<g_lstOpusStages.size(); i++ ){
InvalidateStage( i, BAR_CURSOR|BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
}
else{
for( int i=iStage; i<g_Opus.StageCount(); i++ )
InvalidateStage( i, BAR_DATA|BAR_TITLE|BAR_TRACK );
}
}
else if( iMode==MODE_CHANGE ){ //修改
for( int i=iStage; i<g_Opus.StageCount(); i++ ) //可能出现3小节合并
InvalidateStage( i, BAR_DATA|BAR_TRACK );
}
else if( iMode==MODE_MOVE ){
for( int i=iStage; i<g_Opus.StageCount(); i++ ){
InvalidateStage( i, BAR_CURSOR|BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
if( iMode==MODE_CHANGE && g_iPreStage==0 ){
g_Theme.Set( g_pUseStyle->pStyle->idLoc, g_pUseStyle->pStyle->idStyle,
g_lstOpusStages );
PostMessage( Parent->Handle, UM_STAGECHANGED, 0, 0 );
}
else{
PostMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
}
}
if( !m_bVertical )
GenerateCompose();
}
//-----------------------------------------------------------------------------
void __fastcall TContentPanel::OnChangeMelodyKey( int Index )
{
g_Undo.AddUndo( UNDO_KEY_MELODY, 0, g_iMelodyKey, Index, NULL, NULL );
ChangeBarsKey( 0, g_Opus.BarCount()-1, Index, NULL );
// ChangeMelodyKey( Index );
}
//---------------------------------------------------------------------------
/*
void TContentPanel::ChangeMelodyKey( int iKey )
{
g_Opus.ChangeKey( -1, -1, iKey, NULL );
g_iMelodyKey = iKey;
InvalidateShowBars();
if( g_iViewMode==VIEW_CHORD ){
SelectCells( -1, -1, -1, -1 );
((TChordPanel*)m_pChordPanel)->EnableChordModify( false, -1, -1, -1 );
}
}
//---------------------------------------------------------------------------
*/
void TContentPanel::ChangeBarsKey( int iBarStart, int iBarEnd, int iKey, int keys[] )
{
g_Opus.ChangeKey( iBarStart, iBarEnd, iKey, keys );
if( iBarStart==0 ){
g_iMelodyKey = keys ? keys[0] : iKey;;
Application->MainForm->Perform( UM_CHANGEKEY, 0, 0 );
}
if( g_iPreStage==0 ){
g_Theme.Set( g_pUseStyle->pStyle->idLoc,
g_pUseStyle->pStyle->idStyle,
g_lstOpusStages );
}
if( !m_bVertical )
GenerateCompose();
int opt = BAR_TITLE | BAR_DATA;
if( !m_bVertical )
opt |= BAR_TRACK;
InvalidateBars( iBarStart, iBarEnd+1, opt );
if( g_iViewMode==VIEW_CHORD ){
SelectCells( -1, -1, -1, -1 );
((TChordPanel*)m_pChordPanel)->EnableChordModify( false, -1, -1, -1 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoubleClick(TObject* sender)
{
if( m_iMode==VIEW_TRACK ){
int iHitType = -1;
DWORD dwHit = HitTest( ptDown.X, ptDown.Y, iHitType );
int iHitBar = LOWORD(dwHit),
iHitPoint = HIWORD(dwHit);
if( iHitType>=BAR_TRACK && iHitType<BAR_LEFT){
int iHitTrack = iHitType & 0xFF;
if( m_aTracks[iHitTrack]->type==ST_AUDIO )
/* if( iHitType & 0xFF00 )
SelectRangeByEffect( iHitBar, iHitPoint, ( iHitType & 0xFF00 )>>8 );
else
*/
SelectRangeByWave( iHitBar, iHitPoint );
}
}
else if( m_iSelBarStart>=0 ){
if( m_iMode==VIEW_STYLE ){
int iFirstBar,
iStage = FindStage( m_iSelBarStart, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
int iEndBar = iFirstBar + pStage->aBars.size()-1;
SelectBars( iFirstBar ,iEndBar );
((TUseStylePanel*)m_pStylePanel)->SetSelectStage( iStage );
}
else if( m_iMode==VIEW_CHORD ){
int iFirstBar,
iStage = FindStage( m_iSelBarStart, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
TBar * pBar = pStage->aBars[m_iSelBarStart-iFirstBar];
int iCellStart = m_iSelCellStart,
iCellEnd = iCellStart;
int key = pBar->aChords.iKey[iCellStart],
type = pBar->aChords.iType[iCellStart];
for( int i=m_iSelCellStart-1; i>=0; i-- ){
if( pBar->aChords.iKey[i]==key && pBar->aChords.iType[i]==type )
iCellStart = i;
else
break;
}
for( int i=m_iSelCellStart+1; i<g_nChordNumPerBar; i++ ){
if( pBar->aChords.iKey[i]==key && pBar->aChords.iType[i]==type )
iCellEnd = i;
else
break;
}
SelectCells( m_iSelBarStart, iCellStart, m_iSelBarStart, iCellEnd );
}
}
}
//-----------------------------------------------------------------------------
void TContentPanel::SelectRangeByWave( int iHitBar, int iHitPoint )
{
TWaveBarList& list = g_aAudioTracks[g_iSelAudio]->lstBars;
int nMiss = 0;
//前向查找波形起点
int iBarS = iHitBar, iPtS = iHitPoint;
while( iBarS>=0 ){
for( ; iPtS>=0; iPtS-- ){
DWORD dwValue = list[iBarS]->aVols[iPtS];
WORD wVol = max( LOWORD( dwValue ), HIWORD(dwValue) );
if( wVol<1024 ){
nMiss++;
if( nMiss>4 )
break;
}
else
nMiss = 0;
}
if( nMiss>4 || iBarS==0 )
break;
else{
iPtS = POINTS_PER_BAR - 1;
iBarS--;
}
}
//后向查找波形终点
nMiss = 0;
int iBarE = iHitBar, iPtE = iHitPoint;
while( iBarE<m_nBarNum ){
for( ; iPtE<POINTS_PER_BAR; iPtE++ ){
DWORD dwValue = list[iBarE]->aVols[iPtE];
WORD wVol = max( LOWORD( dwValue ), HIWORD(dwValue) );
if( wVol<1024 ){
nMiss++;
if( nMiss>4 )
break;
}
else
nMiss = 0;
}
if( nMiss>4 || iBarE==m_nBarNum-1 )
break;
else{
iPtE = 0;
iBarE++;
}
}
int ptStart = iBarS * POINTS_PER_BAR + iPtS + nMiss,
ptEnd = iBarE * POINTS_PER_BAR + iPtE - nMiss;
if( ptEnd - ptStart > 4 ){
iBarS = ptStart / POINTS_PER_BAR;
iPtS = ptStart % POINTS_PER_BAR;
iBarE = ptEnd / POINTS_PER_BAR;
iPtE = ptEnd % POINTS_PER_BAR;
SelectRange( iBarS, iPtS, iBarE, iPtE );
}
}
//-----------------------------------------------------------------------------
/*
void TContentPanel::SelectRangeByEffect( int iHitBar, int iHitPoint , int delta )
{
TAudioTrack* pTrack = g_aAudioTracks[g_iSelAudio];
int nEffects = 0,
hE = 1;
if( pTrack->iEffectShow>0 ){
for( int i=0; i<MAX_FX_NUM; i++ ){
if( pTrack->lstEffects[i] ){
nEffects++;
}
}
if( nEffects>0 ){
hE = 14 / nEffects;
if( hE>4 )
hE = 4;
}
}
int hEffects = nEffects * hE;
if( delta >= hEffects )
return;
if( pTrack->iEffectShow==1 ){
delta = hEffects - delta;
}
int y = 0;
for( int j=0; j<MAX_FX_NUM; j++ ){
if( pTrack->lstEffects[j] ){
y += hE;
}
if( delta < y ){
TEffect* pAE = pTrack->lstEffects[j];
while( pAE ){
if( pAE->iBarEnd>iHitBar || pAE->iBarEnd==iHitBar && pAE->iPointEnd>=iHitPoint ){
if( pAE->iBarStart<iHitBar || pAE->iBarStart==iHitBar
&& pAE->iPointStart<=iHitPoint ){
SelectRange( pAE->iBarStart, pAE->iPointStart, pAE->iBarEnd, pAE->iPointEnd );
}
break;
}
pAE = pAE->pNext;
}
break;
}
}
}
//-----------------------------------------------------------------------------
*/
void TContentPanel::BeginBrush( TCommonItem* pBrushItem )
{
if( m_iMode==VIEW_STYLE ){
m_pItem = pBrushItem;
SelectTrack( -1, -1, -1 );
if( m_bVertical )
SelectBars( -1, -1 );
else
SelectRange( -1, -1, -1, -1 );
}
m_bBrush = true;
SetCapture( Handle );
}
//-----------------------------------------------------------------------------
void TContentPanel::CancelBrush()
{
m_bBrush = false;
m_pItem = NULL;
}
//-----------------------------------------------------------------------------
void TContentPanel::HandleBrush()
{
if( m_iMode==VIEW_STYLE ){
if( !m_pItem )
return;
if( m_bPlaying )
Parent->Perform( UM_STOP, STOP_CONTENT, 0 );
// 计算实际有效的起止位置
int iStartBar = m_iSelBarStart,
iEndBar = m_iSelBarEnd,
iFStage = g_Opus.FindStage( iStartBar, NULL ),
iLStage = g_Opus.FindStage( iEndBar, NULL );
iStartBar = -1;
iEndBar = -1;
for( int i=iFStage; i<=iLStage; i++ ){
if( m_pItem->iType==SEGTYPE_TRACK && g_lstOpusStages[i]->iSegType==((TTrackItem*)m_pItem)->GetSegType()
|| m_pItem->iType==SEGTYPE_SEGMENT && g_lstOpusStages[i]->iSegType<=SEGTYPE_FILL ){
int iFBar = g_Opus.StageFirstBar( i );
if( iFBar > m_iSelBarStart )
iStartBar = iFBar;
else
iStartBar = m_iSelBarStart;
break;
}
}
if( iStartBar>=0 ){
for( int i=iLStage; i>=iFStage; i-- ){
if( m_pItem->iType==SEGTYPE_TRACK && g_lstOpusStages[i]->iSegType==((TTrackItem*)m_pItem)->GetSegType()
|| m_pItem->iType==SEGTYPE_SEGMENT && g_lstOpusStages[i]->iSegType<=SEGTYPE_FILL ){
int iLBar = g_Opus.StageLastBar( i );
if( iLBar > m_iSelBarEnd )
iEndBar = m_iSelBarEnd;
else
iEndBar = iLBar;
break;
}
}
}
if( iStartBar<0 || iEndBar<0 || iStartBar>iEndBar ){
SelectBars( -1, -1 );
return;
}
if( iStartBar!=m_iSelBarStart || iEndBar!=m_iSelBarEnd )
SelectBars( iStartBar, iEndBar );
if( m_pItem->iType==SEGTYPE_TRACK ){
int iTrack = -1;
TTrackItem* pTrkItem = (TTrackItem*)m_pItem;
TTrack subTrk( pTrkItem->pTrack );
if( m_iSelTrack<0 ){
bool bAdd = true;
if( subTrk.iChanNo==9 ){
for( int i=0; i<g_aMidiTracks.size(); i++ ){
TMidiTrack* pMT = g_aMidiTracks[i];
if( pMT->IsDrum() ){
subTrk.iFile = pMT->file;
subTrk.iBank = pMT->bank;
subTrk.iChanSpec = pMT->chno;
subTrk.iProg = pMT->prog;
iTrack = i;
bAdd = false;
break;
}
}
}
if( bAdd ){
subTrk.iFile = 0xFF;
subTrk.iChanSpec = subTrk.iChanNo;
}
}
else if( m_aTracks[m_iSelTrack]->type==ST_MIDI ){
TMidiTrack* pMT = (TMidiTrack*)m_aTracks[m_iSelTrack]->pTrack;
subTrk.iFile = pMT->file;
subTrk.iBank = pMT->bank;
subTrk.iChanSpec = pMT->chno;
subTrk.iProg = pMT->prog;
iTrack = m_aTracks[m_iSelTrack]->index;
}
((TUseStylePanel*)m_pStylePanel)->ChangeTexture( iStartBar, iEndBar, pTrkItem->GetSegType(),
iTrack, &subTrk, SEGTYPE_TRACK );
}
else
((TUseStylePanel*)m_pStylePanel)->ReformBars( m_iSelBarStart, m_iSelBarEnd,
(TSegmentItem*)m_pItem );
}
}
//-----------------------------------------------------------------------------
void TContentPanel::GetSelectChord( int& iBarKey, int& iChordKey, int& iChordType )
{
int key=-1, type=-1, barKey=-1;
if( m_iSelBarStart>=0 && m_iSelCellStart>=0 ){
int iFirstBar, iStage = FindStage( m_iSelBarStart, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
TBar* pBar = pStage->aBars[m_iSelBarStart-iFirstBar];
type = pBar->aChords.iType[m_iSelCellStart];
key = pBar->aChords.iKey[m_iSelCellStart];
barKey = pBar->iBarKey;
if( m_iSelBarEnd>m_iSelBarStart || m_iSelCellEnd>m_iSelCellStart ){
int iBar = m_iSelBarStart,
iCell = m_iSelCellStart;
while( iBar<m_iSelBarEnd || iBar==m_iSelBarEnd && iCell<m_iSelCellEnd ){
iCell++;
if( iCell>=g_nChordNumPerBar ){
iCell = 0;
iBar++;
if( iBar>=iFirstBar+pStage->aBars.size() ){
iStage = FindStage( iBar, &iFirstBar );
pStage = g_lstOpusStages[iStage];
}
pBar = pStage->aBars[iBar-iFirstBar];
if( barKey!=pBar->iBarKey ){
barKey = key = type = -1;
break;
}
}
if( key!=pBar->aChords.iKey[iCell] || type!=pBar->aChords.iType[iCell] ){
barKey = key = type = -1;
break;
}
}
}
}
iChordKey = key;
iChordType = type;
iBarKey = barKey;
}
//---------------------------------------------------------------------------
bool TContentPanel::SetSelectChord( int iKey, int iChordType )
{
if( m_iSelBarStart>=0 && m_iSelCellStart>=0 && ( m_iSelBarEnd>m_iSelBarStart
|| m_iSelBarEnd==m_iSelBarStart && m_iSelCellEnd>=m_iSelCellStart )){
int iFirstBar, iStage = FindStage( m_iSelBarStart, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
int iBar = m_iSelBarStart,
iCell = m_iSelCellStart,
iEndBar = m_iSelBarEnd,
iCellEnd = m_iSelCellEnd;
if( iBar==m_iSelBarEnd && iCell==m_iSelCellEnd //仅选中1拍
&& iCell<g_nChordNumPerBar-1){ //且不是小节最后1拍
for( int i=iCell+1; i<g_nChordNumPerBar; i++ ){
int iOriKey = pStage->aBars[iBar-iFirstBar]->aChords.iKey[iCell],
iOriType = pStage->aBars[iBar-iFirstBar]->aChords.iType[iCell];
if( pStage->aBars[iBar-iFirstBar]->aChords.iKey[i]==iOriKey
&& pStage->aBars[iBar-iFirstBar]->aChords.iType[i]==iOriType )
iCellEnd++;
else
break;
}
}
int iUndo = 0,
iSelChordNum = (iEndBar - iBar - 1) * g_nChordNumPerBar
+ (g_nChordNumPerBar - iCell) + (iCellEnd + 1);
BYTE *pBefore = new BYTE[iSelChordNum],
*pAfter = new BYTE[iSelChordNum];
while( iBar<iEndBar || iBar==iEndBar && iCell<=iCellEnd ){
int iSBar = iBar-iFirstBar;
pBefore[iUndo] = (pStage->aBars[iSBar]->aChords.iKey[iCell]<<4)
+ pStage->aBars[iSBar]->aChords.iType[iCell];
pAfter[iUndo] = (iKey<<4) + iChordType;
iUndo++;
pStage->aBars[iSBar]->aChords.iKey[iCell] = iKey;
pStage->aBars[iSBar]->aChords.iType[iCell] = iChordType;
if( g_iPreStage==0 ){ //初始化模式时须修改原始和弦
TOpusStage* pRawStage = g_Theme.StageList()[iStage];
pRawStage->aBars[iSBar]->aChords.iKey[iCell] = iKey;
pRawStage->aBars[iSBar]->aChords.iType[iCell] = iChordType;
}
iCell++;
if( iCell>=g_nChordNumPerBar ){
InvalidateBar( iBar, 0, m_nBarWidth, BAR_DATA );
iCell = 0;
iBar++;
iStage = FindStage( iBar, &iFirstBar );
pStage = g_lstOpusStages[iStage];
}
}
if( iBar==iEndBar && iCell<g_nChordNumPerBar ){
InvalidateBar( iBar, 0, m_nBarWidth, BAR_DATA );
}
int iBegin = MAKELONG( m_iSelCellStart, m_iSelBarStart ),
iEnd = MAKELONG( iCellEnd, iEndBar );
g_Undo.AddUndo( UNDO_CHORD, 0, iBegin, iEnd, pBefore, pAfter );
return true;
}
return false;
}
//---------------------------------------------------------------------------
void TContentPanel::GetChordDispalyKey( int iKey, int iBarKey, int& iMainKey, int& iAjustKey )
{
iMainKey = -1;
iAjustKey = 0;
if( iKey<0 )
return;
if( !g_bAlphaKey ){
iKey -= iBarKey;
if( iKey<0 ) iKey += 12;
}
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;
}
}
//---------------------------------------------------------------------------
void TContentPanel::SelectTrack( int iTrack, int iBar, int iPoint, bool bClear )
{
if( bClear ){
SelectRange( -1, -1, -1, -1 );
}
if( iBar==0 && iPoint<5 ){
iPoint = 0;
}
TShowTrack* pTrack = NULL;
if( iTrack>=0 ){
pTrack = m_aTracks[iTrack];
if( pTrack->type==ST_AUDIO && iBar<0 ){
iBar = 0;
iPoint = 0;
}
}
if( m_iSelTrack==iTrack && m_iSelTrackBar==iBar && m_iSelTrackPoint==iPoint )
return;
int iAudio = pTrack && pTrack->type==ST_AUDIO ? pTrack->index : -1,
iMidi = pTrack && pTrack->type==ST_MIDI ? pTrack->index : -1;
if( m_iSelTrack!=iTrack ){
if( m_iSelTrack>=m_iBeginShowTrack && m_iSelTrack-m_iBeginShowTrack<m_nTrackShow ){
InvalidateShowBars( BAR_TRACK | (m_iSelTrack+1) );
if( !m_bVertical ){
int top = m_nTopBound + m_nRowGapHeight + m_nTitleHeight + m_nChordHeight
+ ( m_iSelTrack - m_iBeginShowTrack ) * m_nTrackHeight;
int nH = m_nTrackHeight;
if( top + m_nTrackHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
RECT rectOld;
SetRect( &rectOld, m_nLeftOriBound, top, m_nLeftBound-4, top + nH );
InvalidateRect( Handle, &rectOld, false );
}
}
m_iSelTrack = iTrack;
g_iSelAudio = iAudio;
g_iSelMidiTrack = iMidi;
if( iTrack>=0 ){
if( iTrack<m_iBeginShowTrack || iTrack-m_iBeginShowTrack>=m_nTrackShow ){
if( !m_bVertical ){
int nPos = iTrack<m_iBeginShowTrack ? iTrack : iTrack - m_nTrackShow + 1;
ScrollView( nPos );
}
}
else{
InvalidateShowBars( BAR_TRACK | (iTrack+1) );
if( !m_bVertical ){
int top = m_nTopBound + m_nRowGapHeight + m_nTitleHeight + m_nChordHeight
+ ( iTrack - m_iBeginShowTrack ) * m_nTrackHeight;
int nH = m_nTrackHeight;
if( top + m_nTrackHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
RECT rectNew;
SetRect( &rectNew, m_nLeftOriBound, top, m_nLeftBound-4, top + nH );
InvalidateRect( Handle, &rectNew, false );
}
}
}
if( ( !w_bDraging || m_iDragAudio>=0 ) && m_pTrackPanel && m_pTrackPanel->Visible ){
((TTrackPanel*)m_pTrackPanel)->SetSelTrack( pTrack ? pTrack->type : -1,
pTrack ? pTrack->index : -1 );
}
}
else if( pTrack && pTrack->type==ST_AUDIO ){
if( m_iSelTrackBar>=0 ){
int iRow = m_bVertical ? m_iSelTrackBar / m_nColumnNum - m_iBeginShowRow : 0,
iCol = m_bVertical ? m_iSelTrackBar % m_nColumnNum : m_iSelTrackBar - m_iBeginShowBar;
if( iRow>=0 && iRow<m_nRowShow && iCol>=0 && iCol<m_nColumnNum ){
int left = iCol * m_nBarWidth + m_iSelTrackPoint + m_nLeftBound,
top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight
+ m_nTitleHeight + m_nChordHeight
+ iTrack * m_nTrackHeight;
int nH = m_nTrackHeight;
if( top + m_nTrackHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
RECT rectOld;
SetRect( &rectOld, left, top, left + 1, top + nH );
InvalidateRect( Handle, &rectOld, false );
}
}
if( iBar>=0 ){
int iRow = m_bVertical ? iBar / m_nColumnNum - m_iBeginShowRow : 0,
iCol = m_bVertical ? iBar % m_nColumnNum : iBar - m_iBeginShowBar;
if( iRow>=0 && iRow<m_nRowShow && iCol>=0 && iCol<m_nColumnNum ){
int left = iCol * m_nBarWidth + iPoint + m_nLeftBound,
top = iRow * m_nBarHeight + m_nTopBound + m_nRowGapHeight
+ m_nTitleHeight + m_nChordHeight
+ iTrack * m_nTrackHeight;
int nH = m_nTrackHeight;
if( top + m_nTrackHeight > ClientHeight - m_nBottomBound )
nH = ClientHeight - m_nBottomBound - top;
for( int i=0; i<nH; i++ ){
Canvas->Pixels[left][top + i] = clrInsertLine;
}
}
}
}
m_iSelTrackBar = iBar;
m_iSelTrackPoint = iPoint;
}
//---------------------------------------------------------------------------
void TContentPanel::SelectRange( int iBarStart, int iPointStart, int iBarEnd, int iPointEnd, bool bInvalid )
{
if( iBarStart==0 && iPointStart<5 ){
iPointStart = 0;
}
if( (m_iDragAudio<0 || g_iSelAudio==m_iDragAudio)
&& m_iSelBarStart==iBarStart && m_iSelPointStart==iPointStart
&& m_iSelBarEnd==iBarEnd && m_iSelPointEnd==iPointEnd){
if( bInvalid && m_iSelTrack>=0 ){
InvalidateBars( iBarStart, iBarEnd, BAR_TRACK | (m_iSelTrack+1) );
}
return;
}
if( m_iSelTrack<0 ){
m_iSelTrackBar = m_iSelTrackPoint = -1;
return;
}
int iTrack = m_iSelTrack + 1;// GetShowTrackId( ST_AUDIO, g_iSelAudio )<<8;
if( iBarStart>=0 ){
m_iSelTrackBar = iBarStart;
m_iSelTrackPoint = iPointStart;
}
else if( iBarEnd>=0 ){
m_iSelTrackBar = m_iSelTrackPoint = 0;
}
if( m_iDragAudio>0 && g_iSelAudio!=m_iDragAudio || bInvalid ){
m_iSelPointStart = iPointStart;
m_iSelPointEnd = iPointEnd;
SelectBars( iBarStart, iBarEnd );
InvalidateBars( iBarStart, iBarEnd, BAR_TRACK | iTrack );
}
else if( iBarStart!=m_iSelBarStart || iBarEnd!=m_iSelBarEnd ){
int iOldBarStart = m_iSelBarStart,
iOldBarEnd = m_iSelBarEnd;
m_iSelPointStart = iPointStart;
m_iSelPointEnd = iPointEnd;
SelectBars( iBarStart, iBarEnd );
int iInvBarEnd = min( iOldBarStart, iBarStart );
if( iInvBarEnd<0 )
iInvBarEnd = max( iOldBarStart, iBarStart );
if( iInvBarEnd>=0 )
InvalidateBars( 0, iInvBarEnd, BAR_TRACK | iTrack );
int iInvBarStart = max( iOldBarEnd, iBarEnd );
if( iInvBarStart<0 )
iInvBarStart = iInvBarEnd;
if( iInvBarStart>=0 )
InvalidateBars( iInvBarStart, m_nBarNum-1, BAR_TRACK | iTrack );
}
else if( iBarStart==iBarEnd ){
m_iSelPointStart = iPointStart;
m_iSelPointEnd = iPointEnd;
InvalidateBar( iBarStart, 0, m_nBarWidth, BAR_TRACK | iTrack );
}
else{
if( iPointStart!=m_iSelPointStart ){
int l = min( m_iSelPointStart, iPointStart ),
r = max( m_iSelPointStart, iPointStart );
m_iSelPointStart = iPointStart;
InvalidateBar( iBarStart, l, r, BAR_TRACK | iTrack );
}
if( iPointEnd!=m_iSelPointEnd ){
int l = min( m_iSelPointEnd, iPointEnd ),
r = max( m_iSelPointEnd, iPointEnd );
m_iSelPointEnd = iPointEnd;
InvalidateBar( iBarEnd, l, r, BAR_TRACK | iTrack );
}
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoSelectAll(System::TObject* Sender)
{
if( m_nBarNum==0 )
return;
if( m_iMode==VIEW_TRACK ){
SelectRange( 0, 0, m_nBarNum-1, m_nDataWidth-1 );
}
else if( m_iMode==VIEW_STYLE ){
SelectBars( 0, m_nBarNum-1 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoCancelAll(System::TObject* Sender)
{
if( m_iMode==VIEW_CHORD ){
SelectCells( -1, -1, -1, -1 );
SelectCopyCells( -1, -1, -1, -1 );
}
else if( m_iMode==VIEW_TRACK ){
SelectRange( -1, -1, -1, -1 );
SelectCopyPos( -1, -1, -1, -1 );
}
else if( m_iMode==VIEW_STYLE ){
SelectBars( -1, -1 );
SelectCopyBars( -1, -1 );
}
ReleaseCapture();
m_bDragReady = false;
m_bDraging = false;
m_bBrush = false;
m_iMouseDownBar = m_iMouseDownPoint = -1;
m_pItem = NULL;
}
//---------------------------------------------------------------------------
// 复制
void __fastcall TContentPanel::DoBarsCopy(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarEnd>=0 ){
bool bSetCopy = false;
int iLSBar, iStage = FindStage( m_iSelBarEnd, &iLSBar );
if( g_lstOpusStages[iStage]->iSegType==SEGTYPE_ENDING ){
int iFirstStage = FindStage( m_iSelBarStart, NULL );
if( iFirstStage!=iStage ){
SelectBars( m_iSelBarStart, iLSBar-1 );
bSetCopy = true;
}
}
else{
bSetCopy = true;
}
if( bSetCopy )
SelectCopyBars( m_iSelBarStart, m_iSelBarEnd, false );
}
}
//---------------------------------------------------------------------------
// 剪切
void __fastcall TContentPanel::DoBarsCut(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarEnd>=0 ){
bool bSetCopy = false;
int iLSBar, iStage = FindStage( m_iSelBarEnd, &iLSBar );
if( g_lstOpusStages[iStage]->iSegType==SEGTYPE_ENDING ){
int iFirstStage = FindStage( m_iSelBarStart, NULL );
if( iFirstStage!=iStage ){
SelectBars( m_iSelBarStart, iLSBar-1 );
bSetCopy = true;
}
}
else{
bSetCopy = true;
}
if( bSetCopy )
SelectCopyBars( m_iSelBarStart, m_iSelBarEnd, true );
}
}
//---------------------------------------------------------------------------
// 插入
void __fastcall TContentPanel::DoBarsInsert(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarStart>=0 && m_iCopyBarStart>=0 ){
int iSelStart = m_iSelBarStart,
//iSelEnd = m_iSelBarEnd,
iCopyStart = m_iCopyBarStart,
iCopyEnd = m_iCopyBarEnd;
((TUseStylePanel*)m_pStylePanel)->MoveBars( iCopyStart, iCopyEnd,
iSelStart, m_bCut ? MODE_MOVE : MODE_COPY );
SelectCopyBars( m_iSelBarStart, m_iSelBarEnd );
}
}
//---------------------------------------------------------------------------
// 删除
void __fastcall TContentPanel::DoBarsDelete(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarStart>=0 ){
((TUseStylePanel*)m_pStylePanel)->MoveBars( m_iSelBarStart,
m_iSelBarEnd, -1, MODE_DELETE );
}
}
//---------------------------------------------------------------------------
// 变调
void __fastcall TContentPanel::DoBarsChangeKey(System::TObject* Sender)
{
if( !m_bDraging ){
int iKey = (int)Sender;
if( iKey<0 )
return;
int* arrKeys = new int[m_iSelBarEnd-m_iSelBarStart+1];
GetBarKeys( m_iSelBarStart, m_iSelBarEnd, arrKeys );
g_Undo.AddUndo( UNDO_KEY_BARS, 0, m_iSelBarStart, m_iSelBarEnd, arrKeys, (void*)iKey );
ChangeBarsKey( m_iSelBarStart, m_iSelBarEnd, iKey, NULL );
}
}
//---------------------------------------------------------------------------
void TContentPanel::GetBarKeys( int iBarStart, int iBarEnd, int arrKeys[] )
{
/* if( g_iPreStage==0 ){
for( int i=iBarStart; i<=iBarEnd; i++ ){
arrKeys[i] = g_lstRawBars[i]->iBarKey;
}
}
else{
*/ int iBar = iBarStart;
while( iBar<=iBarEnd ){
int iFirstBar, iStage = FindStage( iBar, &iFirstBar );
TOpusStage* pStage = g_lstOpusStages[iStage];
int iStart = max( iBar, iFirstBar ),
iEnd = min( iBarEnd, (int)(iFirstBar + pStage->aBars.size() - 1) );
for( int i = iStart; i<=iEnd; i++ ){
arrKeys[iBar-iBarStart] = pStage->iSegType>=SEGTYPE_INTRO ? pStage->iSegKey
: pStage->aBars[i-iFirstBar]->iBarKey;
}
iBar = iEnd + 1;
}
// }
}
//---------------------------------------------------------------------------
void TContentPanel::SelectCopyBars( int iBarStart, int iBarEnd, bool bCut )
{
m_bCut = bCut;
if( m_iCopyBarStart==iBarStart && m_iCopyBarEnd==iBarEnd )
return;
int iOldBarStart = m_iCopyBarStart,
iOldBarEnd = m_iCopyBarEnd;
m_iCopyBarStart = iBarStart;
m_iCopyBarEnd = iBarEnd;
if( iBarStart<0 && iBarEnd<0 ){
m_iCopyCellStart = m_iCopyCellEnd = -1;
m_iCopyPointStart = m_iCopyPointEnd = -1;
}
if( iOldBarStart>=0 ){
if( iBarStart>=0 ){
if( iBarStart<=iOldBarEnd || iBarEnd>=iOldBarStart ){
int iStart = min( iBarStart, iOldBarStart ),
iEnd = max( iBarEnd, iOldBarEnd );
InvalidateBars( iStart, iEnd, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd, BAR_TITLE|BAR_DATA|BAR_TRACK );
InvalidateBars( iBarStart, iBarEnd, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
else{
InvalidateBars( iOldBarStart, iOldBarEnd, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
else if( iBarStart>=0 ){
InvalidateBars( iBarStart, iBarEnd, BAR_TITLE|BAR_DATA|BAR_TRACK );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoChordCopy(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarStart>=0 ){
SelectCopyCells( m_iSelBarStart, m_iSelCellStart, m_iSelBarEnd, m_iSelCellEnd );
}
}
//---------------------------------------------------------------------------
void TContentPanel::ChordPaste( int key[], int type[], int len, bool bAddUndo )
{
BYTE *pBefore=NULL, *pAfter=NULL;
int iSelChordNum = (m_iSelBarEnd - m_iSelBarStart - 1) * g_nChordNumPerBar
+ (g_nChordNumPerBar - m_iSelCellStart) + (m_iSelCellEnd + 1);
int iCell, iStage, iBarCount, iBar, iBarFirst, index = 0, iUndo=0;
iCell = m_iSelCellStart;
iBar = m_iSelBarStart;
iStage = FindStage(iBar, &iBarFirst);
TOpusStage *pStage = g_lstOpusStages[iStage];
iBarCount = pStage->aBars.size();
int iSBar = iBar - iBarFirst;
TBar *pBar = pStage->aBars[iSBar];
if( bAddUndo ){
pBefore = new BYTE[iSelChordNum];
pAfter = new BYTE[iSelChordNum];
}
while(iSelChordNum--){
if( pBefore && pAfter ){
pBefore[iUndo] = ( pBar->aChords.iKey[iCell]<<4 ) + pBar->aChords.iType[iCell];
pAfter[iUndo] = ( key[index]<<4 ) + type[index];
iUndo++;
}
pBar->aChords.iKey[iCell] = key[index];
pBar->aChords.iType[iCell] = type[index];
if( g_iPreStage==0 ){ //初始化模式时须修改原始和弦
TOpusStage* pRawStage = g_Theme.StageList()[iStage];
pRawStage->aBars[iSBar]->aChords.iKey[iCell] = key[index];
pRawStage->aBars[iSBar]->aChords.iType[iCell] = type[index];
}
index++;
if(index == len) index = 0; // 重复粘贴
iCell++;
if(iCell >= g_nChordNumPerBar){
iCell = 0;
iBar++;
if((iBar - iBarFirst) >= iBarCount){
if( ++iStage>=g_lstOpusStages.size() )
break;
iBarFirst = FirstBar(iStage);
pStage = g_lstOpusStages[iStage];
iBarCount = pStage->aBars.size();
}
iSBar = iBar - iBarFirst;
pBar = pStage->aBars[iSBar];
}
}
if( bAddUndo ){
int iBegin = MAKELONG( m_iSelCellStart, m_iSelBarStart ),
iEnd = MAKELONG( m_iSelCellEnd, m_iSelBarEnd );
g_Undo.AddUndo( UNDO_CHORD, 0, iBegin, iEnd, (void*)pBefore, (void*)pAfter );
}
InvalidateBars( m_iSelBarStart, m_iSelBarEnd );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoChordPaste(System::TObject* Sender)
{
if( m_bDraging || m_iSelBarStart<0 || m_iCopyBarStart<0 )
return;
else if( m_iCopyBarStart==m_iSelBarStart && m_iCopyCellStart==m_iSelCellStart )// 不粘贴
return;
int iChordNum = (m_iCopyBarEnd - m_iCopyBarStart - 1) * g_nChordNumPerBar
+ (g_nChordNumPerBar - m_iCopyCellStart) + (m_iCopyCellEnd + 1);
int *iKey = new int[iChordNum];
int *iType = new int[iChordNum];
int iCell, iStage, iBarCount, iBar, iBarFirst;
TOpusStage *pStage = NULL;
TBar *pBar = NULL;
iCell = m_iCopyCellStart;
iBar = m_iCopyBarStart;
iStage = FindStage(iBar, &iBarFirst);
pStage = g_lstOpusStages[iStage];
iBarCount = pStage->aBars.size();
pBar = pStage->aBars[iBar - iBarFirst];
for(int i = 0; i < iChordNum; i++) {
iKey[i] = pBar->aChords.iKey[iCell];
iType[i] = pBar->aChords.iType[iCell];
iCell++;
if(iCell >= g_nChordNumPerBar){
iCell = 0;
iBar++;
if((iBar - iBarFirst) >= iBarCount){
if( ++iStage>=g_lstOpusStages.size() )
break;
iBarFirst = FirstBar(iStage);
pStage = g_lstOpusStages[iStage];
iBarCount = pStage->aBars.size();
}
pBar = pStage->aBars[iBar - iBarFirst];
}
}
ChordPaste(iKey, iType, iChordNum);
delete[] iKey;
delete[] iType;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoChordDelete(System::TObject* Sender)
{
if( m_bDraging || m_iSelBarStart<0 )
return;
int iBar = -1, iCell = -1;
TOpusStage *pStage = NULL;
TBar *pBar = NULL;
if(m_iSelCellStart > 0)
{
iBar = m_iSelBarStart;
iCell = m_iSelCellStart - 1;
}
else
{
iBar = m_iSelBarStart - 1;
iCell = g_nChordNumPerBar - 1;
}
if( iBar>=0 ){
int iBarFirst, iStage = FindStage(iBar, &iBarFirst);
if( iStage>=0 ){
pStage = g_lstOpusStages[iStage];
if( pStage->iSegType<=SEGTYPE_FILL ){
pBar = pStage->aBars[iBar - iBarFirst];
int iKey = pBar->aChords.iKey[iCell],
iType = pBar->aChords.iType[iCell];
SetSelectChord( iKey, iType );
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::CreateEditMenu(TMenuPanel *Menu, bool bEnabled)
{
if( g_Opus.BarCount()==0 || !bEnabled )
return;
if(m_iMode == VIEW_CHORD){
Menu->CreateMenu("-");
CMenuItem* pMenuItem = Menu->CreateMenu( "复制和弦", "Ctrl+C", DoChordCopy );
pMenuItem->Enabled = m_iSelBarStart>=0;
pMenuItem = Menu->CreateMenu( "粘贴和弦", "Ctrl+V", DoChordPaste );
pMenuItem->Enabled = m_iSelBarStart>=0 && m_iCopyBarStart>=0;
Menu->CreateMenu("-");
pMenuItem = Menu->CreateMenu( "与前一和弦相同", "Ctrl+Del", DoChordDelete );
bool bCanDelete = false;
if( m_iSelCellStart != -1 ){
int iFirstBar, iSelStage = FindStage( m_iSelBarStart, &iFirstBar );
if( m_iSelBarStart!=iFirstBar ){
bCanDelete = true;
}
else if(m_iSelBarStart==iFirstBar && m_iSelCellStart > 0){
bCanDelete = true;
}
else if(iSelStage > 0){
TOpusStage *pPreStage = g_lstOpusStages[iSelStage-1];
if( pPreStage->iSegType<=SEGTYPE_FILL ){
bCanDelete = true;
}
}
}
pMenuItem->Enabled = bCanDelete;
}
else if(m_iMode == VIEW_STYLE){
Menu->CreateMenu("-");
bool bSel = m_iSelBarStart>=0;
bool bCanCopy = bSel;
if( m_iSelBarEnd>=0 ){
int iStage = FindStage( m_iSelBarEnd, NULL );
if( g_lstOpusStages[iStage]->iSegType==SEGTYPE_ENDING )
bCanCopy = false;
}
CMenuItem* pMenuItem = Menu->CreateMenu( "复制小节", "Ctrl+C", DoBarsCopy );
pMenuItem->Enabled = bSel && bCanCopy;
pMenuItem = Menu->CreateMenu( "剪切小节", "Ctrl+X", DoBarsCut );
pMenuItem->Enabled = bSel && bCanCopy;
Menu->CreateMenu( "-" );
pMenuItem = Menu->CreateMenu( "插入空小节","Ctrl+Ins",DoInsertBlankBar );
pMenuItem->Enabled = bSel;
if( m_iCopyBarStart>=0 ){
String strText = "插入";
strText += m_bCut ? "剪切的小节" : "复制的小节";
pMenuItem = Menu->CreateMenu( strText,"Ctrl+V",DoBarsInsert );
pMenuItem->Enabled = bSel && m_iCopyBarStart>=0;
}
pMenuItem = Menu->CreateMenu( "删除所选小节", "Ctrl+Del", DoBarsDelete );
pMenuItem->Enabled = bSel;
Menu->CreateMenu("-");
pMenuItem = Menu->CreateMenu( "改变所选小节调号" );
pMenuItem->Enabled = bSel;
if( bSel ){
for( int i=0; i<KEY_NUM; i++ ){
pMenuItem->AppendMenu( g_strMelodyKey[i], "", DoBarsChangeKey, i );
}
}
Menu->CreateMenu("-");
pMenuItem = Menu->CreateMenu( "全选", "Ctrl+A", DoSelectAll );
pMenuItem->Enabled = m_nBarNum>0;
}
else{
Menu->CreateMenu("-");
String strMute = "所选轨道静音",
strSolo = "所选轨道独奏";
if( m_iSelTrack>=0 ){
bool bMute = m_aTracks[m_iSelTrack]->pTrack->IsMute(),
bSolo = m_aTracks[m_iSelTrack]->pTrack->IsSolo();
if( bMute )
strMute = "取消" + strMute;
if( bSolo )
strSolo = "取消" + strSolo;
}
CMenuItem* pMenuItem = Menu->CreateMenu( strMute, "", DoTrackMute );
pMenuItem->Enabled = m_iSelTrack>=0;
pMenuItem = Menu->CreateMenu( strSolo, "",DoTrackSolo );
pMenuItem->Enabled = m_iSelTrack>=0;
pMenuItem = Menu->CreateMenu( "删除所选轨道", "", DoTrackDel, IDM_TRKSHOW+m_iSelTrack );
pMenuItem->Enabled = m_iSelTrack>=0;
pMenuItem = Menu->CreateMenu( "隐藏所选轨道", "", DoTrackHide, IDM_TRKSHOW+m_iSelTrack );
pMenuItem->Enabled = m_iSelTrack>=0;
Menu->CreateMenu("-");
pMenuItem = Menu->CreateMenu( "全选", "Ctrl+A", DoSelectAll );
pMenuItem->Enabled = m_iSelTrack>=0;
if( m_iSelTrack>=0 ){
if( m_aTracks[m_iSelTrack]->type==ST_AUDIO ){
pMenuItem = Menu->CreateMenu( "复制所选音频", "Ctrl+C", DoAudioCopy );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
pMenuItem = Menu->CreateMenu( "剪切所选音频", "Ctrl+X", DoAudioCut );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
pMenuItem = Menu->CreateMenu( "删除所选音频", "Ctrl+Del", DoAudioDelete );
pMenuItem->Enabled = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
if( m_iCopyBarStart>=0 ){
Menu->CreateMenu("-");
String strText = "粘贴";
strText += m_bCut ? "剪切的音频" : "复制的音频";
pMenuItem = Menu->CreateMenu( strText, "Ctrl+V", DoAudioPaste );
}
Menu->CreateMenu("-");
Menu->CreateMenu( "设为录音起点", "", DoSetSelPosStart );
Menu->CreateMenu( "设为录音终点", "", DoSetSelPosEnd );
pMenuItem = Menu->CreateMenu( "取消录音起点", "", DoDelSelPosStart );
pMenuItem->Enabled = m_iSelBarStart>=0;
pMenuItem = Menu->CreateMenu( "取消录音终点", "", DoDelSelPosEnd );
pMenuItem->Enabled = m_iSelBarEnd>=0;
Menu->CreateMenu("-");
Menu->CreateMenu( "插入音频片段...", "Ctrl+Ins", DoAudioLoad );
bool bSP = m_iSelBarStart>=0 || m_iSelBarEnd>=0;
CMenuItem *pMSPFx = NULL,
*pMSPVst = NULL,
*pMSP = Menu->CreateMenu( "局部音效处理" ),
*pMAdd = Menu->CreateMenu( "添加轨道音效" ),
*pMAddFx = pMAdd->AppendMenu( "Fx音效" ),
*pMAddVst = pMAdd->AppendMenu( "VST音效" );
pMSP->Enabled = bSP;
pMAddVst->Enabled = !g_lstVSTFx.empty();
if( bSP ){
pMSPFx = pMSP->AppendMenu( "Fx音效" );
pMSPVst = pMSP->AppendMenu( "VST音效" );
pMSPVst->Enabled = !g_lstVSTFx.empty();
}
for( int i=0; i<MAX_FX_NUM; i++ ){
if( pMSPFx )
pMSPFx->AppendMenu( g_strEffect[i], "", DoAudioFxProcess, i );
if( i<MAX_FX_NUM-1 )
pMAddFx->AppendMenu( g_strEffect[i], "", DoAudioAddFx, i );
}
if( !g_lstVSTFx.empty() ){
for( int i=0; i<g_lstVSTFx.size(); i++ ){
VSTINFO* pVST = g_lstVSTFx[i];
char fname[128],
*name = strrchr( pVST->strFileName, '\\' )+1,
*ext = strrchr( pVST->strFileName, '.' );
if( ext>name ){
strncpy( fname, name, ext-name );
fname[ext-name] = '\0';
}
else
strcpy(fname, name );
if( !pVST->aPlugins.empty() )
strcat( fname, " ..." );
if( pMSPVst )
pMSPVst->AppendMenu( fname, "", DoAudioVstProcess, i );
pMAddVst->AppendMenu( fname, "", DoAudioAddVst, i );
}
}
}
else{
bool bContent=false, bSwitch=false, bInsert=true;
if( m_iSelBarStart>=0 && m_iSelBarEnd>0 ){
TMidiTrack* pMT = (TMidiTrack*)m_aTracks[m_iSelTrack]->pTrack;
int iBStage = FindStage( m_iSelBarStart, NULL ),
iEStage = FindStage( m_iSelBarEnd, NULL );
for( int i=iBStage; i<=iEStage; i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
if( !bSwitch && pStage->iSegType<=SEGTYPE_FILL )
bSwitch = true;
if( bInsert && pMT->IsDrum() && pStage->aTracks[0]->iChanNo==9 )
bInsert = false;
}
for( int i=0; i<pMT->aStages.size(); i++ ){
int s = pMT->aStages[i];
if( s>=iBStage && s<=iEStage ){
bContent = true;
break;
}
else if( s>iEStage ){
break;
}
}
}
pMenuItem = Menu->CreateMenu( "插入织体...", "Ctrl+Ins", DoInsertTexture );
pMenuItem->Enabled = !bContent && bSwitch && bInsert;
pMenuItem = Menu->CreateMenu( "删除所选织体", "Ctrl+Del", DoDeleteTexture );
pMenuItem->Enabled = bContent;
pMenuItem = Menu->CreateMenu( "更换所选织体...", "", DoSwitchTexture );
pMenuItem->Enabled = bContent && bSwitch;
pMenuItem = Menu->CreateMenu( "更换所选乐器/音色...", "", DoSwitchFontProg );
pMenuItem->Enabled = bContent;
pMenuItem = Menu->CreateMenu( "更换轨道织体...", "", DoTrackSwitchTexture );
pMenuItem->Enabled = bContent && bSwitch;
pMenuItem = Menu->CreateMenu( "更换轨道乐器/音色...", "", DoTrackSwitchFontProg );
}
}
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::CreateTrackMenu(TMenuPanel *pMenu, bool bEnabled)
{
CMenuItem* pMenuItem = pMenu->CreateMenu( "新增" );
pMenuItem->Enabled = bEnabled && m_nBarNum;
if( pMenuItem->Enabled ){
CMenuItem* pSubMenu = pMenuItem->AppendMenu( "音频轨道", "", DoTrackAdd, ST_AUDIO );
pSubMenu->Enabled = g_aAudioTracks.size()<MAX_AUDIOTRACK;
pSubMenu = pMenuItem->AppendMenu( "MIDI轨道...", "", DoTrackAdd, ST_MIDI );
pSubMenu->Enabled = !m_bVertical;
}
pMenuItem = pMenu->CreateMenu( "删除" );
pMenuItem->Enabled = bEnabled && m_nBarNum;
if( pMenuItem->Enabled ){
CMenuItem* pSubMenu = pMenuItem->AppendMenu( "全部音频轨道", "", DoTrackDel, ST_AUDIO );
pSubMenu->Enabled = g_iPreStage==0 && !g_aAudioTracks[0]->lstBars.empty()
|| g_iPreStage!=0 && g_aAudioTracks.size()>1;
pSubMenu = pMenuItem->AppendMenu( "全部MIDI轨道", "", DoTrackDel, ST_MIDI );
pSubMenu->Enabled = !m_bVertical && !g_Midi.IsEmpty();
}
pMenuItem = pMenu->CreateMenu( "隐藏" );
pMenuItem->Enabled = bEnabled && m_nBarNum;
if( pMenuItem->Enabled ){
CMenuItem* pSubMenu = pMenuItem->AppendMenu( "全部音频轨道", "", DoTrackHide, ST_AUDIO );
bool bCanDo = false;
if( g_iPreStage==0 ){
if( !g_aAudioTracks[0]->lstBars.empty() && !g_aAudioTracks[0]->IsHide() )
bCanDo = true;
}
else{
for( int i=1; i<g_aAudioTracks.size(); i++ ){
if( !g_aAudioTracks[i]->IsHide() ){
bCanDo = true;
break;
}
}
}
pSubMenu->Enabled = bCanDo;
pSubMenu = pMenuItem->AppendMenu( "全部MIDI轨道", "", DoTrackHide, ST_MIDI );
bCanDo = false;
if( !m_bVertical ){
for( int i=0; i<g_aMidiTracks.size(); i++ ){
if( !g_aMidiTracks[i]->IsHide() ){
bCanDo = true;
break;
}
}
}
pSubMenu->Enabled = bCanDo;
}
pMenuItem = pMenu->CreateMenu( "显示" );
pMenuItem->Enabled = bEnabled && m_nBarNum;
if( pMenuItem->Enabled ){
bool bHasSubAudio = false,
bHasSubMidi = false;
String strText;
CMenuItem *pAudioMenu = pMenuItem->AppendMenu( "全部音频轨道", "", DoTrackShow, ST_AUDIO ),
*pMidiMenu = pMenuItem->AppendMenu( "全部MIDI轨道", "", DoTrackShow, ST_MIDI );
/*//////////////////////////////////////////////////
// test code
pMenuItem->AppendMenu( "-" );
for( int i=0; i<25; i++ ){
strText = "测试音频轨道 " + IntToStr( i );
pMenuItem->AppendMenu( strText );
}
pMenuItem->AppendMenu( "-" );
for( int i=0; i<25; i++ ){
strText = "测试MIDI轨道 " + IntToStr( i );
pMenuItem->AppendMenu( strText );
}
pMenuItem->AppendMenu( "-" );
for( int i=0; i<25; i++ ){
strText = "测试Other轨道 " + IntToStr( i );
pMenuItem->AppendMenu( strText );
}
//
/*///////////////////////////////////////////////////
/* for( int i=0; i<m_aTracks.size(); i++ ){
TShowTrack* pST = m_aTracks[i];
if( pST->pTrack->IsHide() ){
if( pST->type==ST_AUDIO ){
if( !bHasSubAudio ){
pMenuItem->AppendMenu( "-" );
bHasSubAudio = true;
}
int iTrk = pST->index==0 ? 1 : pST->index;
strText = "音频轨道 " + IntToStr( iTrk );
pMenuItem->AppendMenu( strText, "", DoTrackShow, IDM_TRKSHOW+i );
}
else{
if( !bHasSubMidi ){
pMenuItem->AppendMenu( "-" );
bHasSubMidi = true;
}
strText = "MIDI轨道 " + IntToStr( pST->index+1 );
pMenuItem->AppendMenu( strText, "", DoTrackShow, IDM_TRKMID+i );
}
}
}
*/
if( g_iPreStage!=0 && g_aAudioTracks.size()>1 ){
for (int i = 1; i < g_aAudioTracks.size(); i++) {
if( g_aAudioTracks[i]->IsHide() ){
if( !bHasSubAudio ){
pMenuItem->AppendMenu( "-" );
bHasSubAudio = true;
}
strText = "音频轨道 " + IntToStr( i );
pMenuItem->AppendMenu( strText, "", DoTrackShow, IDM_TRKAUD+i );
}
}
}
else if( g_iPreStage==0 && g_aAudioTracks[0]->IsHide() && !g_aAudioTracks[0]->lstBars.empty() ){
pMenuItem->AppendMenu( "-" );
bHasSubAudio = true;
strText = "音频轨道 " + IntToStr( 1 );
pMenuItem->AppendMenu( strText, "", DoTrackShow, IDM_TRKAUD );
}
if( !m_bVertical ){
for (int i = 0; i < g_aMidiTracks.size(); i++) {
if( g_aMidiTracks[i]->IsHide() ){
if( !bHasSubMidi ){
pMenuItem->AppendMenu( "-" );
bHasSubMidi = true;
}
strText = "MIDI轨道 " + IntToStr( i+1 );
pMenuItem->AppendMenu( strText, "", DoTrackShow, IDM_TRKMID+i );
}
}
}
pAudioMenu->Enabled = bHasSubAudio;
pMidiMenu->Enabled = bHasSubMidi;
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoSetSelPosStart(System::TObject* Sender)
{
int iHitType = -1;
DWORD dwHit = HitTest( ptDown.X, ptDown.Y, iHitType );
int iBarStart = LOWORD(dwHit),
iPointStart = HIWORD(dwHit),
iBarEnd = m_iSelBarEnd,
iPointEnd = m_iSelPointEnd;
int iMaxPoint = m_nBarNum * m_nDataWidth - 1,
iStartPoint = iBarStart * m_nDataWidth + iPointStart;
int minArea = max( 10, (int)( g_nPPB / 4.0 + 0.5 ));
if( iStartPoint > iMaxPoint - minArea ){
iStartPoint = iMaxPoint - minArea;
iBarStart = iStartPoint / m_nDataWidth;
iPointStart = iStartPoint % m_nDataWidth;
}
if( iBarEnd>=0 ){
int iEndPoint = iBarEnd * m_nDataWidth + iPointEnd;
if( iEndPoint > iStartPoint ){
if( iEndPoint < iStartPoint + minArea ){
iEndPoint = iStartPoint + minArea;
iBarEnd = iEndPoint / m_nDataWidth;
iPointEnd = iEndPoint % m_nDataWidth;
}
}
else{
iBarEnd = -1;
iPointEnd = -1;
}
}
SelectRange( iBarStart, iPointStart, iBarEnd, iPointEnd );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoSetSelPosEnd(System::TObject* Sender)
{
int iHitType = -1;
DWORD dwHit = HitTest( ptDown.X, ptDown.Y, iHitType );
int iBarStart = m_iSelBarStart,
iPointStart = m_iSelPointStart,
iBarEnd = LOWORD(dwHit),
iPointEnd = HIWORD(dwHit);
int iMinPoint = 0,
iEndPoint = iBarEnd * m_nDataWidth + iPointEnd;
int minArea = max( 10, (int)( g_nPPB / 4.0 + 0.5 ));
if( iEndPoint < iMinPoint + minArea ){
iEndPoint = iMinPoint + minArea;
iBarEnd = iEndPoint / m_nDataWidth;
iPointEnd = iEndPoint % m_nDataWidth;
}
if( iBarStart>=0 ){
int iStartPoint = iBarStart * m_nDataWidth + iPointStart;
if( iEndPoint > iStartPoint ){
if( iEndPoint < iStartPoint + minArea ){
iStartPoint = iEndPoint - minArea;
iBarStart = iStartPoint / m_nDataWidth;
iPointStart = iStartPoint % m_nDataWidth;
}
}
else{
iBarStart = -1;
iPointStart = -1;
}
}
SelectRange( iBarStart, iPointStart, iBarEnd, iPointEnd );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoDelSelPosStart(System::TObject* Sender)
{
if( m_iSelBarStart>=0 ){
SelectRange( -1, -1, m_iSelBarEnd, m_iSelPointEnd );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoDelSelPosEnd(System::TObject* Sender)
{
if( m_iSelBarEnd>=0 ){
SelectRange( m_iSelBarStart, m_iSelPointStart, -1, -1 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoInsertBlankBar(System::TObject* Sender)
{
if( !m_bDraging && m_iSelBarStart>=0 ){
bool bPreChange = g_iPreStage==0;
if( bPreChange ){
DuplicateRawBars();
PostMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
}
f_MM_AddUndoBefore( -1, NULL );
((TUseStylePanel*)m_pStylePanel)->InsertBlankBar( m_iSelBarStart );
if( bPreChange )
InitialVars();
SelectBars( m_iSelBarStart, m_iSelBarStart );
f_MM_AddUndoAfter( -1, NULL );
((TUseStylePanel*)m_pStylePanel)->SetBarsUndo( UNDO_BAR_INSERT, m_iSelBarStart, 1 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackAdd(System::TObject* Sender)
{
Parent->Perform( UM_STOP, STOP_CONTENT, 0 );
if( (int)Sender==ST_AUDIO ){
if( g_iPreStage==0 ){
DuplicateRawBars();
PostMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
}
TAudioTrack* pTrack = NewAudioTrack( g_Opus.BarCount() );
if( pTrack ){
if( VIEW_TRACK!=m_iMode )
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );
InitialVars();
SelectTrack( m_aTracks.size()-1, -1, -1 );
ShowPlayPoint();
}
}
else{
Parent->Perform( UM_STOP, STOP_USESTYLE, 0 );
ChangeMidiTrack();
ShowPlayPoint();
}
}
//---------------------------------------------------------------------------
/*
void __fastcall TContentPanel::DoTrackAddAudio(System::TObject* Sender)
{
Parent->Perform( UM_STOP, STOP_CONTENT | STOP_USESTYLE, 0 );
if( g_iPreStage==0 ){
DuplicateRawBars();
PostMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
// Parent->Perform( UM_STAGECHANGED, 3, 0 );
}
TAudioTrack* pTrack = NewAudioTrack( g_Opus.BarCount() );
if( pTrack ){
if( VIEW_TRACK!=m_iMode )
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );
InitialVars();
SelectTrack( m_aTracks.size()-1, -1, -1 );
ShowPlayPoint();
// Application->MainForm->Perform( UM_ENABLERECORD, 0, 0 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackAddMidi(System::TObject* Sender)
{
ChangeMidiTrack();
ShowPlayPoint();
}
//---------------------------------------------------------------------------
*/
void __fastcall TContentPanel::DoTrackDel(System::TObject* Sender)
{
if( m_nBarNum==0 )
return;
Parent->Perform( UM_STOP, STOP_CONTENT, 0 );
int iType = (int)Sender,
index = iType<IDM_TRKSHOW ? -1 : iType - IDM_TRKSHOW;
bool bSolo = false;
if( index<0 ){
if( iType==ST_AUDIO ){
if( !g_aAudioTracks.empty() ){
if( g_iPreStage==0 && !g_aAudioTracks[0]->lstBars.empty() ){
if( g_aAudioTracks[0]->IsSolo() )
bSolo = true;
}
else if( g_aAudioTracks.size()>1 ){
for (int i = 1; i < g_aAudioTracks.size(); i++) {
if( g_aAudioTracks[i]->IsSolo() )
bSolo = true;
}
}
DeleteAudioTrack(-1);
InitialVars();
}
}
else{
Parent->Perform( UM_STOP, STOP_USESTYLE, 0 );
if( !m_bVertical && g_aMidiTracks.size()>0 ){
((TUseStylePanel*)m_pStylePanel)->DeleteAllTexture();
}
}
}
else{
TShowTrack* pST = m_aTracks[index];
bSolo = pST->pTrack->IsSolo();
if( pST->type==ST_AUDIO ){
DeleteAudioTrack( pST->index );
InitialVars();
}
else{
Parent->Perform( UM_STOP, STOP_USESTYLE, 0 );
((TUseStylePanel*)m_pStylePanel)->ChangeTexture( -1, -1, -1, pST->index, NULL, ST_MIDI );
}
}
if( bSolo )
SetTrackParams();
SelectTrack( -1, -1, -1 );
ShowPlayPoint();
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackShow(System::TObject* Sender)
{
int iType = (int)Sender,
index = -1;
vector<BYTE>* arrIndex = new vector<BYTE>;
if( iType>=IDM_TRKMID ){
index = iType - IDM_TRKMID;
iType = ST_MIDI;
}
else if( iType>=IDM_TRKAUD ){
index = iType - IDM_TRKAUD;
iType = ST_AUDIO;
}
if( iType==ST_AUDIO ){
if( g_iPreStage!=0 && g_aAudioTracks.size()>1 ){
for (int i = 1; i < g_aAudioTracks.size(); i++) {
if( (index<0 || index==i) && g_aAudioTracks[i]->IsHide() ){
g_aAudioTracks[i]->Hide( false );
arrIndex->push_back( (BYTE)i );
}
}
}
else if( g_iPreStage==0 && index<=0 && g_aAudioTracks[0]->IsHide()
&& !g_aAudioTracks[0]->lstBars.empty() ){
g_aAudioTracks[0]->Hide( false );
arrIndex->push_back( (BYTE)0 );
}
}
else{
for (int i = 0; i < g_aMidiTracks.size(); i++) {
if( ( index<0 || index==i ) && g_aMidiTracks[i]->IsHide() ){
g_aMidiTracks[i]->Hide( false );
arrIndex->push_back( (BYTE)i );
}
}
}
if( arrIndex->empty() ){
delete arrIndex;
}
else{
if( index<0 ){
if( iType==ST_AUDIO )
g_Undo.AddUndo( UNDO_TRKAUD_SHOWALL, 0, -1, -1, (void*)arrIndex, NULL );
else
g_Undo.AddUndo( UNDO_TRKMID_SHOWALL, 0, -1, -1, (void*)arrIndex, NULL );
}
else{
if( iType==ST_AUDIO )
g_Undo.AddUndo( UNDO_TRKAUD_SHOW, 0, -1, -1, (void*)arrIndex, NULL );
else
g_Undo.AddUndo( UNDO_TRKMID_SHOW, 0, -1, -1, (void*)arrIndex, NULL );
}
InitialVars();
ShowPlayPoint();
if( arrIndex->size()==1 ){
int iShowTrk = (*arrIndex)[0],
id = GetShowTrackId( iType, iShowTrk ) - 1;
SelectTrack( id, -1, -1 );
}
else{
SelectTrack( -1, -1, -1 );
}
if( iType==ST_AUDIO )
Application->MainForm->Perform( UM_ENABLERECORD, 0, 0 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackHide(System::TObject* Sender)
{
int iType = (int)Sender,
index = iType<IDM_TRKSHOW ? -1 : iType - IDM_TRKSHOW;
vector<BYTE>* arrIndex = new vector<BYTE>;
bool bUnselect = false;
if( index<0 ){
for( int i=0; i<m_aTracks.size(); i++ ){
TShowTrack* pST = m_aTracks[i];
if( pST->type==iType && !pST->pTrack->IsHide() ){
pST->pTrack->Hide(true);
arrIndex->push_back( pST->index );
if( m_iSelTrack==i )
bUnselect = true;
}
}
}
else{
TShowTrack* pST = m_aTracks[index];
iType = pST->type;
if( !pST->pTrack->IsHide() ){
pST->pTrack->Hide(true);
arrIndex->push_back( pST->index );
if( m_iSelTrack==index )
bUnselect = true;
}
}
if( arrIndex->empty() ){
delete arrIndex;
}
else{
if( index<0 ){
if( iType==ST_AUDIO )
g_Undo.AddUndo( UNDO_TRKAUD_HIDEALL, 0, -1, -1, (void*)arrIndex, NULL );
else
g_Undo.AddUndo( UNDO_TRKMID_HIDEALL, 0, -1, -1, (void*)arrIndex, NULL );
}
else{
if( iType==ST_AUDIO )
g_Undo.AddUndo( UNDO_TRKAUD_HIDE, 0, -1, -1, (void*)arrIndex, NULL );
else
g_Undo.AddUndo( UNDO_TRKMID_HIDE, 0, -1, -1, (void*)arrIndex, NULL );
}
if( bUnselect )
SelectTrack( -1, -1, -1 );
InitialVars();
ShowPlayPoint();
if( iType==ST_AUDIO )
Application->MainForm->Perform( UM_ENABLERECORD, 0, 0 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackMute(System::TObject* Sender)
{
((TTrackPanel*)m_pTrackPanel)->OnTrackStateChanged( TRACK_MUTE );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackSolo(System::TObject* Sender)
{
((TTrackPanel*)m_pTrackPanel)->OnTrackStateChanged( TRACK_SOLO );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioDelete(System::TObject* Sender)
{
if( m_bDraging || m_iSelBarStart<0 && m_iSelBarEnd<0 )
return;
if( m_bPlaying )
Parent->Perform( UM_STOP, STOP_CONTENT, 0 );
if( m_iSelBarStart<0 ){
m_iSelBarStart = 0;
m_iSelPointStart = 0;
}
if( m_iSelBarEnd<0 ){
m_iSelBarEnd = m_nBarNum-1;
m_iSelPointEnd = m_nDataWidth-1;
}
double dblStartPoint = m_iSelBarStart + (double)m_iSelPointStart / POINTS_PER_BAR,
dblEndPoint = m_iSelBarEnd + (double)m_iSelPointEnd / POINTS_PER_BAR;
// TAudioTrack* pTrack = g_aAudioTracks[g_iSelAudio];
//Set Undo
DWORD* aWave = NULL;
if( g_iSelAudio>0 ){
CopyWave( g_iSelAudio, m_iSelBarStart, m_iSelPointStart,
m_iSelBarEnd, m_iSelPointEnd, &aWave );
g_Undo.AddUndo( UNDO_AUDIO_ERASE, g_iSelAudio,
MAKELONG( m_iSelPointStart, m_iSelBarStart ),
MAKELONG( m_iSelPointEnd, m_iSelBarEnd ),
(void*)aWave, NULL );
}
else{
TAudioTrack* pAudio = CopyAudioTrack( g_iSelAudio, 0, m_nBarNum );
g_Undo.AddUndo( UNDO_AUDIO_ERASE, g_iSelAudio, g_iMelodyKey, -1,
(void*)pAudio, NULL );
}
f_MM_AddUndoBefore( 1, &g_iSelAudio );
MoveAudio( g_iSelAudio, dblStartPoint, dblEndPoint, -1, -1, MODE_ERASE );
if( g_iSelAudio>0 ){
f_MM_AddUndoAfter( 1, &g_iSelAudio );
InvalidateBars( m_iSelBarStart, m_iSelBarEnd,
BAR_TRACK | GetShowTrackId(ST_AUDIO,g_iSelAudio) );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioCopy(System::TObject* Sender)
{
if( m_bDraging || m_iSelBarStart<0 && m_iSelBarEnd<0 )
return;
SelectCopyPos( m_iSelBarStart, m_iSelPointStart, m_iSelBarEnd, m_iSelPointEnd );
m_bCut = false;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioCut(System::TObject* Sender)
{
if( m_bDraging || m_iSelBarStart<0 && m_iSelBarEnd<0 )
return;
SelectCopyPos( m_iSelBarStart, m_iSelPointStart, m_iSelBarEnd, m_iSelPointEnd );
m_bCut = true;
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioPaste(System::TObject* Sender)
{
if( m_bDraging || g_iSelAudio<0 || m_iSelTrackBar<0
|| m_iCopyAudio<0 || m_iCopyBarStart<0 )
return;
else if( m_iCopyAudio==g_iSelAudio && m_iCopyBarStart==m_iSelTrackBar
&& m_iCopyPointStart==m_iSelTrackPoint )// 不粘贴
return;
AudioMove( m_iCopyAudio, m_iCopyBarStart, m_iCopyPointStart,
m_iCopyBarEnd, m_iCopyPointEnd, m_bCut );
if( m_bCut ){
SelectCopyPos( -1, -1, -1, -1 );
// m_bCut = false;
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioLoad(System::TObject* Sender)
{
PostMessage( Application->MainForm->Handle, UM_AUDIOLOAD, m_iSelTrackBar, m_iSelTrackPoint );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackSave(System::TObject* Sender)
{
if( g_iSelAudio>=0 ){ //导出音轨
PostMessage( Application->MainForm->Handle, UM_SAVEPROJECT, SAVE_AUDIO, g_iSelAudio+1 );
}
else{ //导出伴奏
PostMessage( Application->MainForm->Handle, UM_SAVEPROJECT, SAVE_COMPOSE, g_iSelMidiTrack+1 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioFxProcess(System::TObject* Sender)
{
int ind = (int)Sender;
OnAudioEffectProcess( g_aAudioEffectTypes[ind] );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioVstProcess(System::TObject* Sender)
{
int ind = (int)Sender;
OnAudioEffectProcess( FX_VST + ind );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioAddFx(System::TObject* Sender)
{
int ind = (int)Sender;
PostMessage( m_pTrackPanel->Handle, UM_AUDIOFX, 0, g_aAudioEffectTypes[ind] );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoAudioAddVst(System::TObject* Sender)
{
int ind = (int)Sender;
PostMessage( m_pTrackPanel->Handle, UM_AUDIOFX, 0, FX_VST+ind );
}
//---------------------------------------------------------------------------
void TContentPanel::OnAudioEffectProcess( int iFxType )
{
Parent->Perform( UM_STOP, STOP_ALL, 0 );
double dblEditStartBar = 0,
dblEditEndBar = m_nBarNum;
int iModifyBeginBar = m_iSelBarStart,
iModifyBeginPoint = m_iSelPointStart,
iModifyEndBar = m_iSelBarEnd,
iModifyEndPoint = m_iSelPointEnd;
if( iModifyBeginBar>=0 ){
dblEditStartBar = iModifyBeginBar + (double)iModifyBeginPoint/POINTS_PER_BAR;
}
else{
iModifyBeginBar = 0;
iModifyBeginPoint = 0;
}
if( iModifyEndBar>=0 ){
dblEditEndBar = iModifyEndBar + (double)iModifyEndPoint/POINTS_PER_BAR;
}
else{
iModifyEndBar = g_Opus.BarCount();
iModifyEndPoint = 0;
}
int iPlugin = -1;
UINT pluginID = 0;
char* strVSTFile = NULL;
if( iFxType>=FX_VST ){
VSTINFO* pVST = g_lstVSTFx[iFxType-FX_VST];
strVSTFile = pVST->strFileName;
if( !pVST->aPlugins.empty() ){
TVSTPluginForm* pPlugForm = new TVSTPluginForm( NULL, pVST );
if( pPlugForm->ShowModal()==mrOk ){
iPlugin = pPlugForm->m_iSel;
pluginID = pVST->aPlugins[iPlugin]->id;
}
delete pPlugForm;
if( iPlugin<0 )
return;
}
}
HRESULT hr = f_MM_AudioAddFx( g_iSelAudio, iFxType, strVSTFile, pluginID, true );
if( hr!=S_OK ){
return;
}
GenerateCompose();
TAudioFxForm * pForm = new TAudioFxForm(NULL, g_iSelAudio, dblEditStartBar, dblEditEndBar,
-1, iFxType, iPlugin );
if( pForm->ShowModal()==mrOk ){
// 保存处理前波形
DWORD *aBefore = NULL;
CopyWave( g_iSelAudio, iModifyBeginBar, iModifyBeginPoint,
iModifyEndBar, iModifyEndPoint, &aBefore );
f_MM_AddUndoBefore( 1, &g_iSelAudio );
TProgressForm * frmProgress = new TProgressForm(NULL);
int ret = frmProgress->MM_AudioFxApply( dblEditStartBar, dblEditEndBar );
int eExtra = frmProgress->GetOpertaionResult();
if( ret==mrOk ){
delete frmProgress;
f_MM_AddUndoAfter( 1, &g_iSelAudio );
// 获取处理后波形
int iVolBar = iModifyBeginBar,
iVolPoint = iModifyBeginPoint,
nPoints = ( iModifyEndBar * POINTS_PER_BAR + iModifyEndPoint )
- ( iModifyBeginBar * POINTS_PER_BAR + iModifyBeginPoint ),
iPoint = 0;
DWORD *aAfter = new DWORD[nPoints];
while( iPoint<nPoints ){
int iSP = 0, iEP = POINTS_PER_BAR;
if( iVolPoint>0 ){
iSP = iVolPoint;
if( iSP + nPoints - iPoint < POINTS_PER_BAR )
iEP = iSP + nPoints - iPoint;
}
else if( nPoints-iPoint < POINTS_PER_BAR ){
iEP = nPoints - iPoint;
}
if( iEP > iSP ){
TWaveBar* pBar = g_aAudioTracks[g_iSelAudio]->lstBars[iVolBar];
for( int i=iSP; i<iEP; i++ ){
pBar->aVols[i] = f_MM_GetAudioVolume( g_iSelAudio, iVolBar + i/(double)POINTS_PER_BAR );
}
if( aAfter ){
memcpy( aAfter + iPoint, pBar->aVols + iSP, sizeof(DWORD)*(iEP-iSP) );
}
iVolPoint = 0;
iVolBar++;
iPoint += iEP - iSP;
}
else{
break;
}
}
g_Undo.AddUndo( UNDO_AUDIO_FX, g_iSelAudio,
MAKELONG( iModifyBeginPoint, iModifyBeginBar ),
MAKELONG( iModifyEndPoint, iModifyEndBar ),
(void*)aBefore, (void*)aAfter );
InvalidateBars( iModifyBeginBar, iModifyEndBar, BAR_TRACK | (m_iSelTrack+1) );
}
else{
f_MM_CancelAddUndo();
if( eExtra!=e_UserCanceled ){
MessageForm->ShowMessage( "局部音效处理未成功!", MB_ICONERROR|MB_OK );
}
}
}
delete pForm;
f_MM_AudioMoveFx( g_iSelAudio, -1, -1 );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::OnTrackStateChanged( int iType, int iIndex, BYTE iState, bool bUnset )
{
if( m_bVertical || m_aTracks.empty() )
return;
int iShowTrack = GetShowTrackId( iType, iIndex );
if( iShowTrack>0 ){
RECT rect;
int lBox = iState==TRACK_MUTE ? m_nTrkHdrWidth+MUTE_LEFT : m_nTrkHdrWidth+SOLO_LEFT,
tBox = m_nTopBound + m_nRowGapHeight + m_nTitleHeight + m_nChordHeight + SM_TOP
+ ( iShowTrack - m_iBeginShowTrack - 1 ) * m_nTrackHeight;
SetRect( &rect, lBox, tBox, lBox + SM_SIZE, tBox + SM_SIZE );
if( bUnset ){
if( iState==TRACK_MUTE )
rect.right = m_nTrkHdrWidth+SOLO_LEFT + SM_SIZE;
else
rect.left = m_nTrkHdrWidth+MUTE_LEFT;
}
InvalidateRect( Handle, &rect, false );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoInsertTexture(TObject* Sender)
{
if( !Sender ){
bool bContent=false, bSwitch=false, bInsert=true;
if( m_iSelTrack>=0 && m_iSelBarStart>=0 && m_iSelBarEnd>0 ){
TMidiTrack* pMT = (TMidiTrack*)m_aTracks[m_iSelTrack]->pTrack;
int iBStage = FindStage( m_iSelBarStart, NULL ),
iEStage = FindStage( m_iSelBarEnd, NULL );
for( int i=iBStage; i<=iEStage; i++ ){
TOpusStage* pStage = g_lstOpusStages[i];
if( !bSwitch && pStage->iSegType<=SEGTYPE_FILL )
bSwitch = true;
if( bInsert && pMT->IsDrum() && pStage->aTracks[0]->iChanNo==9 )
bInsert = false;
}
for( int i=0; i<pMT->aStages.size(); i++ ){
int s = pMT->aStages[i];
if( s>=iBStage && s<=iEStage ){
bContent = true;
break;
}
else if( s>iEStage ){
break;
}
}
}
if( bContent || !bSwitch || !bInsert )
return;
}
ChangeMidiTrack( m_iSelTrack>=0 ? m_aTracks[m_iSelTrack]->index : -1,
m_iSelBarStart, m_iSelBarEnd );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoDeleteTexture(TObject* Sender)
{
if( m_iSelTrack>=0 && m_aTracks[m_iSelTrack]->type==ST_MIDI ){
if( !Sender ){
bool bContent=false;
if( m_iSelBarStart>=0 && m_iSelBarEnd>0 ){
TMidiTrack* pMT = (TMidiTrack*)m_aTracks[m_iSelTrack]->pTrack;
int iBStage = FindStage( m_iSelBarStart, NULL ),
iEStage = FindStage( m_iSelBarEnd, NULL );
for( int i=0; i<pMT->aStages.size(); i++ ){
int s = pMT->aStages[i];
if( s>=iBStage && s<=iEStage ){
bContent = true;
break;
}
else if( s>iEStage ){
break;
}
}
}
if( !bContent )
return;
}
Parent->Perform( UM_STOP, STOP_CONTENT | STOP_USESTYLE, 0 );
((TUseStylePanel*)m_pStylePanel)->ChangeTexture( m_iSelBarStart, m_iSelBarEnd,
-1, m_aTracks[m_iSelTrack]->index, NULL, ST_MIDI );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoSwitchTexture(TObject* Sender)
{
if( m_iSelTrack>=0 && m_aTracks[m_iSelTrack]->type==ST_MIDI ){
int iSBar = Sender==NULL ? -1 : m_iSelBarStart,
iEBar = Sender==NULL ? -1 : m_iSelBarEnd;
ChangeMidiTrack( m_aTracks[m_iSelTrack]->index, iSBar, iEBar );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackSwitchTexture(TObject* Sender)
{
DoSwitchTexture( NULL );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoSwitchFontProg(TObject* Sender)
{
if( m_iSelTrack>=0 && m_aTracks[m_iSelTrack]->type==ST_MIDI ){
Parent->Perform( UM_STOP, STOP_ALL, 0 );
TShowTrack* pST = m_aTracks[m_iSelTrack];
TMidiTrack* pMT = g_aMidiTracks[pST->index];
TSwitchProgForm *sPf = new TSwitchProgForm( NULL, pMT->bank, pMT->prog, pMT->chno );
BYTE data[100000];
int len = 100000;
int iSBar = Sender==NULL ? -1 : m_iSelBarStart,
iEBar = Sender==NULL ? -1 : m_iSelBarEnd;
GetMidiTrackData( len, data, pST->index, iSBar, iEBar, &sPf->m_iStartBar, &sPf->m_lenBar );
f_MM_LoadDemo( data, len );
if( sPf->ShowModal() == mrOk ){
BYTE iBank = sPf->m_iFont==g_idFont ? 0xFF : sPf->m_iFont;
char iProg = sPf->m_iProg,
iChno = sPf->m_iChno;
if( iBank!=pMT->bank || iProg!=pMT->prog || iChno!=pMT->chno ){
((TUseStylePanel*)m_pStylePanel)->ChangeFont( iSBar, iEBar,
pST->index, iBank, iProg, iChno, ST_MIDI );
}
}
delete sPf;
f_MM_LoadDemo( NULL, 0 );
}
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::DoTrackSwitchFontProg(TObject* Sender)
{
DoSwitchFontProg( NULL );
}
//---------------------------------------------------------------------------
void __fastcall TContentPanel::OnMidiSwitch(TMessage &msg)
{
if( msg.WParam==0 )
DoSwitchFontProg( NULL );
else if( msg.WParam==1 )
DoSwitchTexture( NULL );
}
//---------------------------------------------------------------------------
void TContentPanel::ChangeMidiTrack( int iMT, int iSBar, int iEBar )
{
Parent->Perform( UM_STOP, STOP_CONTENT | STOP_USESTYLE, 0 );
TMidiTrack* pMT = iMT<0 ? NULL : g_aMidiTracks[iMT];
TStageList lstStages;
char progOri(-1), chanOri(-1), segNoOri(-1);
TPROSTYLE *pStyleOri = NULL;
bool bOriSet = iMT>=0,
bHasDrum = bOriSet && !pMT->IsDrum();
if( pMT ){
progOri = pMT->prog;
if( pMT->IsDrum() )
chanOri = 9;
}
int iEndBar = iEBar<0 ? g_Opus.BarCount()-1 : m_iSelBarEnd,
iStartBar = iSBar<0 ? 0 : m_iSelBarStart,
// lenBar = iEndBar - iStartBar + 1,
iDropMask = 0;
int iFBar, iStage = FindStage( iStartBar, &iFBar ),
iLBar = iFBar;
while( iStage<g_Opus.StageCount() ){
TOpusStage* pStage = g_lstOpusStages[iStage];
TStage* pDemoStage = new TStage;
lstStages.push_back( pDemoStage );
pDemoStage->iSegType = pStage->iSegType;
pDemoStage->iSegKey = pStage->iSegKey;
pDemoStage->nBarNum = pStage->aBars.size();
if( pStage->iSegType<=SEGTYPE_FILL ){
pDemoStage->aChords = new TBarChords[pDemoStage->nBarNum];
for( int j=0; j<pDemoStage->nBarNum; j++ ){
memcpy( &pDemoStage->aChords[j], &pStage->aBars[j]->aChords,
sizeof(TBarChords) );
}
if( bOriSet ){
for( int i=0; i<pStage->aTracks.size(); i++ ){
TTrack* pTrack = pStage->aTracks[i];
if( pTrack->iFile==pMT->file && pTrack->iChanSpec==pMT->chno ){
char st = pDemoStage->iSegType,
sn = pTrack->iSegNo,
cn = pTrack->iChanNo,
pg = pTrack->iProgOrig;// -1;
TPROSTYLE* pStyTemp = GetStyleInfo( pTrack->iStyleLoc, pTrack->iStyleId );
/* if( pTrack->iStyleLoc==0 ){
for( int t=0; t<16; t++ ){
if( pStyTemp->pOrigin->detail.tracks[st][sn][t].no==cn ){
pg = pStyTemp->pOrigin->detail.tracks[st][sn][t].prog;
break;
}
}
}
else if( pTrack->iStyleLoc!=1 ){
for( int t=0; t<16; t++ ){
if( pStyTemp->pLocal->trkRef[st][sn][t].chan==cn ){
pg = pStyTemp->pLocal->trkRef[st][sn][t].prog;
break;
}
}
}
*/
if( !pStyleOri ){
pStyleOri = pStyTemp;
segNoOri = sn;
chanOri = cn;
progOri = pg;
}
else{
if( pStyleOri!=pStyTemp || segNoOri!=sn || chanOri!=cn || progOri!=pg ){
pStyleOri = NULL;
segNoOri = -1;
progOri = -1;
if( chanOri!=9 )
chanOri = -1;
bOriSet = false;
}
}
break;
}
}
}
else if( !bHasDrum && !pStage->aTracks.empty() ){
if( pStage->aTracks[0]->iChanNo==9 )
bHasDrum = true;
}
DWORD iT = ( 1 << pStage->iSegType );
if( !(iDropMask & iT ) )
iDropMask |= iT;
}
iLBar += pStage->aBars.size();
if( iLBar>iEndBar ){
pDemoStage->nBarNum -= iLBar - iEndBar - 1;
break;
}
else{
iStage++;
}
}
if( !bHasDrum )
iDropMask |= 0x80;
TSwitchTextureForm *pProgPar = new TSwitchTextureForm(NULL, iDropMask, progOri,
pMT ? pMT->bank : -1, pMT ? pMT->prog : -1,
pStyleOri, chanOri, segNoOri, &lstStages, iStartBar-iFBar);
if( pProgPar->ShowModal() == mrOk ){
TTrack subTrk;
subTrk.iStyleLoc = pProgPar->m_pSetStyle->idLoc;
subTrk.iStyleId = pProgPar->m_pSetStyle->idStyle;
subTrk.iSegNo = pProgPar->m_cSetSegNo;
subTrk.iChanNo = pProgPar->m_cSetchan;
subTrk.nVol = pProgPar->m_cSetVol;
subTrk.nVolOrig = pProgPar->m_cSetVolOri;
subTrk.iProgOrig = pProgPar->m_cSetProgOri;
if( !pProgPar->m_bSetCur || pMT && pMT->bank==0xFF
&& pProgPar->m_cSetProg==pMT->prog ){
subTrk.iFile = pMT->file;
subTrk.iBank = pMT->bank;
subTrk.iChanSpec = pMT->chno;
subTrk.iProg = pMT->prog;
}
else{
subTrk.iFile = 0xFF;
subTrk.iBank = 0xFF;
subTrk.iChanSpec =subTrk.iChanNo;
subTrk.iProg = pProgPar->m_cSetProg;
}
int iSegType = pProgPar->m_cSetSegType,
op = m_bVertical ? SEGTYPE_TRACK : ST_MIDI;
((TUseStylePanel*)m_pStylePanel)->ChangeTexture( iSBar, iEBar, iSegType, iMT, &subTrk, op );
}
delete pProgPar;
for( int i=0; i<lstStages.size(); i++ ){
delete lstStages[i];
}
}
//---------------------------------------------------------------------------
void TContentPanel::Undo( bool bUndo )
{
if( m_bDraging )
return;
TUndoLite* pLite = bUndo ? g_Undo.Undo() : g_Undo.Redo();
int iType = pLite->iType;
if( iType<=UNDO_TRKAUD_DELALL )
Parent->Perform( UM_STOP, STOP_CONTENT | STOP_USESTYLE, 0 );
if( iType==UNDO_KEY_MELODY ){
TOpusStageList* lstStages = (TOpusStageList*)(bUndo ? pLite->pBefore : pLite->pAfter);
int iKey = bUndo ? pLite->iBegin : pLite->iEnd;
if( !lstStages ){
ChangeBarsKey( 0, g_Opus.BarCount()-1, iKey, NULL );
}
else{
g_Theme.Set( *lstStages );
g_iMelodyKey = iKey;
((TUseStylePanel*)m_pStylePanel)->InitOpus( g_pPreStyle, g_iPreStage );
}
Parent->Perform( UM_CHANGEKEY, 0, 0 );
}
else if( iType==UNDO_KEY_BARS ){
if( VIEW_STYLE!=m_iMode )
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_STYLE, 0 );
int iKey = bUndo ? -1 : (int)pLite->pAfter,
*aKey = bUndo ? (int*)pLite->pBefore : NULL;
ChangeBarsKey( pLite->iBegin, pLite->iEnd, iKey, aKey );
SelectBars( pLite->iBegin, pLite->iEnd );
}
else if(iType==UNDO_CHORD ){
if( VIEW_CHORD!=m_iMode ){
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_CHORD, 0 );
}
BYTE* aParam = (BYTE*)( bUndo ? pLite->pBefore : pLite->pAfter );
int iBarStart = HIWORD(pLite->iBegin),
iCellStart = LOWORD(pLite->iBegin),
iBarEnd = HIWORD(pLite->iEnd),
iCellEnd = LOWORD(pLite->iEnd),
nCellNum = (iBarEnd - iBarStart - 1) * g_nChordNumPerBar
+ (g_nChordNumPerBar - iCellStart) + (iCellEnd + 1),
*keys = new int[nCellNum],
*types = new int[nCellNum];
for( int i=0; i<nCellNum; i++ ){
keys[i] = aParam[i]>>4;
types[i] = aParam[i] & 0x0F;
}
SelectCells( iBarStart, iCellStart, iBarEnd, iCellEnd );
ChordPaste( keys, types, nCellNum, false );
int iKey = -1, iType = -1, iBarKey = -1;
bool bEnable = false;
if( m_iSelBarStart>=0 ){
GetSelectChord( iBarKey, iKey, iType );
bEnable = iKey!=-1;
}
((TChordPanel*)m_pChordPanel)->EnableChordModify( bEnable, iBarKey, iKey, iType );
}
else if( iType>=UNDO_TRKAUD_ADD && iType<=UNDO_TRKAUD_HIDEALL
|| iType>=UNDO_TRKMID_SHOW && iType<=UNDO_TRKMID_HIDEALL ){
short iShowTrk = -1,
iTrkType = ST_AUDIO;
bool bSolo = false;
bool bInit = true;
if( iType<=UNDO_TRKAUD_DELALL ){
f_MM_Undo( bUndo );
short iTrk = pLite->iCode;
if( iType==UNDO_TRKAUD_ADD ){
if( bUndo ){
if( g_aAudioTracks[iTrk]->IsSolo() )
bSolo = true;
DeleteAudioTrack( iTrk, false );
if( iTrk<g_iSelAudio )
g_iSelAudio--;
else if( iTrk==g_iSelAudio ){
SelectTrack( -1, -1, -1 );
}
}
else{
if( g_iViewMode!=VIEW_TRACK )
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );
if( g_iPreStage==0 ){
DuplicateRawBars();
PostMessage( Parent->Handle, UM_STAGECHANGED, 3, 0 );
}
NewAudioTrack( g_Opus.BarCount(), false );
iShowTrk = g_aAudioTracks.size()-1;
}
}
else if( iType<=UNDO_TRKAUD_DELALL ){
TAudioTrackList* aTracks = (TAudioTrackList*)pLite->pBefore;
int num = aTracks->size();
bInit = false;
int iTrack = iTrk<0 ? 1 : iTrk;
iShowTrk = bUndo ? iTrk : -1;
if( bUndo ){
for( int i=0; i<num; i++ ){
TAudioTrack* pTrack = DuplicateAudioTrack( (*aTracks)[i] );
if( iTrack==0 ){
delete g_aAudioTracks[0];
g_aAudioTracks.clear();
}
g_aAudioTracks.insert( g_aAudioTracks.begin()+iTrack, pTrack );
AudioEffectsSet( iTrack );
if( pTrack->IsSolo() )
bSolo = true;
if( !pTrack->IsHide() )
bInit = true;
iTrack++;
}
}
else{
for( int i=0; i<num; i++ ){
if( g_aAudioTracks[iTrack]->IsSolo() )
bSolo = true;
if( !g_aAudioTracks[iTrack]->IsHide() )
bInit = true;
DeleteAudioTrack( iTrack, false );
}
if( iTrk<0 || iTrk==g_iSelAudio )
SelectTrack( -1, -1 ,-1 );
else if( iTrk<g_iSelAudio )
g_iSelAudio--;
}
}
}
else{
iTrkType = ( iType>=UNDO_TRKAUD_SHOW && iType<=UNDO_TRKAUD_HIDEALL ) ? ST_AUDIO : ST_MIDI;
vector<BYTE>* arrIndex = (vector<BYTE>*)pLite->pBefore;
for( int i=0; i<arrIndex->size(); i++ ){
int iTrk = (*arrIndex)[i];
TBaseTrack* pBT = NULL;
if( iTrkType==ST_AUDIO )
pBT = g_aAudioTracks[iTrk];
else
pBT = g_aMidiTracks[iTrk];
pBT->Hide( bUndo && ( iType==UNDO_TRKAUD_SHOW || iType==UNDO_TRKAUD_SHOWALL
|| iType==UNDO_TRKMID_SHOW || iType==UNDO_TRKMID_SHOWALL )
|| !bUndo && ( iType==UNDO_TRKAUD_HIDE || iType==UNDO_TRKAUD_HIDEALL
|| iType==UNDO_TRKMID_HIDE || iType==UNDO_TRKMID_HIDEALL ));
if( arrIndex->size()==1 && !pBT->IsHide() )
iShowTrk = iTrk;
}
}
if( bInit )
InitialVars();
if( bSolo )
SetTrackParams();
if( iShowTrk>=0 ){
int id = GetShowTrackId( iTrkType, iShowTrk ) - 1;
SelectTrack( id, -1, -1 );
}
else{
SelectTrack( -1, -1, -1 );
}
Application->MainForm->Perform( UM_ENABLERECORD, 0, 0 );
}
else if( iType>=UNDO_AUDIO_ERASE && iType<=UNDO_AUDIO_FX ){
int iTrack = pLite->iCode;
int iBarStart = HIWORD( pLite->iBegin ),
iPointStart = LOWORD( pLite->iBegin ),
iBarEnd = HIWORD( pLite->iEnd ),
iPointEnd = LOWORD( pLite->iEnd ),
iSelAudio = iTrack,
iSelBarStart = iBarStart,
iSelPointStart = iPointStart,
iSelBarEnd = iBarEnd,
iSelPointEnd = iPointEnd;
if( g_aAudioTracks[iTrack]->IsHide() ){
g_aAudioTracks[iTrack]->Hide(false);
InitialVars();
}
if( VIEW_TRACK!=m_iMode ){
Application->MainForm->Perform( UM_SETVIEWMODE, VIEW_TRACK, 0 );
}
else{
SelectCopyPos( -1, -1, -1, -1 );
}
f_MM_Undo( bUndo );
if( bUndo ){
DWORD* aWave = (DWORD*)pLite->pBefore;
CopyWave( iTrack, iBarStart, iPointStart, iBarEnd, iPointEnd, &aWave );
if( iType==UNDO_AUDIO_MOVE ){
int iDelTrack = pLite->iExt1;
int iDelBarStart = HIWORD( pLite->iExt2 ),
iDelPointStart = LOWORD( pLite->iExt2 ),
iDelBarEnd = HIWORD( pLite->iExt3 ),
iDelPointEnd = LOWORD( pLite->iExt3 ),
iDelBarBreak = iDelBarEnd,
iDelPointBreak = iDelPointEnd;
if( g_aAudioTracks[iDelTrack]->IsHide() ){
g_aAudioTracks[iDelTrack]->Hide(false);
InitialVars();
}
if( pLite->pExt1 ){
int len = ( iBarEnd * POINTS_PER_BAR + iPointEnd )
- ( iBarStart * POINTS_PER_BAR + iPointStart ),
nPointsBreak = iDelBarStart * POINTS_PER_BAR + iDelPointStart + len;
iDelBarBreak = nPointsBreak / POINTS_PER_BAR;
iDelPointBreak = nPointsBreak % POINTS_PER_BAR;
aWave = (DWORD*)pLite->pExt1;
CopyWave( iDelTrack, iDelBarBreak, iDelPointBreak,
iDelBarEnd, iDelPointEnd, &aWave );
}
aWave = (DWORD*)pLite->pAfter;
CopyWave( iDelTrack, iDelBarStart, iDelPointStart,
iDelBarBreak, iDelPointBreak, &aWave );
iSelAudio = iDelTrack;
iSelBarStart = iDelBarStart;
iSelPointStart = iDelPointStart;
iSelBarEnd = iDelBarEnd;
iSelPointEnd = iDelPointEnd;
InvalidateBars( iBarStart, iBarEnd, BAR_TRACK | GetShowTrackId(ST_AUDIO,iTrack) );
}
}
else{
int iDelBarStart, iDelPointStart, iDelBarEnd, iDelPointEnd,
iDelTrack = -1;
if( iType==UNDO_AUDIO_ERASE ){
iDelTrack = iTrack;
iDelBarStart = iBarStart;
iDelPointStart = iPointStart;
iDelBarEnd = iBarEnd;
iDelPointEnd = iPointEnd;
}
else if( iType==UNDO_AUDIO_MOVE ){
iDelTrack = pLite->iExt1;
iDelBarStart = HIWORD( pLite->iExt2 );
iDelPointStart = LOWORD( pLite->iExt2 );
iDelBarEnd = HIWORD( pLite->iExt3 );
iDelPointEnd = LOWORD( pLite->iExt3 );
}
if( iDelTrack>0 ){
double dblStart = iDelBarStart + (double)iDelPointStart / POINTS_PER_BAR,
dblEnd = iDelBarEnd + (double)iDelPointEnd / POINTS_PER_BAR;
MoveAudio( iDelTrack, dblStart, dblEnd, -1, -1, MODE_ERASE );
}
if( iType>UNDO_AUDIO_ERASE ){
DWORD* aWave = (DWORD*)pLite->pAfter;
CopyWave( iTrack, iBarStart, iPointStart, iBarEnd, iPointEnd, &aWave );
}
}
int iSelTrack = GetShowTrackId( ST_AUDIO, iSelAudio );
if( iSelTrack>0 )
SelectTrack( iSelTrack-1, iSelBarStart, iSelPointStart );
//SelectTrack( iSelAudio, iSelBarStart, iSelPointStart );
SelectRange( iSelBarStart, iSelPointStart, iSelBarEnd, iSelPointEnd, true );
// InvalidateBars( iSelBarStart, iSelBarEnd, BAR_TRACK | GetShowTrackId(ST_AUDIO,iSelAudio) );
}
}
//---------------------------------------------------------------------------