summaryrefslogtreecommitdiffstats
path: root/src/PianoRollKeyTimeView.cpp
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-09-15 21:57:55 -0700
committerKaz Kylheku <kaz@kylheku.com>2013-09-15 21:57:55 -0700
commit672e606b6d857e370ac75c076a1b2982e5bccd67 (patch)
tree46dcaace1126e2b2c2f785e42f562fe5c7718484 /src/PianoRollKeyTimeView.cpp
downloadsekaiju-672e606b6d857e370ac75c076a1b2982e5bccd67.tar.gz
sekaiju-672e606b6d857e370ac75c076a1b2982e5bccd67.tar.bz2
sekaiju-672e606b6d857e370ac75c076a1b2982e5bccd67.zip
Converted Sekaiju 3.6 to Visual Studio 2008.
Diffstat (limited to 'src/PianoRollKeyTimeView.cpp')
-rw-r--r--src/PianoRollKeyTimeView.cpp2181
1 files changed, 2181 insertions, 0 deletions
diff --git a/src/PianoRollKeyTimeView.cpp b/src/PianoRollKeyTimeView.cpp
new file mode 100644
index 0000000..28a06fe
--- /dev/null
+++ b/src/PianoRollKeyTimeView.cpp
@@ -0,0 +1,2181 @@
+//******************************************************************************
+// MIDIシーケンサーソフト『世界樹』
+// ピアノロールキータイムビュークラス
+// (C)2002-2013 おーぷんMIDIぷろじぇくと/くず
+//******************************************************************************
+
+/* This library is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU Lesser General Public */
+/* License as published by the Free Software Foundation; either */
+/* version 2.1 of the License, or (at your option) any later version. */
+
+/* This library is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
+/* Lesser General Public License for more details. */
+
+/* You should have received a copy of the GNU Lesser General Public */
+/* License along with this library; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "winver.h"
+#include <afxwin.h>
+#include <afxext.h>
+#include <afxcmn.h>
+#include <afxmt.h>
+#include "../../MIDIIO/MIDIIO.h"
+#include "../../MIDIData/MIDIData.h"
+#include "../../MIDIClock/MIDIClock.h"
+#include "../../MIDIStatus/MIDIStatus.h"
+#include "../../MIDIInstrument/MIDIInstrument.h"
+#include "mousewheel.h"
+#include "ColorfulComboBox.h"
+#include "ColorfulCheckListBox.h"
+#include "HistoryRecord.h"
+#include "HistoryUnit.h"
+#include "SekaijuApp.h"
+#include "SekaijuDoc.h"
+#include "SekaijuView.h"
+#include "SekaijuToolBar.h"
+#include "SekaijuStatusBar.h"
+#include "ChildFrame.h"
+#include "PianoRollFrame.h"
+#include "PianoRollKeyTimeView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+IMPLEMENT_DYNCREATE (CPianoRollKeyTimeView, CSekaijuView)
+
+// メッセージマップ
+BEGIN_MESSAGE_MAP (CPianoRollKeyTimeView, CSekaijuView)
+ ON_WM_CREATE ()
+ ON_WM_DESTROY ()
+ ON_WM_TIMER ()
+ ON_WM_KEYDOWN ()
+ ON_WM_KEYUP ()
+ ON_WM_LBUTTONDOWN ()
+ ON_WM_RBUTTONDOWN ()
+ ON_WM_LBUTTONUP ()
+ ON_WM_RBUTTONUP ()
+ ON_WM_MOUSEMOVE ()
+ ON_WM_MOUSEWHEEL40 ()
+END_MESSAGE_MAP()
+
+//------------------------------------------------------------------------------
+// 構築と破壊
+//------------------------------------------------------------------------------
+
+// コンストラクタ
+CPianoRollKeyTimeView::CPianoRollKeyTimeView () {
+ m_lCurTime = m_lOldTime = 0;
+ m_lOldY1 = m_lOldY2 = 0;
+ m_bOldDraw = TRUE;
+ m_pTempEvent = NULL;
+ m_lTempMode = 0;
+ m_pLastEvent = NULL;
+}
+
+// デストラクタ
+CPianoRollKeyTimeView::~CPianoRollKeyTimeView () {
+}
+
+//------------------------------------------------------------------------------
+// オペレーション
+//------------------------------------------------------------------------------
+
+// ノート矩形を取得する
+CRect CPianoRollKeyTimeView::GetNoteRect (MIDIEvent* pNoteOnEvent) {
+ ASSERT (pNoteOnEvent);
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ if (!MIDIEvent_IsNoteOn (pNoteOnEvent)) {
+ return CRect (0,0,0,0);
+ }
+ long lTime = MIDIEvent_GetTime (pNoteOnEvent);
+ long lKey = MIDIEvent_GetKey (pNoteOnEvent);
+ long lDuration = MIDIEvent_GetDuration (pNoteOnEvent);
+ long x = pPianoRollFrame->TimetoX (lTime);
+ long w = pPianoRollFrame->TimetoX (lDuration);
+ long y = pPianoRollFrame->KeytoY (lKey);
+ long h = pPianoRollFrame->GetKeyZoom ();
+ return CRect (x, y - h, x + w, y);
+}
+
+
+
+
+// 旧位置の縦線消去
+void CPianoRollKeyTimeView::EraseOldLine (CDC* pDC) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CRect rcClient;
+ GetClientRect (&rcClient);
+ rcClient += CSize (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ if (rcClient.left <= m_lOldX && m_lOldX <= rcClient.right && m_bOldDraw == TRUE) {
+ pDC->SetROP2 (R2_NOT);
+ pDC->MoveTo (m_lOldX, m_lOldY1);
+ pDC->LineTo (m_lOldX, m_lOldY2);
+ }
+}
+
+// 現在位置の縦線描画
+void CPianoRollKeyTimeView::DrawCurLine (CDC* pDC) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CRect rcClient;
+ GetClientRect (&rcClient);
+ rcClient += CSize (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ long x = pPianoRollFrame->TimetoX (m_lCurTime);
+ if (rcClient.left <= x && x <= rcClient.right) {
+ pDC->SetROP2 (R2_NOT);
+ pDC->MoveTo (x, rcClient.top);
+ pDC->LineTo (x, rcClient.bottom);
+ m_bOldDraw = TRUE;
+ m_lOldTime = m_lCurTime;
+ m_lOldX = x;
+ m_lOldY1 = rcClient.top;
+ m_lOldY2 = rcClient.bottom;
+ }
+ else {
+ m_bOldDraw = FALSE;
+ }
+}
+
+// ポップアップメニューの表示
+BOOL CPianoRollKeyTimeView::ShowPopupMenu (CPoint ptMenu) {
+
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ ASSERT (m_lTempMode == 0x1001);
+ // ノートイベント上でポップアップメニューを表示した場合
+ if (m_pTempEvent) {
+ pSekaijuDoc->m_lTempTime = MIDIEvent_GetTime (m_pTempEvent);
+ pSekaijuDoc->m_pTempTrack = MIDIEvent_GetParent (m_pTempEvent);
+ pSekaijuDoc->m_pTempEvent = m_pTempEvent;
+ }
+ // 何もないところでポップアップメニューを表示した場合
+ else {
+ pSekaijuDoc->m_lTempTime = pSekaijuDoc->m_lNewTime;
+ pSekaijuDoc->m_pTempTrack = NULL; //pSekaijuDoc->m_pTempTrack; // 20100429修正
+ pSekaijuDoc->m_pTempEvent = NULL;
+ }
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+
+ CMenu theMenu;
+ VERIFY (theMenu.LoadMenu (IDR_POPUPMENU11));
+ CMenu* pContextMenu = theMenu.GetSubMenu (0);
+ pContextMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
+ ptMenu.x, ptMenu.y, pPianoRollFrame);
+
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ m_lTempMode = 0x0000;
+
+ return TRUE;
+}
+
+
+
+//------------------------------------------------------------------------------
+// オーバーライド
+//------------------------------------------------------------------------------
+
+// 原点の移動をオーバーライド
+void CPianoRollKeyTimeView::OnPrepareDC (CDC* pDC, CPrintInfo* pInfo) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ pDC->SetWindowOrg (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+}
+
+// 描画
+void CPianoRollKeyTimeView::OnDraw (CDC* pDC) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CRect rcClient;
+ GetClientRect (&rcClient);
+ rcClient += CSize (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ CPen penMeasure (PS_SOLID, 1, pSekaijuApp->m_theColorOption.m_lVertColor[1]);
+ CPen penBeat (PS_SOLID, 1, pSekaijuApp->m_theColorOption.m_lVertColor[0]);
+ CPen penKey (PS_SOLID, 1, pSekaijuApp->m_theColorOption.m_lHorzColor[0]);
+ CPen penOctave (PS_SOLID, 1, pSekaijuApp->m_theColorOption.m_lHorzColor[1]);
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ long x, y, lTime;
+ long lVisibleLeftTime = pPianoRollFrame->GetVisibleLeftTime ();
+ long lVisibleRightTime = pPianoRollFrame->GetVisibleRightTime ();
+ long lVisibleTopKey = pPianoRollFrame->GetVisibleTopKey ();
+ long lVisibleBottomKey = pPianoRollFrame->GetVisibleBottomKey ();
+ long lLeftMeasure, lLeftBeat, lLeftTick;
+ long lRightMeasure, lRightBeat, lRightTick;
+ long lnn, ldd, lcc, lbb;
+ long lUnitTick;
+ long temp;
+
+ // 横線の描画
+ CPen* pOldPen = pDC->SelectObject (&penKey);
+ long lKeyZoom = pPianoRollFrame->GetKeyZoom ();
+ long i, j;
+ for (i = lVisibleBottomKey; i <= lVisibleTopKey + 1; i++) {
+ y = pPianoRollFrame->KeytoY (i);
+ // 黒鍵部の塗り潰し
+ temp = i % 12;
+ if (temp == 1 || temp == 3 || temp == 6 || temp == 8 || temp == 10) {
+ pDC->FillSolidRect (rcClient.left, y, rcClient.Width (), -lKeyZoom,
+ pSekaijuApp->m_theColorOption.m_lBackColor[1]);
+ }
+ // 白鍵部の塗り潰し
+ else {
+ pDC->FillSolidRect (rcClient.left, y, rcClient.Width (), -lKeyZoom,
+ pSekaijuApp->m_theColorOption.m_lBackColor[0]);
+ }
+ // 横線描画
+ pDC->MoveTo (rcClient.left, y);
+ pDC->LineTo (rcClient.right, y);
+ }
+
+ // 縦線の描画
+ long lTimeMode, lTimeResolution;
+ MIDIData_GetTimeBase (pMIDIData, &lTimeMode, &lTimeResolution);
+ if (lTimeMode == MIDIDATA_TPQNBASE) {
+ MIDIData_BreakTime (pMIDIData, lVisibleLeftTime, &lLeftMeasure, &lLeftBeat, &lLeftTick);
+ MIDIData_BreakTime (pMIDIData, lVisibleRightTime, &lRightMeasure, &lRightBeat, &lRightTick);
+ for (i = lLeftMeasure; i <= lRightMeasure; i++) {
+ // 小節線の描画
+ MIDIData_MakeTimeEx (pMIDIData, i, 0, 0, &lTime, &lnn, &ldd, &lcc, &lbb);
+ x = pPianoRollFrame->TimetoX (lTime);
+ pDC->SelectObject (&penMeasure);
+ pDC->MoveTo (x, rcClient.top);
+ pDC->LineTo (x, rcClient.bottom);
+ // 拍線の描画
+ pDC->SelectObject (&penBeat);
+ lUnitTick = lTimeResolution * 4 / (1 << ldd);
+ for (long j = 1; j < lnn; j++) {
+ x = pPianoRollFrame->TimetoX (lTime + j * lUnitTick);
+ pDC->MoveTo (x, rcClient.top);
+ pDC->LineTo (x, rcClient.bottom);
+ }
+ }
+ }
+ else {
+ long lLeftFrameNumber = lVisibleLeftTime / lTimeResolution;
+ long lRightFrameNumber = lVisibleRightTime / lTimeResolution;
+ for (i = lLeftFrameNumber; i <= lRightFrameNumber; i++) {
+ // フレーム境界線の描画
+ lTime = i * lTimeResolution;
+ x = pPianoRollFrame->TimetoX (lTime);
+ pDC->SelectObject (&penMeasure);
+ pDC->MoveTo (x, rcClient.top);
+ pDC->LineTo (x, rcClient.bottom);
+ }
+ pDC->SelectObject (pOldPen);
+ }
+
+ // オクターブ線の描画
+ pDC->SelectObject (&penOctave);
+ for (j = lVisibleBottomKey; j <= lVisibleTopKey; j++) {
+ if (j % 12 == 0) {
+ y = pPianoRollFrame->KeytoY (j);
+ pDC->MoveTo (rcClient.left, y);
+ pDC->LineTo (rcClient.right, y);
+ }
+ }
+
+ // ピアノロールバーの描画
+ long w;
+ CPen penBar (PS_SOLID, 1, RGB (0, 0, 0));
+ pDC->SelectObject (&penBar);
+ MIDITrack* pMIDITrack = NULL;
+ MIDIEvent* pMIDIEvent = NULL;
+ i = 0;
+ forEachTrack (pMIDIData, pMIDITrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ long lColor = MIDITrack_GetForeColor (pMIDITrack);
+ forEachEvent (pMIDITrack, pMIDIEvent) {
+ if (MIDIEvent_IsNoteOn (pMIDIEvent)) {
+ if (pMIDIEvent->m_lTime < lVisibleRightTime) {
+ x = pPianoRollFrame->TimetoX (MIDIEvent_GetTime (pMIDIEvent));
+ w = pPianoRollFrame->TimetoX (MIDIEvent_GetDuration (pMIDIEvent));
+ y = pPianoRollFrame->KeytoY (MIDIEvent_GetKey (pMIDIEvent));
+ if (pSekaijuDoc->IsEventSelected (pMIDIEvent)) {
+ pDC->FillSolidRect (CRect (x, y, x + w, y - lKeyZoom), RGB (0, 0, 0));
+ }
+ else {
+ pDC->FillSolidRect (CRect (x, y, x + w, y - lKeyZoom), lColor);
+ }
+ pDC->Draw3dRect (x, y - lKeyZoom, w, lKeyZoom ,RGB (255,255,255), RGB (0, 0, 0));
+ }
+ }
+ }
+ }
+ i++;
+ }
+
+ pDC->SelectObject (pOldPen);
+
+ // 現在位置の描画
+ DrawCurLine (pDC);
+
+ // マウストラッカーが必要な場合、マウストラッカーの描画
+ if (GetCapture () == this) {
+ if (m_lTempMode == 0x0401) {
+ pDC->SetROP2 (R2_NOT);
+ pDC->MoveTo (m_ptMouseDown.x, m_ptMouseDown.y);
+ pDC->LineTo (m_ptMouseMove.x, m_ptMouseDown.y);
+ pDC->MoveTo (m_ptMouseDown.x, m_ptMouseMove.y);
+ pDC->LineTo (m_ptMouseMove.x, m_ptMouseMove.y);
+ pDC->MoveTo (m_ptMouseDown.x, m_ptMouseDown.y);
+ pDC->LineTo (m_ptMouseDown.x, m_ptMouseMove.y);
+ pDC->MoveTo (m_ptMouseMove.x, m_ptMouseDown.y);
+ pDC->LineTo (m_ptMouseMove.x, m_ptMouseMove.y);
+ pDC->SetROP2 (R2_COPYPEN);
+ }
+ // ライントラッカーが必要な場合、ライントラッカーの描画
+ else if (m_lTempMode == 0x0201) {
+ pDC->SetROP2 (R2_NOT);
+ pDC->MoveTo (m_ptMouseDown.x, m_ptMouseDown.y);
+ pDC->LineTo (m_ptMouseMove.x, m_ptMouseMove.y);
+ pDC->SetROP2 (R2_COPYPEN);
+ }
+ }
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ Sleep (0);
+}
+
+// ビューの更新
+void CPianoRollKeyTimeView::OnUpdate (CView* pSender, LPARAM lHint, CObject* pHint) {
+ // クリティカルセクションはロックされているものとする。
+ if ((lHint & SEKAIJUDOC_PLAYSTARTED) ||
+ (lHint & SEKAIJUDOC_RECORDSTARTED) ||
+ (lHint & SEKAIJUDOC_POSITIONCHANGED)) {
+ PostMessage (WM_TIMER, 0x11, NULL);
+ }
+ CSekaijuView::OnUpdate (pSender, lHint, pHint);
+}
+
+// ウィンドウクラスの変更
+BOOL CPianoRollKeyTimeView::PreCreateWindow (CREATESTRUCT& cs) {
+ CView::PreCreateWindow (cs);
+ cs.lpszClass = AfxRegisterWndClass
+ (CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS,
+ NULL, // デフォルトカーソル無し
+ (HBRUSH)::GetStockObject (WHITE_BRUSH), // デフォルト背景ブラシ
+ NULL); // デフォルトアイコン無し
+ return TRUE;
+}
+
+
+
+
+//------------------------------------------------------------------------------
+// メッセージマップ
+//------------------------------------------------------------------------------
+
+// ウィンドウ生成時
+int CPianoRollKeyTimeView::OnCreate (LPCREATESTRUCT lpCreateStruct) {
+ SetTimer (0x11, 55, NULL);
+ return CSekaijuView::OnCreate (lpCreateStruct);
+}
+
+// ウィンドウ破棄時
+void CPianoRollKeyTimeView::OnDestroy () {
+ KillTimer (0x11);
+ CSekaijuView::OnDestroy ();
+}
+
+// タイマー呼び出し時
+void CPianoRollKeyTimeView::OnTimer (UINT nIDEvent) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+
+ // 演奏・記録中のカレントバー移動処理
+ if (nIDEvent == 0x11) {
+ if (pSekaijuDoc->m_pMIDIData && pSekaijuDoc->m_pMIDIClock) {
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+
+ CDC* pDC = GetDC ();
+ OnPrepareDC (pDC, NULL);
+ CRect rcClient;
+ GetClientRect (&rcClient);
+ rcClient += CSize (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ m_lCurTime = MIDIClock_GetTickCount (GetDocument ()->m_pMIDIClock);
+ // 前回の時刻と現在の時刻が違っている場合のみ
+ if (m_lOldTime != m_lCurTime) {
+ EraseOldLine (pDC);
+ DrawCurLine (pDC);
+ }
+ // ページの更新およびオートスクロール(手動スクロール時はしない)
+ if (pPianoRollFrame->m_bAutoPageUpdate == TRUE) {
+ long lTimeMode, lTimeResolution;
+ MIDIData_GetTimeBase (pMIDIData, &lTimeMode, &lTimeResolution);
+ if (lTimeMode == MIDIDATA_TPQNBASE) {
+ // 現在位置が右側へはみ出した場合
+ long lRightMeasure; long lRightBeat; long lRightTick; long lTempRightTime;
+ MIDIData_BreakTime (pMIDIData, pPianoRollFrame->GetVisibleRightTime (),
+ &lRightMeasure, &lRightBeat, &lRightTick);
+ MIDIData_MakeTime (pMIDIData, lRightMeasure, 0, 0, &lTempRightTime);
+ if (m_lCurTime >= lTempRightTime) {
+ long lNewMeasure; long lNewBeat; long lNewTick;
+ MIDIData_BreakTime (pMIDIData, m_lCurTime, &lNewMeasure, &lNewBeat, &lNewTick);
+ MIDIData_MakeTime (pMIDIData, lNewMeasure, 0, 0, &lTempRightTime);
+ int x = pPianoRollFrame->TimetoX (lTempRightTime);
+ pPianoRollFrame->SetTimeScrollPos (x);
+ }
+ // 現在位置が左側へはみ出した場合
+ long lLeftMeasure; long lLeftBeat; long lLeftTick; long lTempLeftTime;
+ MIDIData_BreakTime (pMIDIData, pPianoRollFrame->GetVisibleLeftTime (),
+ &lLeftMeasure, &lLeftBeat, &lLeftTick);
+ MIDIData_MakeTime (pMIDIData, lLeftMeasure, 0, 0, &lTempLeftTime);
+ if (m_lCurTime < lTempLeftTime) {
+ long lNewMeasure; long lNewBeat; long lNewTick;
+ MIDIData_BreakTime (GetDocument()->m_pMIDIData, m_lCurTime, &lNewMeasure, &lNewBeat, &lNewTick);
+ MIDIData_MakeTime (GetDocument()->m_pMIDIData, lNewMeasure, 0, 0, &lTempLeftTime);
+ int x = pPianoRollFrame->TimetoX (lTempLeftTime);
+ pPianoRollFrame->SetTimeScrollPos (x);
+ }
+ }
+ else {
+ // 現在位置が右側へはみ出した場合
+ long lRightFrameNumber = pPianoRollFrame->GetVisibleRightTime () / lTimeResolution;
+ long lTempRightTime = lRightFrameNumber * lTimeResolution;
+ if (m_lCurTime >= lTempRightTime) {
+ lTempRightTime = (m_lCurTime / lTimeResolution) * lTimeResolution;
+ long x = pPianoRollFrame->TimetoX (lTempRightTime);
+ pPianoRollFrame->SetTimeScrollPos (x);
+ }
+ // 現在位置が左側へはみ出した場合
+ long lLeftFrameNumber = pPianoRollFrame->GetVisibleLeftTime () / lTimeResolution;
+ long lTempLeftTime = lLeftFrameNumber * lTimeResolution;
+ if (m_lCurTime < lTempLeftTime) {
+ lTempLeftTime = (m_lCurTime / lTimeResolution) * lTimeResolution;
+ long x = pPianoRollFrame->TimetoX (lTempLeftTime);
+ pPianoRollFrame->SetTimeScrollPos (x);
+ }
+ }
+ }
+ ReleaseDC (pDC);
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+ }
+ }
+ // マウスキャプター中にクライアント領域をはみ出した場合の自動スクロール処理
+ else if (nIDEvent == 0x21) {
+ if (GetCapture () == this) {
+ CRect rcClient;
+ GetClientRect (&rcClient);
+ rcClient += CSize (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ if (!rcClient.PtInRect (m_ptMouseMove)) {
+ long lOldTimeScrollPos = pPianoRollFrame->GetTimeScrollPos ();
+ long lOldKeyScrollPos = pPianoRollFrame->GetKeyScrollPos ();
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ if (m_ptMouseMove.x < rcClient.left) {
+ pPianoRollFrame->SendMessage (WM_HSCROLL, (WPARAM)SB_LINEUP,
+ (LPARAM)(pPianoRollFrame->m_wndTimeScroll.GetSafeHwnd ()));
+ }
+ else if (m_ptMouseMove.x > rcClient.right) {
+ pPianoRollFrame->SendMessage (WM_HSCROLL, (WPARAM)SB_LINEDOWN,
+ (LPARAM)(pPianoRollFrame->m_wndTimeScroll.GetSafeHwnd ()));
+ }
+ if (m_ptMouseMove.y < rcClient.top) {
+ pPianoRollFrame->SendMessage (WM_VSCROLL, (WPARAM)SB_LINEUP,
+ (LPARAM)(pPianoRollFrame->m_wndKeyScroll.GetSafeHwnd ()));
+ }
+ else if (m_ptMouseMove.y > rcClient.bottom) {
+ pPianoRollFrame->SendMessage (WM_VSCROLL, (WPARAM)SB_LINEDOWN,
+ (LPARAM)(pPianoRollFrame->m_wndKeyScroll.GetSafeHwnd ()));
+ }
+ WORD wX = (WORD)(m_ptMouseMove.x - lOldTimeScrollPos);
+ WORD wY = (WORD)(m_ptMouseMove.y - lOldKeyScrollPos);
+ PostMessage (WM_MOUSEMOVE, (WPARAM)m_nMouseMoveFlags, (LPARAM)((wY << 16) | wX));
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+ }
+ }
+ }
+}
+
+
+// キーが押された時
+void CPianoRollKeyTimeView::OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags) {
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ switch (nChar) {
+ // DEL
+ case VK_DELETE:
+ // キャプター中ならば
+ if (GetCapture () == this) {
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ CHistoryUnit* pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ long lOldKey = pPianoRollFrame->YtoKey (m_ptMouseMove.y);
+ switch (m_lTempTool) {
+ // ペン
+ case ID_PIANOROLL_PEN:
+ if ((m_lTempMode == 0x0101 || m_lTempMode == 0x0102) && m_pTempEvent != NULL) {
+ ASSERT (m_pTempTrack);
+ // 置こうとしているノート又は移動中のノート削除
+ if (m_lTempMode = 0x0101) {
+ MIDIEvent_Delete (m_pTempEvent);
+ m_pTempEvent = NULL;
+ }
+ else if (m_lTempMode = 0x0102) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, m_pTempEvent);
+ MIDITrack_RemoveEvent (m_pTempTrack, m_pTempEvent);
+ }
+ // 履歴記録
+ if (m_pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (m_pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, m_pLastEvent);
+ }
+ }
+ // 古いキー消音
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ BYTE byMIDIMessage[3];
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ ReleaseCapture ();
+ KillTimer (0x21);
+ m_lTempMode = 0;
+ pSekaijuDoc->UpdateAllViews (NULL, SEKAIJUDOC_MIDIEVENTCHANGED);
+ }
+ break;
+ }
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+ }
+ // キャプター中でないならば
+ else {
+ // 『編集(E)』-『削除』実行 (20090823追加)
+ PostMessage (WM_COMMAND, ID_EDIT_DELETE, NULL);
+ }
+ break;
+ // ESC
+ case VK_ESCAPE:
+ // キャプター中ならば
+ if (GetCapture () == this) {
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ CHistoryUnit* pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ long lOldKey = pPianoRollFrame->YtoKey (m_ptMouseMove.y);
+ switch (m_lTempTool) {
+ // ペン
+ case ID_PIANOROLL_PEN:
+ if (m_lTempMode == 0x0101 && m_pTempEvent != NULL) {
+ ASSERT (m_pTempTrack);
+ // 置こうとしているノート廃止
+ MIDIEvent_Delete (m_pTempEvent);
+ m_pTempEvent = NULL;
+ // 履歴記録
+ if (m_pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (m_pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, m_pLastEvent);
+ }
+ }
+ // 古いキー消音
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ BYTE byMIDIMessage[3];
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ ReleaseCapture ();
+ KillTimer (0x21);
+ m_lTempMode = 0;
+ pSekaijuDoc->UpdateAllViews (NULL, SEKAIJUDOC_MIDIEVENTCHANGED);
+ break;
+ }
+ }
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+ }
+ break;
+ // Control
+ case VK_CONTROL:
+ if (1) {
+ WORD wX = (WORD)(m_ptMouseMove.x - pPianoRollFrame->GetTimeScrollPos ());
+ WORD wY = (WORD)(m_ptMouseMove.y - pPianoRollFrame->GetKeyScrollPos ());
+ UINT nFlags = m_nMouseMoveFlags | MK_CONTROL;
+ PostMessage (WM_MOUSEMOVE, (WPARAM)nFlags, (LPARAM)((wY << 16) | wX));
+ }
+ break;
+ // デフォルト
+ default:
+ pPianoRollFrame->PostMessage (WM_KEYDOWN, nChar, (nFlags << 16) | nRepCnt);
+ break;
+ }
+ return;
+}
+
+
+// キーが離された時
+void CPianoRollKeyTimeView::OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+ switch (nChar) {
+ // Control
+ case VK_CONTROL:
+ if (1) {
+ WORD wX = (WORD)(m_ptMouseMove.x - pPianoRollFrame->GetTimeScrollPos ());
+ WORD wY = (WORD)(m_ptMouseMove.y - pPianoRollFrame->GetKeyScrollPos ());
+ UINT nFlags = m_nMouseMoveFlags & (~MK_CONTROL);
+ PostMessage (WM_MOUSEMOVE, (WPARAM)nFlags, (LPARAM)((wY << 16) | wX));
+ }
+ break;
+ }
+ return;
+}
+
+// マウス左ボタン押された時
+void CPianoRollKeyTimeView::OnLButtonDown (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+ // 録音中は何もしない
+ if (pSekaijuApp->m_bRecording) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+ // MIDIデータがロックされている場合は何もしない
+ if (pSekaijuDoc->m_bEditLocked) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+
+ CClientDC dc (this);
+ OnPrepareDC (&dc, NULL);
+ CSize sizWndOrg (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ point += sizWndOrg;
+ ASSERT (m_pTempEvent == NULL);
+ ASSERT (m_lTempMode == 0);
+
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ CString strHistoryName;
+ CHistoryUnit* pCurHistoryUnit = NULL;
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ long lFormat = MIDIData_GetFormat (pMIDIData);
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempKey = pPianoRollFrame->YtoKey (point.y);
+ m_lTempTime = pPianoRollFrame->XtoTime (point.x);
+ m_lTempTool = pPianoRollFrame->m_lCurTool;
+ m_lTempChannel = pPianoRollFrame->GetCurChannel ();
+ m_lTempChannel = CLIP (0, m_lTempChannel, 15);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempVelocity = CLIP (1, m_lTempVelocity, 127);
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempDuration = CLIP (1, m_lTempDuration, 65535);
+ m_lTempSnap = pPianoRollFrame->GetCurSnap ();
+ m_lTempSnap = CLIP (1, m_lTempSnap, MIDIData_GetTimeResolution (pMIDIData));
+ m_pTempEvent = NULL;
+ m_pLastEvent = NULL;
+ CRect rcRegion;
+ BOOL bPtInNote = FALSE;
+ CRect rcNote;
+ MIDITrack* pTempTrack = NULL;
+ MIDIEvent* pTempEvent = NULL;
+ MIDITrack* pCloneTrack = NULL;
+ MIDIEvent* pLastEvent = NULL;
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ BYTE byMIDIMessage[3];
+ long i = 0;
+ switch (m_lTempTool) {
+ // ペン
+ case ID_PIANOROLL_PEN:
+ // フォーマット1のMIDIデータで最初のトラックにノートを置くのを禁止
+ if (lFormat == 1 && m_lTempTrackIndex == 0) {
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ CString strMsg;
+ VERIFY (strMsg.LoadString (IDS_UNABLE_TO_INSERT_NOTEEVENT_TO_THE_FIRST_TRACK_IN_FORMAT1_MIDIDATA));
+ AfxMessageBox (strMsg, MB_ICONEXCLAMATION);
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ break;
+ }
+ // 既存のノートの上にマウスが置かれた場合
+ i = MIDIData_CountTrack (pMIDIData) - 1; // 20090629追加
+ forEachTrackInverse (pMIDIData, pTempTrack) { // 20090629修正
+ long lPort = MIDITrack_GetOutputPort (pTempTrack);
+ if (0 <= lPort && lPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[lPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[lPort];
+ }
+ if (pPianoRollFrame->IsTrackVisible (i)) { // 20090629修正
+ forEachEventInverse (pTempTrack, pTempEvent) {
+ if (MIDIEvent_IsNoteOn (pTempEvent) && MIDIEvent_IsNote (pTempEvent)) {
+ CRect rcNote = GetNoteRect (pTempEvent);
+ if (rcNote.top <= point.y && point.y <= rcNote.bottom) {
+ // 長方形の左辺上をクリック
+ if (rcNote.left <= point. x && point.x < rcNote.left + rcNote.Width () / 4) {
+ pPianoRollFrame->SetCurTrackIndex (i);
+ pPianoRollFrame->SetCurVelocity (MIDIEvent_GetVelocity (pTempEvent));
+ pPianoRollFrame->SetCurDuration (MIDIEvent_GetDuration (pTempEvent));
+ pPianoRollFrame->SetCurChannel (MIDIEvent_GetChannel (pTempEvent));
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempChannel = MIDITrack_GetOutputChannel (pTempTrack); // 20100226修正
+ if (m_lTempChannel < 0 || m_lTempChannel >= 16) { // 20100226追加
+ m_lTempChannel = pPianoRollFrame->GetCurChannel (); // 20100226追加
+ } // 20100226追加
+ m_lTempTimeNoteOn = MIDIEvent_GetTime (pTempEvent);
+ m_lTempMode = 0x0103;
+ VERIFY (strHistoryName.LoadString (IDS_MODIFY_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ m_pTempEvent = pSekaijuDoc->ReplaceMIDIEvent (pTempEvent);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ InvalidateRect (rcRegion - sizWndOrg);
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+ }
+ // 長方形の右辺上をクリック
+ else if (rcNote.right - rcNote.Width () / 4 < point. x && point.x <= rcNote.right) {
+ pPianoRollFrame->SetCurTrackIndex (i);
+ pPianoRollFrame->SetCurVelocity (MIDIEvent_GetVelocity (pTempEvent));
+ pPianoRollFrame->SetCurDuration (MIDIEvent_GetDuration (pTempEvent));
+ pPianoRollFrame->SetCurChannel (MIDIEvent_GetChannel (pTempEvent));
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempChannel = MIDITrack_GetOutputChannel (pTempTrack); // 20100226修正
+ if (m_lTempChannel < 0 || m_lTempChannel >= 16) { // 20100226追加
+ m_lTempChannel = pPianoRollFrame->GetCurChannel (); // 20100226追加
+ } // 20100226追加
+ m_lTempTimeNoteOn = MIDIEvent_GetTime (pTempEvent);
+ m_lTempMode = 0x0104;
+ VERIFY (strHistoryName.LoadString (IDS_MODIFY_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ pCurHistoryUnit->AddHistoryRecord
+ (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ m_pTempEvent = pSekaijuDoc->ReplaceMIDIEvent (pTempEvent);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ InvalidateRect (rcRegion - sizWndOrg);
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+ }
+ // 長方形の内部をクリック
+ else if (rcNote.left <= point. x && point.x <= rcNote.right) {
+ pPianoRollFrame->SetCurTrackIndex (i);
+ pPianoRollFrame->SetCurVelocity (MIDIEvent_GetVelocity (pTempEvent));
+ pPianoRollFrame->SetCurDuration (MIDIEvent_GetDuration (pTempEvent));
+ pPianoRollFrame->SetCurChannel (MIDIEvent_GetChannel (pTempEvent));
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempChannel = MIDITrack_GetOutputChannel (pTempTrack); // 20100226修正
+ if (m_lTempChannel < 0 || m_lTempChannel >= 16) { // 20100226追加
+ m_lTempChannel = pPianoRollFrame->GetCurChannel (); // 20100226追加
+ } // 20100226追加
+ m_lTempTimeNoteOn = MIDIEvent_GetTime (pTempEvent);
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, m_lTempKey + MIDITrack_GetKeyPlus (pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (pTempTrack), 127);
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ m_lTempMode = 0x0102;
+ VERIFY (strHistoryName.LoadString (IDS_MODIFY_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ m_pTempEvent = pSekaijuDoc->ReplaceMIDIEvent (pTempEvent);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ if (nFlags & MK_CONTROL) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ else {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ InvalidateRect (rcRegion - sizWndOrg);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+ }
+ }
+ }
+ }
+ if (m_lTempMode != 0) {
+ break;
+ }
+ }
+ i--;
+ }
+ // 何もないところにマウスが置かれた場合
+ if (m_pTempEvent == NULL) {
+ if (MIDIData_GetFormat (pMIDIData) == 1 &&
+ m_pTempTrack == MIDIData_GetFirstTrack (pMIDIData)) {
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ CString strMsg;
+ VERIFY (strMsg.LoadString (IDS_UNABLE_TO_INSERT_NOTEEVENT_TO_THE_FIRST_TRACK_IN_FORMAT1_MIDIDATA));
+ AfxMessageBox (strMsg, MB_ICONEXCLAMATION);
+ return;
+ }
+ if (pPianoRollFrame->IsTrackVisible (m_lTempTrackIndex) == FALSE) {
+ pPianoRollFrame->SetTrackVisible (m_lTempTrackIndex);
+ pPianoRollFrame->m_pKeyScaleView->Invalidate ();
+ pPianoRollFrame->m_pKeyTimeView->Invalidate ();
+ pPianoRollFrame->m_pVelScaleView->Invalidate ();
+ pPianoRollFrame->m_pVelTimeView->Invalidate ();
+ }
+ m_lTempTime = (m_lTempTime / m_lTempSnap) * m_lTempSnap;
+ m_lTempTimeNoteOn = m_lTempTime;
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_pTempEvent = MIDIEvent_CreateNote
+ (m_lTempTime, m_lTempChannel, m_lTempKey, m_lTempVelocity, m_lTempDuration);
+ if (m_pTempEvent == NULL) {
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ CString strMsg;
+ VERIFY (strMsg.LoadString (IDS_UNABLE_TO_INSERT_NOTEEVENT_ANY_MORE_BEACUSE_OF_INSUFFICIENT_MEMORY));
+ AfxMessageBox (strMsg, MB_ICONEXCLAMATION);
+ return;
+ }
+ VERIFY (strHistoryName.LoadString (IDS_INSERT_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ pLastEvent = MIDITrack_GetLastEvent (m_pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ MIDITrack_InsertEvent (m_pTempTrack, m_pTempEvent);
+ m_lTempMode = 0x0101;
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, m_lTempKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ rcRegion = GetNoteRect (m_pTempEvent);
+ InvalidateRect (rcRegion - sizWndOrg);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ }
+ break;
+ // 線
+ case ID_PIANOROLL_LINE:
+ if (MIDIData_GetFormat (pMIDIData) == 1 &&
+ m_pTempTrack == MIDIData_GetFirstTrack (pMIDIData)) {
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ CString strMsg;
+ VERIFY (strMsg.LoadString (IDS_UNABLE_TO_INSERT_NOTEEVENT_TO_THE_FIRST_TRACK_IN_FORMAT1_MIDIDATA));
+ AfxMessageBox (strMsg, MB_ICONEXCLAMATION);
+ return;
+ }
+ if (pPianoRollFrame->IsTrackVisible (m_lTempTrackIndex) == FALSE) {
+ pPianoRollFrame->SetTrackVisible (m_lTempTrackIndex);
+ pPianoRollFrame->m_pKeyScaleView->Invalidate ();
+ pPianoRollFrame->m_pKeyTimeView->Invalidate ();
+ pPianoRollFrame->m_pVelScaleView->Invalidate ();
+ pPianoRollFrame->m_pVelTimeView->Invalidate ();
+ }
+ m_lTempTime = (m_lTempTime / m_lTempSnap) * m_lTempSnap;
+ m_lTempTimeNoteOn = m_lTempTime;
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, m_lTempKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ ::SetCursor (pSekaijuApp->m_hCursorLine);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ m_lTempMode = 0x0201;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+
+ // 消しゴム
+ case ID_PIANOROLL_ERASER:
+ // フォーマット1のMIDIデータで最初のトラックにノートを消すのを禁止
+ if (lFormat == 1 && m_lTempTrackIndex == 0) {
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ CString strMsg;
+ VERIFY (strMsg.LoadString (IDS_UNABLE_TO_DELETE_NOTEEVENT_TO_THE_FIRST_TRACK_IN_FORMAT1_MIDIDATA));
+ AfxMessageBox (strMsg, MB_ICONEXCLAMATION);
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ break;
+ }
+ VERIFY (strHistoryName.LoadString (IDS_DELETE_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ m_pTempEvent = NULL;
+ m_lTempMode = 0x0301;
+ // 既存のノートの上にマウスが置かれたか調べる
+ bPtInNote = FALSE;
+ i = MIDIData_CountTrack (pMIDIData) - 1;
+ forEachTrackInverse (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEventInverse (pTempTrack, pTempEvent) {
+ if (MIDIEvent_IsNoteOn (pTempEvent) && MIDIEvent_IsNote (pTempEvent)) {
+ CRect rcNote = GetNoteRect (pTempEvent);
+ // 既存のノートの上をクリックした場合
+ if (rcNote.top <= point.y && point.y <= rcNote.bottom &&
+ rcNote.left <= point.x && point. x<= rcNote.right) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ MIDITrack_RemoveEvent (pTempTrack, pTempEvent);
+ rcRegion = rcNote - sizWndOrg;
+ InvalidateRect (rcRegion);
+ bPtInNote = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (bPtInNote) {
+ break;
+ }
+ i++;
+ }
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+
+ // 選択
+ case ID_PIANOROLL_SELECT:
+ bPtInNote = FALSE;
+ i = 0;
+ // 既存の選択されているノートの上にマウスが置かれたか調べる
+ forEachTrack (pMIDIData, pTempTrack) {
+ long lPort = MIDITrack_GetOutputPort (pTempTrack);
+ if (0 <= lPort && lPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[lPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[lPort];
+ }
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEvent (pTempTrack, pTempEvent) {
+ if (MIDIEvent_IsNoteOn (pTempEvent) && MIDIEvent_IsNote (pTempEvent) &&
+ pSekaijuDoc->IsEventSelected (pTempEvent)) {
+ rcNote = GetNoteRect (pTempEvent);
+ if (rcNote.top <= point.y && point.y <= rcNote.bottom &&
+ rcNote.left <= point.x && point. x<= rcNote.right) {
+ bPtInNote = TRUE;
+ break;
+ }
+ }
+ }
+ if (bPtInNote) {
+ break;
+ }
+ }
+ i++;
+ }
+ // 既存の選択されているノートの上にマウスが置かれた場合(複写又は移動モード)
+ if (bPtInNote) {
+ pPianoRollFrame->SetCurTrackIndex (i);
+ pPianoRollFrame->SetCurVelocity (MIDIEvent_GetVelocity (pTempEvent));
+ pPianoRollFrame->SetCurDuration (MIDIEvent_GetDuration (pTempEvent));
+ pPianoRollFrame->SetCurChannel (MIDIEvent_GetChannel (pTempEvent));
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempChannel = MIDITrack_GetOutputChannel (pTempTrack); // 20100226修正
+ if (m_lTempChannel < 0 || m_lTempChannel >= 16) { // 20100226追加
+ m_lTempChannel = pPianoRollFrame->GetCurChannel (); // 20100226追加
+ } // 20100226追加
+ m_lTempTimeNoteOn = MIDIEvent_GetTime (pTempEvent);
+ m_lTempNoteDuration = MIDIEvent_GetDuration (pTempEvent);
+ m_pTempEvent = pTempEvent;
+ m_theTempSelectedEventArray.RemoveAll ();
+ // 複写の場合(CONTROLが押されている)
+ if (nFlags & MK_CONTROL) {
+ VERIFY (strHistoryName.LoadString (IDS_DUPLICATE_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ i = 0; //20080902追加
+ forEachTrack (pMIDIData, pTempTrack) { //20080902修正
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ // このトラックのEndofTrackイベントを履歴記録
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ // 選択ノートイベントの複写
+ forEachEvent (pTempTrack, pTempEvent) {
+ if (MIDIEvent_IsNoteOn (pTempEvent) &&
+ pSekaijuDoc->IsEventSelected (pTempEvent) &&
+ pTempEvent->m_pPrevCombinedEvent == NULL) {
+ // 選択されたノートオンを非選択状態にする。
+ MIDIEvent* pCloneEvent = NULL;
+ pCloneEvent = pSekaijuDoc->SelectEvent (pTempEvent, 0, pCurHistoryUnit);
+ if (pCloneEvent == NULL) {
+ continue;
+ }
+ // ノートオンを複写し、複写した方を選択状態にする。
+ pCloneEvent = pSekaijuDoc->DuplicateMIDIEvent (pCloneEvent);
+ if (pCloneEvent) {
+ pCloneEvent->m_lUser1 = MIDIEvent_GetKey (pCloneEvent);
+ pCloneEvent->m_lUser2 = MIDIEvent_GetTime (pCloneEvent);
+ pCloneEvent->m_lUser3 = MIDIEvent_GetDuration (pCloneEvent);
+ pSekaijuDoc->SetEventSelected (pCloneEvent, 1);
+ m_theTempSelectedEventArray.Add (pCloneEvent);
+ pTempEvent = pCloneEvent;
+ }
+ }
+ }
+ }
+ i++;
+ }
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAllCopy);
+ m_lTempMode = 0x0403;
+ }
+ // 移動の場合(CONTROLが押されていない)
+ else {
+ VERIFY (strHistoryName.LoadString (IDS_MOVE_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ i = 0; //20080902追加
+ forEachTrack (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ forEachEvent (pTempTrack, pTempEvent) {
+ if (MIDIEvent_IsNoteOn (pTempEvent) &&
+ pSekaijuDoc->IsEventSelected (pTempEvent) &&
+ pTempEvent->m_pPrevCombinedEvent == NULL) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ MIDIEvent* pCloneEvent = pSekaijuDoc->ReplaceMIDIEvent (pTempEvent);
+ if (pCloneEvent) {
+ pCloneEvent->m_lUser1 = MIDIEvent_GetKey (pCloneEvent);
+ pCloneEvent->m_lUser2 = MIDIEvent_GetTime (pCloneEvent);
+ pCloneEvent->m_lUser3 = MIDIEvent_GetDuration (pCloneEvent);
+ m_theTempSelectedEventArray.Add (pCloneEvent);
+ pTempEvent = pCloneEvent;
+ }
+ }
+ }
+ }
+ i++;
+ }
+ // 長方形の左辺上をクリック(開始時刻の移動)
+ if (rcNote.left <= point.x && point.x < rcNote.left + rcNote.Width () / 4) {
+ m_lTempMode = 0x0406;
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ }
+ // 長方形の右辺上をクリック(終了時刻の移動)
+ else if (rcNote.right - rcNote.Width() / 4 <= point.x && point.x < rcNote.right) {
+ m_lTempMode = 0x0407;
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ }
+ // 長方形の中央部をクリック(移動)
+ else {
+ m_lTempMode = 0x0402;
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ }
+ // 移動又は複写の場合のみ音だし
+ if (m_lTempMode == 0x0402 || m_lTempMode == 0x0403) {
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, m_lTempKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ }
+ rcRegion = GetNoteRect (m_pTempEvent);
+ InvalidateRect (rcRegion - sizWndOrg);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+
+ }
+ // 何もないところにマウスが置かれた場合(選択範囲モード)
+ else {
+ // 旧選択イベントの選択解除(Shiftが押されていない場合かつCtrlが押されていない場合のみ)
+ CString strHistoryName;
+ VERIFY (strHistoryName.LoadString (IDS_SELECT_DESELECT_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ if ((nFlags & MK_SHIFT) == 0 && (nFlags & MK_CONTROL) == 0) {
+ pSekaijuDoc->SelectNoObject (pCurHistoryUnit);
+ }
+ m_lTempMode = 0x0401;
+ dc.SetROP2 (R2_NOT);
+ dc.SetPixel (point, RGB (0, 0, 0));
+ dc.SetROP2 (R2_COPYPEN);
+ ::SetCursor (pSekaijuApp->m_hCursorSelect);
+ Invalidate ();
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ }
+ break;
+
+ // スクラブ
+ case ID_PIANOROLL_SPEAKER:
+ if (pSekaijuApp->m_bPlaying) {
+ pPianoRollFrame->SendMessage (WM_COMMAND, (WPARAM)ID_CONTROL_PLAY, (LPARAM)0);
+ }
+ if (pSekaijuApp->m_thePianoRollOption.m_bSpeakerModeVisibleTrack) {
+ long i = 0;
+ long lTempOutputOn[MAXMIDITRACKNUM];
+ forEachTrack (pMIDIData, pTempTrack) {
+ lTempOutputOn[i] = MIDITrack_GetOutputOn (pTempTrack);
+ MIDITrack_SetOutputOn (pTempTrack, pPianoRollFrame->IsTrackVisible (i));
+ i++;
+ }
+ pSekaijuApp->SetPlayPosition (pSekaijuDoc, m_lTempTime);
+ pSekaijuApp->SendDifferentStatus (SDS_ALL);
+ i = 0;
+ forEachTrack (pMIDIData, pTempTrack) {
+ MIDITrack_SetOutputOn (pTempTrack, lTempOutputOn[i]);
+ i++;
+ }
+ }
+ else {
+ pSekaijuApp->SetPlayPosition (pSekaijuDoc, m_lTempTime);
+ pSekaijuApp->SendDifferentStatus (SDS_ALL);
+ }
+ m_lTempMode = 0x0501;
+ ::SetCursor (pSekaijuApp->m_hCursorSpeaker);
+ pPianoRollFrame->m_bAutoPageUpdate = FALSE;
+ SetTimer (0x21, 55, NULL);
+ SetCapture ();
+ break;
+ }
+ m_ptMouseDown = m_ptMouseMove = point;
+ m_nMouseDownFlags = m_nMouseMoveFlags = nFlags;
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+}
+
+// マウス右ボタン押された時
+void CPianoRollKeyTimeView::OnRButtonDown (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+ // マウスキャプター中は何もしない
+ if (GetCapture () == this) {
+ return;
+ }
+
+ // 他の操作中は何もしない
+ if (m_lTempMode != 0x0000) {
+ return;
+ }
+
+ CPoint ptMenu (point);
+ ClientToScreen (&ptMenu);
+
+ CClientDC dc (this);
+ OnPrepareDC (&dc, NULL);
+ CSize sizWndOrg (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ point += sizWndOrg;
+ ASSERT (m_pTempEvent == NULL);
+ ASSERT (m_lTempMode == 0);
+
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ CHistoryUnit* pCurHistoryUnit = NULL;
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ long lFormat = MIDIData_GetFormat (pMIDIData);
+ m_lTempTrackIndex = pPianoRollFrame->GetCurTrackIndex ();
+ m_pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ m_lTempKey = pPianoRollFrame->YtoKey (point.y);
+ m_lTempTime = pPianoRollFrame->XtoTime (point.x);
+ m_lTempTool = pPianoRollFrame->m_lCurTool;
+ m_lTempChannel = pPianoRollFrame->GetCurChannel ();
+ m_lTempChannel = CLIP (0, m_lTempChannel, 15);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempVelocity = CLIP (1, m_lTempVelocity, 127);
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempDuration = CLIP (1, m_lTempDuration, 65535);
+ m_lTempSnap = pPianoRollFrame->GetCurSnap ();
+ m_lTempSnap = CLIP (1, m_lTempSnap, MIDIData_GetTimeResolution (pMIDIData));
+ m_pTempEvent = NULL;
+ m_pLastEvent = NULL;
+ CRect rcRegion;
+ BOOL bPtInNote = FALSE;
+ MIDITrack* pTempTrack = NULL;
+ MIDIEvent* pTempEvent = NULL;
+ MIDITrack* pCloneTrack = NULL;
+ MIDIEvent* pLastEvent = NULL;
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ // 既存のノートの上にマウスが置かれた場合
+ long i = MIDIData_CountTrack (pMIDIData) - 1; // 20090629修正
+ forEachTrackInverse (pMIDIData, pTempTrack) { // 20090629修正
+ long lPort = MIDITrack_GetOutputPort (pTempTrack);
+ if (0 <= lPort && lPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[lPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[lPort];
+ }
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEventInverse (pTempTrack, pTempEvent) { // 20090629修正
+ if (MIDIEvent_IsNoteOn (pTempEvent) && MIDIEvent_IsNote (pTempEvent)) {
+ CRect rcNote = GetNoteRect (pTempEvent);
+ // 長方形の内部をクリック
+ if (rcNote.top <= point.y && point.y <= rcNote.bottom) {
+ if (rcNote.left <= point. x && point.x <= rcNote.right) {
+ //pPianoRollFrame->SetCurTrackIndex (i);
+ //pPianoRollFrame->SetCurVelocity (MIDIEvent_GetVelocity (pTempEvent));
+ //pPianoRollFrame->SetCurDuration (MIDIEvent_GetDuration (pTempEvent));
+ //pPianoRollFrame->SetCurChannel (MIDIEvent_GetChannel (pTempEvent));
+ m_lTempTrackIndex = i;
+ m_pTempTrack = pSekaijuDoc->GetTrack (i);
+ m_lTempOutputPort = MIDITrack_GetOutputPort (m_pTempTrack);
+ m_lTempVelocity = pPianoRollFrame->GetCurVelocity ();
+ m_lTempDuration = pPianoRollFrame->GetCurDuration ();
+ m_lTempChannel = MIDITrack_GetOutputChannel (pTempTrack); // 20110115修正
+ if (m_lTempChannel < 0 || m_lTempChannel >= 16) { // 20110115追加
+ m_lTempChannel = pPianoRollFrame->GetCurChannel (); // 20110115追加
+ } // 20110115追加
+ m_lTempTimeNoteOn = MIDIEvent_GetTime (pTempEvent);
+ m_pTempEvent = pTempEvent;
+ break;
+ }
+ }
+ }
+ }
+ if (m_pTempEvent) {
+ break;
+ }
+ }
+ i--; // 20090629修正
+ }
+ m_lTempMode = 0x1001;
+
+ ShowPopupMenu (ptMenu);
+
+ m_pTempEvent = NULL;
+ m_lTempMode = 0x0000;
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+}
+
+// マウス左ボタン離されたとき
+void CPianoRollKeyTimeView::OnLButtonUp (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+ // 録音中は何もしない
+ if (pSekaijuApp->m_bRecording) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+ // MIDIデータがロックされている場合は何もしない
+ if (pSekaijuDoc->m_bEditLocked) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+
+ CClientDC dc (this);
+ OnPrepareDC (&dc, NULL);
+ CSize sizWndOrg (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ point += sizWndOrg;
+
+ long lDownKey = pPianoRollFrame->YtoKey (m_ptMouseDown.y);
+ long lOldKey = pPianoRollFrame->YtoKey (m_ptMouseMove.y);
+ long lNewKey = pPianoRollFrame->YtoKey (point.y);
+ long lDownTime = pPianoRollFrame->XtoTime (m_ptMouseDown.x);
+ long lOldTime = pPianoRollFrame->XtoTime (m_ptMouseMove.x);
+ long lNewTime = pPianoRollFrame->XtoTime (point.x);
+ long lStartKey = MIN (lDownKey, lNewKey);
+ long lEndKey = MAX (lDownKey, lNewKey);
+ long lStartTime = MIN (lDownTime, lNewTime);
+ long lEndTime = MAX (lDownTime, lNewTime);
+ long i = 0;
+ CRect rcRegion;
+ // キャプター中ならば
+ if (GetCapture () == this) {
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ MIDITrack* pMIDITrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ CHistoryUnit* pCurHistoryUnit = NULL;
+ MIDITrack* pTempTrack = NULL;
+ MIDIEvent* pTempEvent = NULL;
+ MIDIEvent* pLastEvent = NULL;
+ BYTE byMIDIMessage[3];
+ switch (m_lTempTool) {
+ // ペン
+ case ID_PIANOROLL_PEN:
+ ASSERT (m_pTempTrack);
+ ASSERT (m_pTempEvent);
+ ASSERT (m_lTempMode);
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ // 音符挿入中又は音符移動中の場合に限り
+ if (m_lTempMode == 0x0101 || m_lTempMode == 0x0102) {
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ }
+ pSekaijuDoc->SetModifiedFlag (TRUE);
+ // 履歴記録
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, m_pTempEvent);
+ if (m_pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (m_pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, m_pLastEvent);
+ }
+ }
+ break;
+ // 線
+ case ID_PIANOROLL_LINE:
+ ASSERT (m_pTempTrack);
+ ASSERT (m_lTempMode);
+ if (m_lTempMode == 0x0201) {
+ CString strHistoryName;
+ VERIFY (strHistoryName.LoadString (IDS_INSERT_NOTE));
+ VERIFY (pSekaijuDoc->AddHistoryUnit (strHistoryName));
+ VERIFY (pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ());
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ // EOT処理
+ pLastEvent = MIDITrack_GetLastEvent (m_pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pLastEvent);
+ m_pLastEvent = pSekaijuDoc->ReplaceMIDIEvent (pLastEvent);
+ }
+ }
+ // ノートイベントの挿入
+ long lKey = 0;
+ long lStartTime2 = 0;
+ long lEndTime2 = 0;
+ long lDur = 0;
+ long lCh = m_lTempChannel & 0x0F;
+ long lVel = CLIP (1, m_lTempVelocity, 127);
+ // 垂直線の場合
+ if (lEndTime == lStartTime) {
+ ;
+ }
+ // 水平線の場合
+ else if (lEndKey == lStartKey) {
+ lDur = lEndTime - lStartTime;
+ MIDIEvent* pNewEvent = MIDIEvent_CreateNote
+ (lStartTime, lCh, lKey, lVel, lDur);
+ if (pNewEvent) {
+ MIDITrack_InsertEvent (m_pTempTrack, pNewEvent);
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pNewEvent);
+ }
+ }
+ // 左下→右上又は右上→左下の場合
+ else if (lDownKey < lOldKey && lDownTime < lOldTime ||
+ lDownKey > lOldKey && lDownTime > lOldTime) {
+ for (lKey = lStartKey; lKey <= lEndKey; lKey++) {
+ lStartTime2 = lStartTime +
+ (lEndTime - lStartTime) * (lKey - lStartKey) / (lEndKey - lStartKey);
+ lEndTime2 = lStartTime +
+ (lEndTime - lStartTime) * (lKey + 1 - lStartKey) / (lEndKey - lStartKey);
+ lDur = lEndTime2 - lStartTime2;
+ MIDIEvent* pNewEvent = MIDIEvent_CreateNote
+ (lStartTime2, lCh, lKey, lVel, lDur);
+ if (pNewEvent) {
+ MIDITrack_InsertEvent (m_pTempTrack, pNewEvent);
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pNewEvent);
+ }
+ }
+ }
+ // 右下→左上又は左上→右下の場合
+ else if (lDownKey < lOldKey && lDownTime > lOldTime ||
+ lDownKey > lOldKey && lDownTime < lOldTime) {
+ for (lKey = lEndKey; lKey >= lStartKey; lKey--) {
+ lStartTime2 = lStartTime +
+ (lEndTime - lStartTime) * (lEndKey - lKey) / (lEndKey - lStartKey);
+ lEndTime2 = lStartTime +
+ (lEndTime - lStartTime) * (lEndKey - lKey + 1) / (lEndKey - lStartKey);
+ lDur = lEndTime2 - lStartTime2;
+ MIDIEvent* pNewEvent = MIDIEvent_CreateNote
+ (lStartTime2, lCh, lKey, lVel, lDur);
+ if (pNewEvent) {
+ MIDITrack_InsertEvent (m_pTempTrack, pNewEvent);
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pNewEvent);
+ }
+ }
+ }
+ // EOT処理
+ if (m_pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (m_pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, m_pLastEvent);
+ }
+ }
+ pSekaijuDoc->SetModifiedFlag (TRUE);
+ }
+ break;
+ // 消しゴム
+ case ID_PIANOROLL_ERASER:
+ pSekaijuDoc->SetModifiedFlag (TRUE);
+ break;
+ // 選択
+ case ID_PIANOROLL_SELECT:
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ // 音符移動中又は音符複写中の場合又は開始時刻の移動中又は終了時刻の移動中
+ if (m_lTempMode == 0x0402 || m_lTempMode == 0x0403 || m_lTempMode == 0x0406 || m_lTempMode == 0x0407) {
+ // 各選択イベントのマウスダウン時のキー情報とタイム情報を削除
+ long j;
+ long lTempSelectedEventCount = m_theTempSelectedEventArray.GetSize ();
+ for (j = 0; j < lTempSelectedEventCount; j++) {
+ MIDIEvent* pTempEvent = (MIDIEvent*)(m_theTempSelectedEventArray.GetAt (j));
+ pTempEvent->m_lUser1 = 0;
+ pTempEvent->m_lUser2 = 0;
+ pTempEvent->m_lUser3 = 0;
+ }
+ // 複写の場合
+ if (m_lTempMode == 0x0403) {
+ // 元の位置と同じ場合は複写しない。
+ if ((lDownKey == lNewKey) &&
+ (lDownTime / m_lTempSnap) * m_lTempSnap ==
+ (lNewTime / m_lTempSnap) * m_lTempSnap) {
+ for (j = 0; j < lTempSelectedEventCount; j++) {
+ MIDIEvent* pCloneEvent = (MIDIEvent*)(m_theTempSelectedEventArray.GetAt (j));
+ MIDIEvent_Delete (pCloneEvent);
+ }
+ }
+ // 元の位置と異なる場所に複写された場合、複写確定、履歴記録。
+ else {
+ for (j = 0; j < lTempSelectedEventCount; j++) {
+ MIDIEvent* pCloneEvent = (MIDIEvent*)(m_theTempSelectedEventArray.GetAt (j));
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pCloneEvent);
+ }
+ }
+ }
+ // 移動の場合、開始時刻の移動の場合、終了時刻の移動の場合
+ else if (m_lTempMode == 0x0402 || m_lTempMode == 0x0406 || m_lTempMode == 0x0407) {
+ for (j = 0; j < lTempSelectedEventCount; j++) {
+ MIDIEvent* pCloneEvent = (MIDIEvent*)(m_theTempSelectedEventArray.GetAt (j));
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pCloneEvent);
+ }
+ }
+ // EOTの履歴記録
+ i = 0;
+ forEachTrack (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ pLastEvent = MIDITrack_GetLastEvent (pTempTrack);
+ if (pLastEvent) {
+ if (MIDIEvent_IsEndofTrack (pLastEvent)) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_INSERTEVENT, pLastEvent);
+ }
+ }
+ }
+ i++;
+ }
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ pSekaijuDoc->SetModifiedFlag (TRUE);
+ }
+ // 選択範囲変更中の場合
+ else if (m_lTempMode == 0x0401) {
+ // 新規矩形内部選択(左→右へドラッグ)
+ if (m_ptMouseMove.x >= m_ptMouseDown.x) {
+ forEachTrack (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEvent (pTempTrack, pTempEvent) {
+ if ((MIDIEvent_IsNoteOn (pTempEvent) || MIDIEvent_IsNoteOff (pTempEvent)) &&
+ pTempEvent->m_pPrevCombinedEvent == NULL) {
+ long lTime = MIDIEvent_GetTime (pTempEvent);
+ long lDur = MIDIEvent_GetDuration (pTempEvent);
+ if (lStartTime <= lTime && lTime <= lEndTime &&
+ lStartTime <= lTime + lDur && lTime + lDur <= lEndTime) {
+ long lKey = MIDIEvent_GetKey (pTempEvent);
+ if (lStartKey + 1 <= lKey && lKey <= lEndKey - 1) { // 2010042
+ MIDIEvent* pCloneEvent = pSekaijuDoc->SelectEvent
+ (pTempEvent, 1, pCurHistoryUnit);
+ if (pCloneEvent) {
+ pTempEvent = pCloneEvent;
+ }
+ }
+ }
+ }
+ }
+ }
+ i++;
+ }
+ }
+ // 新規矩形接触選択(右→左へドラッグ) // 20100503追加
+ else {
+ forEachTrack (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEvent (pTempTrack, pTempEvent) {
+ if ((MIDIEvent_IsNoteOn (pTempEvent) || MIDIEvent_IsNoteOff (pTempEvent)) &&
+ pTempEvent->m_pPrevCombinedEvent == NULL) {
+ long lTime = MIDIEvent_GetTime (pTempEvent);
+ long lDur = MIDIEvent_GetDuration (pTempEvent);
+ if (lStartTime <= lTime && lTime <= lEndTime ||
+ lStartTime <= lTime + lDur && lTime + lDur <= lEndTime ||
+ lTime <= lStartTime && lEndTime <= lTime + lDur) {
+ long lKey = MIDIEvent_GetKey (pTempEvent);
+ if (lStartKey <= lKey && lKey <= lEndKey) {
+ MIDIEvent* pCloneEvent = pSekaijuDoc->SelectEvent
+ (pTempEvent, 1, pCurHistoryUnit);
+ if (pCloneEvent) {
+ pTempEvent = pCloneEvent;
+ }
+ }
+ }
+ }
+ }
+ }
+ i++;
+ }
+ }
+ }
+ break;
+
+ // スクラブ
+ case ID_PIANOROLL_SPEAKER:
+ pSekaijuApp->SendAllNoteOff ();
+ pSekaijuApp->SendAllSoundOff ();
+ break;
+ }
+ m_theTempSelectedEventArray.RemoveAll ();
+ m_pTempEvent = NULL;
+ m_lTempMode = 0;
+ KillTimer (0x21);
+ ReleaseCapture ();
+ pSekaijuDoc->UpdateAllViews (NULL, SEKAIJUDOC_MIDIEVENTCHANGED);
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+ }
+}
+
+// マウス右ボタン離されたとき
+void CPianoRollKeyTimeView::OnRButtonUp (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+}
+
+// マウスが動かされたとき
+void CPianoRollKeyTimeView::OnMouseMove (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+
+ // 録音中は何もしない
+ if (pSekaijuApp->m_bRecording) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+ // MIDIデータがロックされている場合は何もしない
+ if (pSekaijuDoc->m_bEditLocked) {
+ ::SetCursor (pSekaijuApp->m_hCursorNo);
+ return;
+ }
+
+ CClientDC dc (this);
+ OnPrepareDC (&dc, NULL);
+ CSize sizWndOrg (pPianoRollFrame->GetTimeScrollPos (), pPianoRollFrame->GetKeyScrollPos ());
+ point += sizWndOrg;
+ CRect rcClient;
+ GetClientRect (&rcClient);
+
+ pSekaijuDoc->m_theCriticalSection.Lock ();
+ MIDIData* pMIDIData = pSekaijuDoc->m_pMIDIData;
+ MIDITrack* pTempTrack = NULL;
+ MIDIEvent* pTempEvent = NULL;
+ CHistoryUnit* pCurHistoryUnit = NULL;
+ long lDownKey = pPianoRollFrame->YtoKey (m_ptMouseDown.y);
+ long lOldKey = pPianoRollFrame->YtoKey (m_ptMouseMove.y);
+ long lNewKey = pPianoRollFrame->YtoKey (point.y);
+ long lDownTime = pPianoRollFrame->XtoTime (m_ptMouseDown.x);
+ long lOldTime = pPianoRollFrame->XtoTime (m_ptMouseMove.x);
+ long lNewTime = pPianoRollFrame->XtoTime (point.x);
+ CRect rcRegion;
+
+ BYTE byMIDIMessage[3];
+ // キャプター中ならば
+ if (GetCapture () == this) {
+ // マウスが動かされていないのにこの関数が呼び出された場合は何もしない(20090629追加)
+ if (point == m_ptMouseMove) {
+ pSekaijuDoc->m_theCriticalSection.Unlock (); // 20090704修正
+ return;
+ }
+ MIDIOut* pMIDIOut = NULL;
+ MIDIStatus* pMIDIStatus = NULL;
+ pTempTrack = pSekaijuDoc->GetTrack (m_lTempTrackIndex);
+ if (0 <= m_lTempOutputPort && m_lTempOutputPort < MAXMIDIOUTDEVICENUM) {
+ pMIDIOut = pSekaijuApp->m_pMIDIOut[m_lTempOutputPort];
+ pMIDIStatus = pSekaijuApp->m_pMIDIOutStatus[m_lTempOutputPort];
+ }
+ long i = 0;
+ BOOL bErased = FALSE;
+ // ツール別の操作
+ switch (m_lTempTool) {
+ case ID_PIANOROLL_PEN:
+ ASSERT (m_pTempTrack);
+ ASSERT (m_pTempEvent);
+ ASSERT (m_lTempMode);
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ // 音符移動中
+ if (m_lTempMode == 0x0101 || m_lTempMode == 0x0102) {
+ // キーが変わった場合
+ if (lOldKey != lNewKey) {
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ // 新しいキーを設定
+ MIDIEvent_SetKey (m_pTempEvent, CLIP (0, lNewKey, 127));
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ // 新しいキー発音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lNewKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ }
+ // 時刻が変わった場合
+ if ((lOldTime / m_lTempSnap) * m_lTempSnap !=
+ (lNewTime / m_lTempSnap) * m_lTempSnap) {
+ long lDeltaTime =
+ (lNewTime / m_lTempSnap) * m_lTempSnap -
+ (lOldTime / m_lTempSnap) * m_lTempSnap;
+ long lCurTime = MIDIEvent_GetTime (m_pTempEvent);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ long lTempTime = CLIP (0, lCurTime + lDeltaTime, 0x7FFF0000);
+ MIDIEvent_SetTime (m_pTempEvent, lTempTime);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ }
+ // 音符の開始時刻移動
+ else if (m_lTempMode == 0x0103) {
+ // 時刻が変わった場合(20081227修正,20120731修正)
+ if ((lOldTime + m_lTempSnap / 2) / m_lTempSnap != (lNewTime + m_lTempSnap / 2) / m_lTempSnap) {
+ long lTempTime = MIDIEvent_GetTime (m_pTempEvent);
+ long lTempDuration = MIDIEvent_GetDuration (m_pTempEvent);
+ long lDeltaTime = (lNewTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap - lTempTime;
+ long lTime = CLIP (0, lTempTime + lDeltaTime, 0x7FFFFFFF);
+ long lDuration = CLIP (1, lTempDuration - lDeltaTime, 65535);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ MIDIEvent_SetTime (m_pTempEvent, lTime);
+ MIDIEvent_SetDuration (m_pTempEvent, lDuration);
+ pPianoRollFrame->SetCurDuration (lDuration);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ }
+ // 音符の終了時刻移動
+ else if (m_lTempMode == 0x0104) {
+ // 時刻が変わった場合(20081227修正,20120731修正)
+ if ((lOldTime + m_lTempSnap / 2) / m_lTempSnap != (lNewTime + m_lTempSnap / 2) / m_lTempSnap) {
+ long lTempTime = MIDIEvent_GetTime (m_pTempEvent);
+ long lTempDuration = MIDIEvent_GetDuration (m_pTempEvent);
+ long lDeltaTime = (lNewTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap - lTempDuration - lTempTime;
+ long lDuration = CLIP (1, lTempDuration + lDeltaTime, 65535);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ MIDIEvent_SetDuration (m_pTempEvent, lDuration);
+ pPianoRollFrame->SetCurDuration (lDuration);
+ rcRegion = GetNoteRect (m_pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ }
+ break;
+
+ // 線
+ case ID_PIANOROLL_LINE:
+ ASSERT (m_pTempTrack);
+ ASSERT (m_lTempMode);
+ // 音符移動中
+ if (m_lTempMode == 0x0201) {
+ rcRegion = CRect (m_ptMouseDown, m_ptMouseMove);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseDown, point);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ // キーが変わった場合
+ if (lOldKey != lNewKey) {
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ // 新しいキー発音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lNewKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ }
+ }
+ break;
+ // 消しゴム
+ case ID_PIANOROLL_ERASER:
+ bErased = FALSE; // 20090629追加
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ // 既存のノートの上にマウスが置かれた場合 */
+ i = MIDIData_CountTrack (pMIDIData) - 1;
+ forEachTrackInverse (pMIDIData, pTempTrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEventInverse (pTempTrack, pTempEvent) { // 20090629追加
+ if (MIDIEvent_IsNoteOn (pTempEvent) && MIDIEvent_IsNote (pTempEvent)) {
+ CRect rcNote = GetNoteRect (pTempEvent);
+ // 長方形の内部を通過
+ if (rcNote.top <= point.y && point.y <= rcNote.bottom &&
+ rcNote.left <= point.x && point.x <= rcNote.right) {
+ pCurHistoryUnit->AddHistoryRecord (HISTORYRECORD_REMOVEEVENT, pTempEvent);
+ MIDITrack_RemoveEvent (pTempTrack, pTempEvent);
+ rcRegion = rcNote;
+ rcRegion.InflateRect (1, 1);
+ bErased = TRUE; // 20090629追加
+ InvalidateRect (rcRegion - sizWndOrg);
+ break;
+ }
+ }
+ }
+ if (bErased) { // 20090629追加
+ break;
+ }
+ }
+ i--;
+ }
+ break;
+ // 選択
+ case ID_PIANOROLL_SELECT:
+ pCurHistoryUnit = pSekaijuDoc->GetCurHistoryUnit ();
+ // 移動又は複写中
+ if (m_lTempMode == 0x0402 || m_lTempMode == 0x0403 || m_lTempMode == 0x0406 || m_lTempMode == 0x0407) {
+ long lTempSelectedEventArrayCount = m_theTempSelectedEventArray.GetSize ();
+ long i;
+ // キーが変わった場合
+ if (lOldKey != lNewKey) {
+ if (m_lTempMode == 0x0402 || m_lTempMode == 0x0403) {
+ long lDeltaKey = lNewKey - lDownKey;
+ // 古いキー消音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lOldKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)0;
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ // 新しいキーを設定
+ for (i = 0; i < lTempSelectedEventArrayCount; i++) {
+ MIDIEvent* pTempEvent = (MIDIEvent*)m_theTempSelectedEventArray.GetAt (i);
+ rcRegion = GetNoteRect (pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ long lTempKey = pTempEvent->m_lUser1;
+ long lTargetKey = lTempKey + lDeltaKey;
+ lTargetKey = CLIP (0, lTargetKey, 127);
+ MIDIEvent_SetKey (pTempEvent, lTargetKey);
+ rcRegion = GetNoteRect (pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ // 新しいキー発音
+ byMIDIMessage[0] = 0x90 | (m_lTempChannel & 0x0F);
+ byMIDIMessage[1] = (BYTE)CLIP (0, lNewKey + MIDITrack_GetKeyPlus (m_pTempTrack), 127);
+ byMIDIMessage[2] = (BYTE)CLIP (1, m_lTempVelocity + MIDITrack_GetVelocityPlus (m_pTempTrack), 127);
+ if (pMIDIOut) {
+ MIDIOut_PutMIDIMessage (pMIDIOut, byMIDIMessage, 3);
+ }
+ if (pMIDIStatus) {
+ MIDIStatus_PutMIDIMessage (pMIDIStatus, byMIDIMessage, 3);
+ }
+ }
+ }
+ // 時刻が変わった場合
+ if ((lOldTime + m_lTempSnap) / 2 / m_lTempSnap != (lNewTime + m_lTempSnap) / m_lTempSnap) {
+ for (i = 0; i < lTempSelectedEventArrayCount; i++) {
+ MIDIEvent* pTempEvent = (MIDIEvent*)m_theTempSelectedEventArray.GetAt (i);
+ rcRegion = GetNoteRect (pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ long lTempTime = pTempEvent->m_lUser2;
+ long lTempDuration = pTempEvent->m_lUser3;
+ // 移動又は複写中
+ if (m_lTempMode == 0x0402 || m_lTempMode == 0x0403) {
+ long lDeltaTime =
+ (lNewTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap -
+ (lDownTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap;
+ long lTime = CLIP (0, lTempTime + lDeltaTime, 0x7FFFFFFF);
+ MIDIEvent_SetTime (pTempEvent, lTime);
+ }
+ // 開始時刻の移動中
+ else if (m_lTempMode == 0x0406) {
+ long lDeltaTime = (lNewTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap -
+ m_lTempTimeNoteOn;
+ long lTime = CLIP (0, lTempTime + lDeltaTime, 0x7FFFFFFF);
+ long lDuration = CLIP (1, lTempDuration - lDeltaTime, 65535);
+ MIDIEvent_SetTime (pTempEvent, lTime);
+ MIDIEvent_SetDuration (pTempEvent, lDuration);
+ pPianoRollFrame->SetCurDuration (lDuration);
+ }
+ // 終了時刻の移動中
+ else if (m_lTempMode == 0x0407) {
+ long lDeltaTime = (lNewTime + m_lTempSnap / 2) / m_lTempSnap * m_lTempSnap -
+ m_lTempTimeNoteOn - m_lTempNoteDuration;
+ long lDuration = CLIP (1, lTempDuration + lDeltaTime, 65535);
+ MIDIEvent_SetDuration (pTempEvent, lDuration);
+ pPianoRollFrame->SetCurDuration (lDuration);
+ }
+ rcRegion = GetNoteRect (pTempEvent);
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ }
+ }
+ // 選択範囲移動中
+ else if (m_lTempMode = 0x0401) {
+ // 案B(選択矩形はちらつくが内部はちらつかない)
+ rcRegion = CRect (m_ptMouseDown.x, m_ptMouseDown.y, m_ptMouseMove.x, m_ptMouseDown.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseDown.x, m_ptMouseMove.y, m_ptMouseMove.x, m_ptMouseMove.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseDown.x, m_ptMouseDown.y, m_ptMouseDown.x, m_ptMouseMove.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseMove.x, m_ptMouseDown.y, m_ptMouseMove.x, m_ptMouseMove.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+
+ rcRegion = CRect (m_ptMouseDown.x, m_ptMouseDown.y, point.x, m_ptMouseDown.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseDown.x, point.y, point.x, point.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (m_ptMouseDown.x, m_ptMouseDown.y, m_ptMouseDown.x, point.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ rcRegion = CRect (point.x, m_ptMouseDown.y, point.x, point.y);
+ rcRegion.NormalizeRect ();
+ rcRegion.InflateRect (1, 1);
+ InvalidateRect (rcRegion - sizWndOrg);
+ }
+ break;
+
+ // スクラブ
+ case ID_PIANOROLL_SPEAKER:
+ m_lTempTime = pPianoRollFrame->XtoTime (point.x);
+ if (pSekaijuApp->m_thePianoRollOption.m_bSpeakerModeVisibleTrack) {
+ long i = 0;
+ long lTempOutputOn[MAXMIDITRACKNUM];
+ forEachTrack (pMIDIData, pTempTrack) {
+ lTempOutputOn[i] = MIDITrack_GetOutputOn (pTempTrack);
+ MIDITrack_SetOutputOn (pTempTrack, pPianoRollFrame->IsTrackVisible (i));
+ i++;
+ }
+ pSekaijuApp->SetPlayPosition (pSekaijuDoc, m_lTempTime);
+ pSekaijuApp->SendDifferentStatus (SDS_ALL);
+ i = 0;
+ forEachTrack (pMIDIData, pTempTrack) {
+ MIDITrack_SetOutputOn (pTempTrack, lTempOutputOn[i]);
+ i++;
+ }
+ }
+ else {
+ pSekaijuApp->SetPlayPosition (pSekaijuDoc, m_lTempTime);
+ pSekaijuApp->SendDifferentStatus (SDS_ALL);
+ }
+ break;
+ }
+ }
+ // 非キャプター中(カーソルの種類だけ変更)
+ else {
+ long i = 0;
+ BOOL bChanged = FALSE;
+ MIDITrack* pMIDITrack;
+ MIDIEvent* pMIDIEvent;
+ switch (pPianoRollFrame->m_lCurTool) {
+ // 描画
+ case ID_PIANOROLL_PEN:
+ i = MIDIData_CountTrack (pMIDIData) - 1; // 20090629追加
+ forEachTrackInverse (pMIDIData, pMIDITrack) { // 20090629修正
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEventInverse (pMIDITrack, pMIDIEvent) { // 20090629修正
+ if (MIDIEvent_IsNoteOn (pMIDIEvent) && MIDIEvent_IsNote (pMIDIEvent)) {
+ if (MIDIEvent_GetKey (pMIDIEvent) == lNewKey) {
+ long lNoteOnTime = MIDIEvent_GetTime (pMIDIEvent);
+ long lDuration = MIDIEvent_GetDuration (pMIDIEvent);
+ long lNoteOffTime = lNoteOnTime + lDuration;
+ if (lNoteOnTime <= lNewTime && lNewTime < lNoteOnTime + lDuration / 4) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ bChanged = TRUE;
+ break;
+ }
+ else if (lNoteOnTime + lDuration / 4 <= lNewTime &&
+ lNewTime <= lNoteOffTime - lDuration / 4) {
+ if (nFlags & MK_CONTROL) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ else {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ bChanged = TRUE;
+ break;
+ }
+ else if (lNoteOffTime - lDuration / 4 < lNewTime && lNewTime <= lNoteOffTime) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ bChanged = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (bChanged) { // 20090629追加
+ break;
+ }
+ }
+ i--;
+ }
+ if (bChanged == FALSE) {
+ ::SetCursor (pSekaijuApp->m_hCursorDraw);
+ }
+ break;
+ // 線
+ case ID_PIANOROLL_LINE:
+ ::SetCursor (pSekaijuApp->m_hCursorLine);
+ break;
+ // 消しゴム
+ case ID_PIANOROLL_ERASER:
+ ::SetCursor (pSekaijuApp->m_hCursorEraser);
+ break;
+ // 選択
+ case ID_PIANOROLL_SELECT:
+ i = 0;
+ forEachTrack (pMIDIData, pMIDITrack) {
+ if (pPianoRollFrame->IsTrackVisible (i)) {
+ forEachEvent (pMIDITrack, pMIDIEvent) {
+ if (pSekaijuDoc->IsEventSelected (pMIDIEvent)) {
+ if (MIDIEvent_IsNoteOn (pMIDIEvent)) {
+ if (MIDIEvent_GetKey (pMIDIEvent) == lNewKey) {
+ long lNoteOnTime = MIDIEvent_GetTime (pMIDIEvent);
+ long lNoteDuration = MIDIEvent_GetDuration (pMIDIEvent);
+ long lNoteOffTime = lNoteOnTime + MIDIEvent_GetDuration (pMIDIEvent);
+ if (lNoteOnTime <= lNewTime && lNewTime <= lNoteOffTime) {
+ // 複写
+ if (nFlags & MK_CONTROL) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAllCopy);
+ }
+ // 移動
+ else {
+ if (lNoteOnTime <= lNewTime && lNewTime < lNoteOnTime + lNoteDuration / 4) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ }
+ else if (lNoteOffTime - lNoteDuration / 4 < lNewTime && lNewTime <= lNoteOffTime) {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeWE);
+ }
+ else {
+ ::SetCursor (pSekaijuApp->m_hCursorSizeAll);
+ }
+ }
+ bChanged = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ i++;
+ }
+ if (!bChanged) {
+ ::SetCursor (pSekaijuApp->m_hCursorSelect);
+ }
+ break;
+ // スピーカー
+ case ID_PIANOROLL_SPEAKER:
+ ::SetCursor (pSekaijuApp->m_hCursorSpeaker);
+ break;
+ // 不明
+ default:
+ //::SetCursor (pSekaijuApp->m_hCursorArrow);
+ break;
+ }
+ }
+ m_ptMouseMove = point;
+ m_nMouseMoveFlags = nFlags;
+ pSekaijuDoc->m_theCriticalSection.Unlock ();
+ ::Sleep (0);
+}
+
+// マウスホイールが回された時
+void CPianoRollKeyTimeView::OnMouseWheel40 (UINT nFlags, CPoint point) {
+ CPianoRollFrame* pPianoRollFrame = (CPianoRollFrame*)GetParent ();
+ CSekaijuApp* pSekaijuApp = (CSekaijuApp*)AfxGetApp ();
+ CSekaijuDoc* pSekaijuDoc = GetDocument ();
+ long lDelta = (short)HIWORD (nFlags);
+ long lFlags = LOWORD (nFlags);
+ if (lFlags & MK_CONTROL) {
+ if (lDelta > 0 && pSekaijuApp->m_theGeneralOption.m_bInvertCtrlMouseWheel == 0 ||
+ lDelta < 0 && pSekaijuApp->m_theGeneralOption.m_bInvertCtrlMouseWheel != 0) {
+ pPianoRollFrame->PostMessage (WM_COMMAND, ID_CONTROL_PREVMEASURE);
+ }
+ else {
+ pPianoRollFrame->PostMessage (WM_COMMAND, ID_CONTROL_NEXTMEASURE);
+ }
+ }
+ else {
+ long lKeyScrollPos = pPianoRollFrame->GetKeyScrollPos ();
+ long lKeyZoom = pPianoRollFrame->GetKeyZoom ();
+ lKeyScrollPos -= lKeyZoom * lDelta / WHEELDELTA;
+ pPianoRollFrame->SetKeyScrollPos (lKeyScrollPos);
+ }
+}