PianoKeys.cpp
上传用户:fs3633
上传日期:2021-05-14
资源大小:909k
文件大小:14k
源码类别:

midi

开发平台:

Visual C++

  1. /*
  2.   PianoKeys.cpp
  3.   This class represents the implementation of the CPianoKey derived 
  4.   classes.
  5.   Copyright (C) 2002 Leslie Sanford
  6.   This library is free software; you can redistribute it and/or
  7.   modify it under the terms of the GNU Lesser General Public
  8.   License as published by the Free Software Foundation; either
  9.   version 2.1 of the License, or (at your option) any later version.
  10.   This library is distributed in the hope that it will be useful,
  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.   Lesser General Public License for more details.
  14.   You should have received a copy of the GNU Lesser General Public
  15.   License along with this library; if not, write to the Free Software
  16.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
  17.   USA
  18.   Contact: Leslie Sanford (jabberdabber@hotmail.com)
  19.   Last modified: 12/14/2002
  20. */
  21. //---------------------------------------------------------------------
  22. // Dependencies
  23. //---------------------------------------------------------------------
  24. #include <afxwin.h>
  25. #include "PianoCtrl.h"
  26. //---------------------------------------------------------------------
  27. // Constants
  28. //---------------------------------------------------------------------
  29. // The width of the black keys as a percentage of the width of the 
  30. // white keys 白色琴键和黑色琴键的百分比
  31. const double CPianoCtrl::CPianoKey::BLACK_KEY_OFFSET = 0.7;
  32. // The number of units natural keys use in their widest part.
  33. const int CPianoCtrl::CPianoKey::UNIT_PER_NAT_KEY = 3;
  34. //---------------------------------------------------------------------
  35. // CWhiteKeyLeft class implementation
  36. //---------------------------------------------------------------------
  37. // Constructor 构造器
  38. CPianoCtrl::CWhiteKeyLeft::CWhiteKeyLeft(double UnitLength, int Width, 
  39.                                          double Position)
  40. {
  41.     // Initialize upper portion of this key 初始化上面一部分的琴键
  42.     m_UpperRect.top    = 0;
  43.     m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
  44.     m_UpperRect.left   = static_cast<long>(Position);
  45.     m_UpperRect.right  = static_cast<long>
  46.         (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
  47.     // Initialize lower portion of this key 初始化下面一部分的琴键
  48.     m_LowerRect.top    = static_cast<long>(Width * BLACK_KEY_OFFSET);
  49.     m_LowerRect.bottom = Width - 1;
  50.     m_LowerRect.left   = static_cast<long>(Position);
  51.     m_LowerRect.right  = static_cast<long>
  52.         (Position + UnitLength * UNIT_PER_NAT_KEY);
  53. }
  54. // Hit detection 弹奏探测
  55. bool CPianoCtrl::CWhiteKeyLeft::IsPointInKey(const CPoint &pt) const
  56. {
  57.     return (IsPointInRect(pt, m_UpperRect) || 
  58.             IsPointInRect(pt, m_LowerRect));
  59. }
  60. // Turns note on 开启音符
  61. void CPianoCtrl::CWhiteKeyLeft::NoteOn(COLORREF NoteOnColor, 
  62.                                        CRect &Rect)
  63. {
  64.     m_NoteOnFlag = true;
  65.     m_NoteOnColor = NoteOnColor;
  66.     CalcInvalidRect(Rect);
  67. }
  68. // Turns note off 关闭音符
  69. void CPianoCtrl::CWhiteKeyLeft::NoteOff(CRect &Rect)
  70. {
  71.     m_NoteOnFlag = false;
  72.     CalcInvalidRect(Rect);
  73. }
  74. // Paints the key 绘制琴键
  75. void CPianoCtrl::CWhiteKeyLeft::Paint(CDC *dc)
  76. {
  77.     //
  78.     // Fill key
  79.     //
  80.     // Note is on 判断音符有没有开启
  81.     if(m_NoteOnFlag)
  82.     {
  83.         dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
  84.         dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
  85.     }
  86.     // Note is off 判断音符是不是关闭的
  87.     else
  88.     {
  89.         dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
  90.         dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
  91.     }
  92.     dc->SelectStockObject(BLACK_PEN);
  93.     // 
  94.     // Draw border 绘制界线
  95.     //
  96.     // Left side 左边的
  97.     dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
  98.     dc->LineTo(m_UpperRect.left, m_LowerRect.bottom);
  99.     // Bottom 底部的界线
  100.     dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
  101.     // Right side 右边的界线
  102.     dc->LineTo(m_LowerRect.right, m_LowerRect.top);
  103.     dc->LineTo(m_UpperRect.right, m_UpperRect.bottom);
  104.     dc->LineTo(m_UpperRect.right, m_UpperRect.top);
  105.     // Top 顶部的界线
  106.     dc->LineTo(m_UpperRect.left, m_UpperRect.top);
  107.     
  108. }
  109. // Calculate the rectangular area to invalidate for this key
  110. //计算这个长方形的范围,并且让上面的琴键无效化
  111. void CPianoCtrl::CWhiteKeyLeft::CalcInvalidRect(CRect &Rect)
  112. {
  113.     Rect.top    = m_UpperRect.top;
  114.     Rect.bottom = m_LowerRect.bottom;
  115.     Rect.left   = m_UpperRect.left;
  116.     Rect.right  = m_LowerRect.right;
  117. }
  118. //---------------------------------------------------------------------
  119. // CWhiteKeyMiddle class implementation
  120. //---------------------------------------------------------------------
  121. // Constructor 构造器
  122. CPianoCtrl::CWhiteKeyMiddle::CWhiteKeyMiddle(double UnitLength, 
  123.                                              int Width, double Position)
  124. {
  125.     // Initialize upper portion of this key 初始化上部分琴键
  126.     m_UpperRect.top    = 0;
  127.     m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
  128.     m_UpperRect.left   = static_cast<long>(Position + UnitLength);
  129.     m_UpperRect.right  = static_cast<long>
  130.         (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
  131.     // Initialize lower portion of this key 初始化下部分琴键
  132.     m_LowerRect.top    = static_cast<long>(Width * BLACK_KEY_OFFSET);
  133.     m_LowerRect.bottom = Width - 1;
  134.     m_LowerRect.left   = static_cast<long>(Position);
  135.     m_LowerRect.right  = static_cast<long>
  136.         (Position + UnitLength * UNIT_PER_NAT_KEY);
  137. }
  138. // Hit detection 弹奏检测
  139. bool CPianoCtrl::CWhiteKeyMiddle::IsPointInKey(const CPoint &pt) const
  140. {
  141.     return (IsPointInRect(pt, m_UpperRect) || 
  142.             IsPointInRect(pt, m_LowerRect));
  143. }
  144. // Turns note on 开启音符
  145. void CPianoCtrl::CWhiteKeyMiddle::NoteOn(COLORREF NoteOnColor, 
  146.                                          CRect &Rect)
  147. {
  148.     m_NoteOnFlag = true;
  149.     m_NoteOnColor = NoteOnColor;
  150.     CalcInvalidRect(Rect);
  151.     
  152. }
  153. // Turns note off 关闭音符
  154. void CPianoCtrl::CWhiteKeyMiddle::NoteOff(CRect &Rect)
  155. {
  156.     m_NoteOnFlag = false;
  157.     CalcInvalidRect(Rect);
  158. }
  159. // Paints key 绘制琴键
  160. void CPianoCtrl::CWhiteKeyMiddle::Paint(CDC *dc)
  161. {
  162.     //
  163.     // Fill key
  164.     //
  165.     // Note is on 判断音符是不是开启了
  166.     if(m_NoteOnFlag)
  167.     {
  168.         dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
  169.         dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
  170.     }
  171.     // Note is off 否则就是关闭的
  172.     else
  173.     {
  174.         dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
  175.         dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
  176.     }
  177.     dc->SelectStockObject(BLACK_PEN);
  178.     // 
  179.     // Draw border 绘制界线
  180.     //
  181.     // Left side 左边的界线
  182.     dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
  183.     dc->LineTo(m_UpperRect.left, m_UpperRect.bottom);
  184.     dc->LineTo(m_LowerRect.left, m_LowerRect.top);
  185.     dc->LineTo(m_LowerRect.left, m_LowerRect.bottom);
  186.     // Bottom 底布的界线
  187.     dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
  188.     // Right side 右边的界线
  189.     dc->LineTo(m_LowerRect.right, m_LowerRect.top);
  190.     dc->LineTo(m_UpperRect.right, m_UpperRect.bottom);
  191.     dc->LineTo(m_UpperRect.right, m_UpperRect.top);
  192.     // Top  顶部的界线
  193.     dc->LineTo(m_UpperRect.left, m_UpperRect.top);
  194. }
  195. // Calculate rectangular area to invalidate for this key
  196. void CPianoCtrl::CWhiteKeyMiddle::CalcInvalidRect(CRect &Rect)
  197. {
  198.     Rect.top    = m_UpperRect.top;
  199.     Rect.bottom = m_LowerRect.bottom;
  200.     Rect.left   = m_LowerRect.left;
  201.     Rect.right  = m_LowerRect.right;
  202. }
  203. //---------------------------------------------------------------------
  204. // CWhiteKeyRight class implementation
  205. //---------------------------------------------------------------------
  206. // Constructor
  207. CPianoCtrl::CWhiteKeyRight::CWhiteKeyRight(double UnitLength, int Width, 
  208.                                            double Position)
  209. {
  210.     // Initialize upper portion of this key
  211.     m_UpperRect.top    = 0;
  212.     m_UpperRect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
  213.     m_UpperRect.left   = static_cast<long>(Position + UnitLength);
  214.     m_UpperRect.right  = static_cast<long>
  215.         (Position + UnitLength * UNIT_PER_NAT_KEY);
  216.     // Initialize lower portion of this key
  217.     m_LowerRect.top    = static_cast<long>(Width * BLACK_KEY_OFFSET);
  218.     m_LowerRect.bottom = Width - 1;
  219.     m_LowerRect.left   = static_cast<long>(Position);
  220.     m_LowerRect.right  = static_cast<long>
  221.         (Position + UnitLength * UNIT_PER_NAT_KEY);
  222. }
  223. // Hit detection
  224. bool CPianoCtrl::CWhiteKeyRight::IsPointInKey(const CPoint &pt) const
  225. {
  226.     return (IsPointInRect(pt, m_UpperRect) || 
  227.             IsPointInRect(pt, m_LowerRect));
  228. }
  229. // Turns note on
  230. void CPianoCtrl::CWhiteKeyRight::NoteOn(COLORREF NoteOnColor, 
  231.                                         CRect &Rect)
  232. {
  233.     m_NoteOnFlag = true;
  234.     m_NoteOnColor = NoteOnColor;
  235.     CalcInvalidRect(Rect);
  236. }
  237. // Turns note off
  238. void CPianoCtrl::CWhiteKeyRight::NoteOff(CRect &Rect)
  239. {
  240.     m_NoteOnFlag = false;
  241.     CalcInvalidRect(Rect);
  242. }
  243. // Paints key
  244. void CPianoCtrl::CWhiteKeyRight::Paint(CDC *dc)
  245. {
  246.     //
  247.     // Fill key
  248.     //
  249.     // Note is on
  250.     if(m_NoteOnFlag)
  251.     {
  252.         dc->FillSolidRect(&m_UpperRect, m_NoteOnColor);
  253.         dc->FillSolidRect(&m_LowerRect, m_NoteOnColor);
  254.     }
  255.     // Note is off
  256.     else
  257.     {
  258.         dc->FillSolidRect(&m_UpperRect, RGB(250, 250, 250));
  259.         dc->FillSolidRect(&m_LowerRect, RGB(250, 250, 250));
  260.     }
  261.     dc->SelectStockObject(BLACK_PEN);
  262.     // 
  263.     // Draw border
  264.     //
  265.     // Left side
  266.     dc->MoveTo(m_UpperRect.left, m_UpperRect.top);
  267.     dc->LineTo(m_UpperRect.left, m_UpperRect.bottom);
  268.     dc->LineTo(m_LowerRect.left, m_LowerRect.top);
  269.     dc->LineTo(m_LowerRect.left, m_LowerRect.bottom);
  270.     // Bottom
  271.     dc->LineTo(m_LowerRect.right, m_LowerRect.bottom);
  272.     // Right side
  273.     dc->LineTo(m_LowerRect.right, m_UpperRect.top);
  274.     // Top
  275.     dc->LineTo(m_UpperRect.left, m_UpperRect.top);
  276. }
  277. // Calculates rectangular area to invalidate for this key
  278. void CPianoCtrl::CWhiteKeyRight::CalcInvalidRect(CRect &Rect)
  279. {
  280.     Rect.top    = m_UpperRect.top;
  281.     Rect.bottom = m_LowerRect.bottom;
  282.     Rect.left   = m_LowerRect.left;
  283.     Rect.right  = m_LowerRect.right;
  284. }
  285. //---------------------------------------------------------------------
  286. // CWhiteKeyFull class implementation
  287. //---------------------------------------------------------------------
  288. // Constructor
  289. CPianoCtrl::CWhiteKeyFull::CWhiteKeyFull(double UnitLength, int Width, 
  290.                                          double Position)
  291. {
  292.     // Initialize this key's rectangular area
  293.     m_Rect.top    = 0;
  294.     m_Rect.bottom = Width - 1;
  295.     m_Rect.left   = static_cast<long>(Position);
  296.     m_Rect.right  = 
  297.         static_cast<long>(Position + UnitLength * UNIT_PER_NAT_KEY);
  298. }
  299. // Hit detection
  300. bool CPianoCtrl::CWhiteKeyFull::IsPointInKey(const CPoint &pt) const
  301. {
  302.     return (IsPointInRect(pt, m_Rect));
  303. }
  304. // Turns note on
  305. void CPianoCtrl::CWhiteKeyFull::NoteOn(COLORREF NoteOnColor, CRect &Rect)
  306. {
  307.     m_NoteOnFlag = true;
  308.     m_NoteOnColor = NoteOnColor;
  309.     Rect = m_Rect;
  310.     
  311. }
  312. // Turns note off
  313. void CPianoCtrl::CWhiteKeyFull::NoteOff(CRect &Rect)
  314. {
  315.     m_NoteOnFlag = false;
  316.     Rect = m_Rect;
  317. }
  318. // Paints this key
  319. void CPianoCtrl::CWhiteKeyFull::Paint(CDC *dc)
  320. {
  321.     //
  322.     // Fill key
  323.     //
  324.     // Note is on
  325.     if(m_NoteOnFlag)
  326.     {
  327.         dc->FillSolidRect(&m_Rect, m_NoteOnColor);
  328.     }
  329.     // Note is off
  330.     else
  331.     {
  332.         dc->FillSolidRect(&m_Rect, RGB(250, 250, 250));
  333.     }
  334.     dc->SelectStockObject(BLACK_PEN);
  335.     // 
  336.     // Draw border
  337.     //
  338.     // Left side
  339.     dc->MoveTo(m_Rect.left, m_Rect.top);
  340.     dc->LineTo(m_Rect.left, m_Rect.bottom);
  341.     // Bottom
  342.     dc->LineTo(m_Rect.right, m_Rect.bottom);
  343.     // Right side
  344.     dc->LineTo(m_Rect.right, m_Rect.top);
  345.     // Top
  346.     dc->LineTo(m_Rect.left, m_Rect.top);
  347. }
  348. //---------------------------------------------------------------------
  349. // CBlackKey class implementation
  350. //---------------------------------------------------------------------
  351. // Constructor
  352. CPianoCtrl::CBlackKey::CBlackKey(double UnitLength, int Width, 
  353.                                  double Position)
  354. {
  355.     // Initialize this key's rectangular area
  356.     m_Rect.top    = 0;
  357.     m_Rect.bottom = static_cast<long>(Width * BLACK_KEY_OFFSET);
  358.     m_Rect.left   = static_cast<long>(Position);
  359.     m_Rect.right  = static_cast<long>
  360.         (Position + UnitLength * (UNIT_PER_NAT_KEY - 1));
  361. }
  362. // Hit detection
  363. bool CPianoCtrl::CBlackKey::IsPointInKey(const CPoint &pt) const
  364. {
  365.     return (IsPointInRect(pt, m_Rect));
  366. }
  367. // Turns note on
  368. void CPianoCtrl::CBlackKey::NoteOn(COLORREF NoteOnColor, CRect &Rect)
  369. {
  370.     m_NoteOnFlag = true;
  371.     m_NoteOnColor = NoteOnColor;
  372.     Rect = m_Rect;
  373. }
  374. // Turns note off
  375. void CPianoCtrl::CBlackKey::NoteOff(CRect &Rect)
  376. {
  377.     m_NoteOnFlag = false;
  378.     Rect = m_Rect;
  379. }
  380. // Paints this key
  381. void CPianoCtrl::CBlackKey::Paint(CDC *dc)
  382. {
  383.     //
  384.     // Fill key
  385.     //
  386.     // Note is on
  387.     if(m_NoteOnFlag)
  388.     {
  389.         dc->FillSolidRect(&m_Rect, m_NoteOnColor);
  390.     }
  391.     // Note is off
  392.     else
  393.     {
  394.         dc->FillSolidRect(&m_Rect, RGB(0, 0, 0));
  395.     }
  396.     dc->SelectStockObject(BLACK_PEN);
  397.     // 
  398.     // Draw border
  399.     //
  400.     // Left side
  401.     dc->MoveTo(m_Rect.left, m_Rect.top);
  402.     dc->LineTo(m_Rect.left, m_Rect.bottom);
  403.     // Bottom
  404.     dc->LineTo(m_Rect.right, m_Rect.bottom);
  405.     // Right side
  406.     dc->LineTo(m_Rect.right, m_Rect.top);
  407.     // Top
  408.     dc->LineTo(m_Rect.left, m_Rect.top);
  409. }