//---------------------------------------------------------------------------
#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) );
	}
}
//---------------------------------------------------------------------------

