PianoKeys.cpp
上传用户:fs3633
上传日期:2021-05-14
资源大小:909k
文件大小:14k
- /*
- PianoKeys.cpp
- This class represents the implementation of the CPianoKey derived
- classes.
- Copyright (C) 2002 Leslie Sanford
- 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
- Contact: Leslie Sanford (jabberdabber@hotmail.com)
- Last modified: 12/14/2002
- */
- //---------------------------------------------------------------------
- // Dependencies
- //---------------------------------------------------------------------
- #include <afxwin.h>
- #include "PianoCtrl.h"
- //---------------------------------------------------------------------
- // Constants
- //---------------------------------------------------------------------
- // The width of the black keys as a percentage of the width of the
- // white keys 白色琴键和黑色琴键的百分比
- const double CPianoCtrl::CPianoKey::BLACK_KEY_OFFSET = 0.7;
- // The number of units natural keys use in their widest part.
- const int CPianoCtrl::CPianoKey::UNIT_PER_NAT_KEY = 3;
- //---------------------------------------------------------------------
- // CWhiteKeyLeft class implementation
- //---------------------------------------------------------------------
- // Constructor 构造器
- CPianoCtrl::CWhiteKeyLeft::CWhiteKeyLeft(double UnitLength, int Width,
- double Position)
- {
- // Initialize upper portion of this key 初始化上面一部分的琴键
- m_UpperRect.top = 0;
- m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_UpperRect.left = static_cast<long>(Position);
- m_UpperRect.right = static_cast<long>
- (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
- // Initialize lower portion of this key 初始化下面一部分的琴键
- m_LowerRect.top = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_LowerRect.bottom = Width - 1;
- m_LowerRect.left = static_cast<long>(Position);
- m_LowerRect.right = static_cast<long>
- (Position + UnitLength * UNIT_PER_NAT_KEY);
- }
- // Hit detection 弹奏探测
- bool CPianoCtrl::CWhiteKeyLeft::IsPointInKey(const CPoint &pt) const
- {
- return (IsPointInRect(pt, m_UpperRect) ||
- IsPointInRect(pt, m_LowerRect));
- }
- // Turns note on 开启音符
- void CPianoCtrl::CWhiteKeyLeft::NoteOn(COLORREF NoteOnColor,
- CRect &Rect)
- {
- m_NoteOnFlag = true;
- m_NoteOnColor = NoteOnColor;
- CalcInvalidRect(Rect);
- }
- // Turns note off 关闭音符
- void CPianoCtrl::CWhiteKeyLeft::NoteOff(CRect &Rect)
- {
- m_NoteOnFlag = false;
- CalcInvalidRect(Rect);
- }
- // Paints the key 绘制琴键
- void CPianoCtrl::CWhiteKeyLeft::Paint(CDC *dc)
- {
- //
- // Fill key
- //
- // Note is on 判断音符有没有开启
- if(m_NoteOnFlag)
- {
- dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
- dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
- }
- // Note is off 判断音符是不是关闭的
- else
- {
- dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
- dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
- }
- dc->SelectStockObject(BLACK_PEN);
- //
- // Draw border 绘制界线
- //
- // Left side 左边的
- dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
- dc->LineTo(m_UpperRect.left, m_LowerRect.bottom);
- // Bottom 底部的界线
- dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
- // Right side 右边的界线
- dc->LineTo(m_LowerRect.right, m_LowerRect.top);
- dc->LineTo(m_UpperRect.right, m_UpperRect.bottom);
- dc->LineTo(m_UpperRect.right, m_UpperRect.top);
- // Top 顶部的界线
- dc->LineTo(m_UpperRect.left, m_UpperRect.top);
-
- }
- // Calculate the rectangular area to invalidate for this key
- //计算这个长方形的范围,并且让上面的琴键无效化
- void CPianoCtrl::CWhiteKeyLeft::CalcInvalidRect(CRect &Rect)
- {
- Rect.top = m_UpperRect.top;
- Rect.bottom = m_LowerRect.bottom;
- Rect.left = m_UpperRect.left;
- Rect.right = m_LowerRect.right;
- }
- //---------------------------------------------------------------------
- // CWhiteKeyMiddle class implementation
- //---------------------------------------------------------------------
- // Constructor 构造器
- CPianoCtrl::CWhiteKeyMiddle::CWhiteKeyMiddle(double UnitLength,
- int Width, double Position)
- {
- // Initialize upper portion of this key 初始化上部分琴键
- m_UpperRect.top = 0;
- m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_UpperRect.left = static_cast<long>(Position + UnitLength);
- m_UpperRect.right = static_cast<long>
- (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
- // Initialize lower portion of this key 初始化下部分琴键
- m_LowerRect.top = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_LowerRect.bottom = Width - 1;
- m_LowerRect.left = static_cast<long>(Position);
- m_LowerRect.right = static_cast<long>
- (Position + UnitLength * UNIT_PER_NAT_KEY);
- }
- // Hit detection 弹奏检测
- bool CPianoCtrl::CWhiteKeyMiddle::IsPointInKey(const CPoint &pt) const
- {
- return (IsPointInRect(pt, m_UpperRect) ||
- IsPointInRect(pt, m_LowerRect));
- }
- // Turns note on 开启音符
- void CPianoCtrl::CWhiteKeyMiddle::NoteOn(COLORREF NoteOnColor,
- CRect &Rect)
- {
- m_NoteOnFlag = true;
- m_NoteOnColor = NoteOnColor;
- CalcInvalidRect(Rect);
-
- }
- // Turns note off 关闭音符
- void CPianoCtrl::CWhiteKeyMiddle::NoteOff(CRect &Rect)
- {
- m_NoteOnFlag = false;
- CalcInvalidRect(Rect);
- }
- // Paints key 绘制琴键
- void CPianoCtrl::CWhiteKeyMiddle::Paint(CDC *dc)
- {
- //
- // Fill key
- //
- // Note is on 判断音符是不是开启了
- if(m_NoteOnFlag)
- {
- dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
- dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
- }
- // Note is off 否则就是关闭的
- else
- {
- dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
- dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
- }
- dc->SelectStockObject(BLACK_PEN);
- //
- // Draw border 绘制界线
- //
- // Left side 左边的界线
- dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
- dc->LineTo(m_UpperRect.left, m_UpperRect.bottom);
- dc->LineTo(m_LowerRect.left, m_LowerRect.top);
- dc->LineTo(m_LowerRect.left, m_LowerRect.bottom);
- // Bottom 底布的界线
- dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
- // Right side 右边的界线
- dc->LineTo(m_LowerRect.right, m_LowerRect.top);
- dc->LineTo(m_UpperRect.right, m_UpperRect.bottom);
- dc->LineTo(m_UpperRect.right, m_UpperRect.top);
- // Top 顶部的界线
- dc->LineTo(m_UpperRect.left, m_UpperRect.top);
- }
- // Calculate rectangular area to invalidate for this key
- void CPianoCtrl::CWhiteKeyMiddle::CalcInvalidRect(CRect &Rect)
- {
- Rect.top = m_UpperRect.top;
- Rect.bottom = m_LowerRect.bottom;
- Rect.left = m_LowerRect.left;
- Rect.right = m_LowerRect.right;
- }
- //---------------------------------------------------------------------
- // CWhiteKeyRight class implementation
- //---------------------------------------------------------------------
- // Constructor
- CPianoCtrl::CWhiteKeyRight::CWhiteKeyRight(double UnitLength, int Width,
- double Position)
- {
- // Initialize upper portion of this key
- m_UpperRect.top = 0;
- m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_UpperRect.left = static_cast<long>(Position + UnitLength);
- m_UpperRect.right = static_cast<long>
- (Position + UnitLength * UNIT_PER_NAT_KEY);
- // Initialize lower portion of this key
- m_LowerRect.top = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_LowerRect.bottom = Width - 1;
- m_LowerRect.left = static_cast<long>(Position);
- m_LowerRect.right = static_cast<long>
- (Position + UnitLength * UNIT_PER_NAT_KEY);
- }
- // Hit detection
- bool CPianoCtrl::CWhiteKeyRight::IsPointInKey(const CPoint &pt) const
- {
- return (IsPointInRect(pt, m_UpperRect) ||
- IsPointInRect(pt, m_LowerRect));
- }
- // Turns note on
- void CPianoCtrl::CWhiteKeyRight::NoteOn(COLORREF NoteOnColor,
- CRect &Rect)
- {
- m_NoteOnFlag = true;
- m_NoteOnColor = NoteOnColor;
- CalcInvalidRect(Rect);
- }
- // Turns note off
- void CPianoCtrl::CWhiteKeyRight::NoteOff(CRect &Rect)
- {
- m_NoteOnFlag = false;
- CalcInvalidRect(Rect);
- }
- // Paints key
- void CPianoCtrl::CWhiteKeyRight::Paint(CDC *dc)
- {
- //
- // Fill key
- //
- // Note is on
- if(m_NoteOnFlag)
- {
- dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
- dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
- }
- // Note is off
- else
- {
- dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
- dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
- }
- dc->SelectStockObject(BLACK_PEN);
- //
- // Draw border
- //
- // Left side
- dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
- dc->LineTo(m_UpperRect.left, m_UpperRect.bottom);
- dc->LineTo(m_LowerRect.left, m_LowerRect.top);
- dc->LineTo(m_LowerRect.left, m_LowerRect.bottom);
- // Bottom
- dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
- // Right side
- dc->LineTo(m_LowerRect.right, m_UpperRect.top);
- // Top
- dc->LineTo(m_UpperRect.left, m_UpperRect.top);
- }
- // Calculates rectangular area to invalidate for this key
- void CPianoCtrl::CWhiteKeyRight::CalcInvalidRect(CRect &Rect)
- {
- Rect.top = m_UpperRect.top;
- Rect.bottom = m_LowerRect.bottom;
- Rect.left = m_LowerRect.left;
- Rect.right = m_LowerRect.right;
- }
- //---------------------------------------------------------------------
- // CWhiteKeyFull class implementation
- //---------------------------------------------------------------------
- // Constructor
- CPianoCtrl::CWhiteKeyFull::CWhiteKeyFull(double UnitLength, int Width,
- double Position)
- {
- // Initialize this key's rectangular area
- m_Rect.top = 0;
- m_Rect.bottom = Width - 1;
- m_Rect.left = static_cast<long>(Position);
- m_Rect.right =
- static_cast<long>(Position + UnitLength * UNIT_PER_NAT_KEY);
- }
- // Hit detection
- bool CPianoCtrl::CWhiteKeyFull::IsPointInKey(const CPoint &pt) const
- {
- return (IsPointInRect(pt, m_Rect));
- }
- // Turns note on
- void CPianoCtrl::CWhiteKeyFull::NoteOn(COLORREF NoteOnColor, CRect &Rect)
- {
- m_NoteOnFlag = true;
- m_NoteOnColor = NoteOnColor;
- Rect = m_Rect;
-
- }
- // Turns note off
- void CPianoCtrl::CWhiteKeyFull::NoteOff(CRect &Rect)
- {
- m_NoteOnFlag = false;
- Rect = m_Rect;
- }
- // Paints this key
- void CPianoCtrl::CWhiteKeyFull::Paint(CDC *dc)
- {
- //
- // Fill key
- //
- // Note is on
- if(m_NoteOnFlag)
- {
- dc->FillSolidRect(&m_Rect, m_NoteOnColor);
- }
- // Note is off
- else
- {
- dc->FillSolidRect(&m_Rect, RGB(250, 250, 250));
- }
- dc->SelectStockObject(BLACK_PEN);
- //
- // Draw border
- //
- // Left side
- dc->MoveTo(m_Rect.left, m_Rect.top);
- dc->LineTo(m_Rect.left, m_Rect.bottom);
- // Bottom
- dc->LineTo(m_Rect.right, m_Rect.bottom);
- // Right side
- dc->LineTo(m_Rect.right, m_Rect.top);
- // Top
- dc->LineTo(m_Rect.left, m_Rect.top);
- }
- //---------------------------------------------------------------------
- // CBlackKey class implementation
- //---------------------------------------------------------------------
- // Constructor
- CPianoCtrl::CBlackKey::CBlackKey(double UnitLength, int Width,
- double Position)
- {
- // Initialize this key's rectangular area
- m_Rect.top = 0;
- m_Rect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
- m_Rect.left = static_cast<long>(Position);
- m_Rect.right = static_cast<long>
- (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
- }
- // Hit detection
- bool CPianoCtrl::CBlackKey::IsPointInKey(const CPoint &pt) const
- {
- return (IsPointInRect(pt, m_Rect));
- }
- // Turns note on
- void CPianoCtrl::CBlackKey::NoteOn(COLORREF NoteOnColor, CRect &Rect)
- {
- m_NoteOnFlag = true;
- m_NoteOnColor = NoteOnColor;
- Rect = m_Rect;
- }
- // Turns note off
- void CPianoCtrl::CBlackKey::NoteOff(CRect &Rect)
- {
- m_NoteOnFlag = false;
- Rect = m_Rect;
- }
- // Paints this key
- void CPianoCtrl::CBlackKey::Paint(CDC *dc)
- {
- //
- // Fill key
- //
- // Note is on
- if(m_NoteOnFlag)
- {
- dc->FillSolidRect(&m_Rect, m_NoteOnColor);
- }
- // Note is off
- else
- {
- dc->FillSolidRect(&m_Rect, RGB(0, 0, 0));
- }
- dc->SelectStockObject(BLACK_PEN);
- //
- // Draw border
- //
- // Left side
- dc->MoveTo(m_Rect.left, m_Rect.top);
- dc->LineTo(m_Rect.left, m_Rect.bottom);
- // Bottom
- dc->LineTo(m_Rect.right, m_Rect.bottom);
- // Right side
- dc->LineTo(m_Rect.right, m_Rect.top);
- // Top
- dc->LineTo(m_Rect.left, m_Rect.top);
- }