326 lines
8.5 KiB
C++
326 lines
8.5 KiB
C++
//---------------------------------------------------------------------------
|
|
|
|
#pragma hdrstop
|
|
|
|
#include "KeyBoard.h"
|
|
//---------------------------------------------------------------------------
|
|
#pragma package(smart_init)
|
|
|
|
__fastcall TKeyBoard::TKeyBoard(TComponent* Owner)
|
|
: Vcl::Extctrls::TPanel(Owner)
|
|
{
|
|
Height = 145;
|
|
Width = 430;
|
|
Left = 150;
|
|
Top = 500;
|
|
|
|
m_pBmpWhiteDDown = new TBitmap();
|
|
m_pBmpWhiteDDown->LoadFromResourceName(int(HInstance), "KBWhiteDDown");
|
|
m_pBmpWhiteLDown = new TBitmap();
|
|
m_pBmpWhiteLDown->LoadFromResourceName(int(HInstance), "KBWhiteLDown");
|
|
m_pBmpWhiteRDown = new TBitmap();
|
|
m_pBmpWhiteRDown->LoadFromResourceName(int(HInstance), "KBWhiteRDown");
|
|
m_pBmpBlackDown = new TBitmap();
|
|
m_pBmpBlackDown->LoadFromResourceName(int(HInstance), "KBBlackDown");
|
|
m_nBlackWidth = m_pBmpBlackDown->Width;
|
|
m_nBlackHeight = m_pBmpBlackDown->Height;
|
|
m_nWhiteWidth = m_pBmpWhiteDDown->Width;
|
|
m_nGroupWidth = m_nWhiteWidth * 7;
|
|
|
|
m_aBlackHitTest[0].x1 = 12;
|
|
m_aBlackHitTest[0].iKey = 1;
|
|
m_aBlackHitTest[1].x1 = 32;
|
|
m_aBlackHitTest[1].iKey = 3;
|
|
m_aBlackHitTest[2].x1 = 72;
|
|
m_aBlackHitTest[2].iKey = 6;
|
|
m_aBlackHitTest[3].x1 = 92;
|
|
m_aBlackHitTest[3].iKey = 8;
|
|
m_aBlackHitTest[4].x1 = 112;
|
|
m_aBlackHitTest[4].iKey = 10;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
m_aBlackHitTest[i].x2 = m_aBlackHitTest[i].x1 + m_pBmpBlackDown->Width;
|
|
|
|
m_aKey[0].xPos = -1;
|
|
m_aKey[0].pBmp = m_pBmpWhiteRDown;
|
|
m_aKey[1].xPos = 12;
|
|
m_aKey[1].pBmp = m_pBmpBlackDown;
|
|
m_aKey[2].xPos = 19;
|
|
m_aKey[2].pBmp = m_pBmpWhiteDDown;
|
|
m_aKey[3].xPos = 32;
|
|
m_aKey[3].pBmp = m_pBmpBlackDown;
|
|
m_aKey[4].xPos = 39;
|
|
m_aKey[4].pBmp = m_pBmpWhiteLDown;
|
|
m_aKey[5].xPos = 59;
|
|
m_aKey[5].pBmp = m_pBmpWhiteRDown;
|
|
m_aKey[6].xPos = 72;
|
|
m_aKey[6].pBmp = m_pBmpBlackDown;
|
|
m_aKey[7].xPos = 79;
|
|
m_aKey[7].pBmp = m_pBmpWhiteDDown;
|
|
m_aKey[8].xPos = 92;
|
|
m_aKey[8].pBmp = m_pBmpBlackDown;
|
|
m_aKey[9].xPos = 99;
|
|
m_aKey[9].pBmp = m_pBmpWhiteDDown;
|
|
m_aKey[10].xPos = 112;
|
|
m_aKey[10].pBmp = m_pBmpBlackDown;
|
|
m_aKey[11].xPos = 119;
|
|
m_aKey[11].pBmp = m_pBmpWhiteLDown;
|
|
|
|
m_iPressGroup = m_iPressKey = -1;
|
|
|
|
//背景
|
|
m_ImgBrk = new TPngImage();
|
|
m_ImgBrk->LoadFromResourceName(int(HInstance), "KeyBoard");
|
|
|
|
m_imgKeyboard = new TImage(this);
|
|
m_imgKeyboard->Parent = this;
|
|
m_imgKeyboard->Picture->Assign(m_ImgBrk);
|
|
m_imgKeyboard->Left = 0;
|
|
m_imgKeyboard->Top = 0;
|
|
m_imgKeyboard->Width = Width;
|
|
m_imgKeyboard->Height = Height;
|
|
|
|
m_imgKeyboard->Visible = true;
|
|
|
|
//PaintBox
|
|
m_pbKeyboard = new TPaintBox(this);
|
|
m_pbKeyboard->Parent = this;
|
|
m_pbKeyboard->Left = 6;
|
|
m_pbKeyboard->Top = 19; // Will be Change!
|
|
m_pbKeyboard->Width = 420;
|
|
m_pbKeyboard->Height = 121;
|
|
m_pbKeyboard->OnPaint = KeyboardPaint;
|
|
m_pbKeyboard->OnMouseDown = KeyboardMouseDown;
|
|
m_pbKeyboard->OnMouseEnter = KeyboardMouseEnter;
|
|
m_pbKeyboard->OnMouseLeave = KeyboardMouseLeave;
|
|
m_pbKeyboard->OnMouseMove = KeyboardMouseMove;
|
|
m_pbKeyboard->OnMouseUp = KeyboardMouseUp;
|
|
m_pbKeyboard->Visible = true;
|
|
|
|
//PNG Close
|
|
m_ImgClose = new TPngImage();
|
|
m_ImgClose->LoadFromResourceName(int(HInstance), "imgClose");
|
|
|
|
m_PngClose = new TPNGButton(this);
|
|
m_PngClose->Parent = this;
|
|
m_PngClose->OnClick = CloseClick;
|
|
m_PngClose->ImgStates = 3;
|
|
m_PngClose->PngImg = m_ImgClose;
|
|
m_PngClose->Top = 0;
|
|
m_PngClose->Left = Width - 23;
|
|
m_PngClose->Visible = true;
|
|
}
|
|
|
|
__fastcall TKeyBoard::~TKeyBoard()
|
|
{
|
|
delete m_PngClose;
|
|
m_PngClose = NULL;
|
|
|
|
delete m_imgKeyboard;
|
|
m_imgKeyboard = NULL;
|
|
|
|
delete m_pbKeyboard;
|
|
m_pbKeyboard = NULL;
|
|
|
|
delete m_pBmpWhiteDDown;
|
|
m_pBmpWhiteDDown = NULL;
|
|
|
|
delete m_pBmpWhiteLDown;
|
|
m_pBmpWhiteLDown = NULL;
|
|
|
|
delete m_pBmpWhiteRDown;
|
|
m_pBmpWhiteRDown = NULL;
|
|
|
|
delete m_pBmpBlackDown;
|
|
m_pBmpBlackDown = NULL;
|
|
|
|
delete m_imgFirst;
|
|
m_imgFirst = NULL;
|
|
|
|
delete m_imgSecond;
|
|
m_imgSecond = NULL;
|
|
|
|
delete m_imgThird;
|
|
m_imgThird = NULL;
|
|
|
|
delete m_imgForth;
|
|
m_imgForth = NULL;
|
|
|
|
delete m_ImgClose; //关闭
|
|
m_ImgClose = NULL;
|
|
|
|
delete m_ImgBrk; //钢琴背景
|
|
m_ImgBrk = NULL;
|
|
}
|
|
|
|
// 模拟键盘相关
|
|
int TKeyBoard::KeyboardGetPressKey(int X, int Y) {
|
|
short iPressKey = -1, iPressGroup = X / m_nGroupWidth;
|
|
int xInGroup = X % m_nGroupWidth;
|
|
|
|
int iWhite = xInGroup / m_nWhiteWidth;
|
|
if (iWhite < 3)
|
|
iPressKey = iWhite * 2;
|
|
else
|
|
iPressKey = iWhite * 2 - 1;
|
|
|
|
if (Y < m_nBlackHeight) {
|
|
for (int i = 0; i < 5; i++) {
|
|
if (xInGroup >= m_aBlackHitTest[i].x1 && xInGroup <
|
|
m_aBlackHitTest[i].x2) {
|
|
iPressKey = m_aBlackHitTest[i].iKey;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return MAKELONG(iPressKey, iPressGroup);
|
|
}
|
|
|
|
|
|
void __fastcall TKeyBoard::KeyboardPaint(TObject *Sender)
|
|
{
|
|
//
|
|
if (m_bKeyDown) {
|
|
int xPos = m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos;
|
|
m_pbKeyboard->Canvas->Draw(xPos, 0, m_aKey[m_iPressKey].pBmp);
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::KeyboardMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift,
|
|
int X, int Y)
|
|
{
|
|
//mouseup
|
|
if (Button == mbLeft && m_bKeyDown) {
|
|
m_bKeyDown = false;
|
|
|
|
f_MM_RealTimeMIDINoteOff(m_iPressGroup*12 + m_iPressKey + 48);
|
|
|
|
TRect rect;
|
|
rect.init(m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 6,
|
|
19,
|
|
m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 26,
|
|
m_pbKeyboard->Height+19);
|
|
|
|
m_iPressGroup = m_iPressKey = -1;
|
|
|
|
InvalidateRect(m_pbKeyboard->Parent->Handle,&rect,true);
|
|
// m_pbKeyboard->Invalidate();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::KeyboardMouseMove(TObject *Sender, TShiftState Shift, int X,
|
|
int Y)
|
|
{
|
|
if (m_bKeyDown && X >= 0 && Y >= 0 && X < m_pbKeyboard->Width && Y <
|
|
m_pbKeyboard->Height) {
|
|
int iKey = KeyboardGetPressKey(X, Y);
|
|
int iPressGroup = HIWORD(iKey);
|
|
int iPressKey = LOWORD(iKey);
|
|
|
|
if (iPressGroup != m_iPressGroup || iPressKey != m_iPressKey) {
|
|
HRESULT hRet = f_MM_RealTimeMIDINoteOff(m_iPressGroup * 12 + m_iPressKey + 48);
|
|
hRet = f_MM_RealTimeMIDINoteOn( iPressGroup * 12 + iPressKey + 48);
|
|
|
|
TRect rect;
|
|
|
|
//更新原来区域
|
|
rect.init(m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 6,
|
|
19,
|
|
m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 26,
|
|
m_pbKeyboard->Height+19);
|
|
|
|
InvalidateRect(m_pbKeyboard->Parent->Handle,&rect,true);
|
|
|
|
m_iPressGroup = iPressGroup;
|
|
m_iPressKey = iPressKey;
|
|
|
|
//更新新区域
|
|
rect.init(m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 6,
|
|
19,
|
|
m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 26,
|
|
m_pbKeyboard->Height+19);
|
|
|
|
InvalidateRect(m_pbKeyboard->Parent->Handle,&rect,true);
|
|
|
|
// m_pbKeyboard->Invalidate();
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::KeyboardMouseLeave(TObject *Sender)
|
|
{
|
|
//
|
|
Screen->Cursor = crDefault;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::KeyboardMouseEnter(TObject *Sender)
|
|
{
|
|
//
|
|
Screen->Cursor = crHandPoint;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::KeyboardMouseDown(TObject *Sender, TMouseButton Button,
|
|
TShiftState Shift, int X, int Y)
|
|
{
|
|
// TMouseButton Button, TShiftState Shift, int X, int Y) {
|
|
if (Sender == m_pbKeyboard && Button == mbLeft) {
|
|
m_bKeyDown = true;
|
|
|
|
int iKey = KeyboardGetPressKey(X, Y);
|
|
int iPressGroup = HIWORD(iKey);
|
|
int iPressKey = LOWORD(iKey);
|
|
|
|
if (iPressGroup != m_iPressGroup || iPressKey != m_iPressKey) {
|
|
m_iPressGroup = iPressGroup;
|
|
m_iPressKey = iPressKey;
|
|
|
|
HRESULT hRet =
|
|
f_MM_RealTimeMIDINoteOn(m_iPressGroup * 12 + m_iPressKey + 48);
|
|
|
|
TRect rect;
|
|
rect.init(m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 6,
|
|
19,
|
|
m_iPressGroup * m_nGroupWidth + m_aKey[m_iPressKey].xPos + 26,
|
|
m_pbKeyboard->Height+19);
|
|
|
|
InvalidateRect(m_pbKeyboard->Parent->Handle,&rect,true);
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
void __fastcall TKeyBoard::ShowKeyboard( bool bShow )
|
|
{
|
|
if( bShow ){
|
|
// 创建模拟键盘设备
|
|
HRESULT hResult = f_MM_CreateRealTimeMIDIStream( false );
|
|
if (hResult != S_OK) {
|
|
DebugPrint("Create realtime midi stream error.\n");
|
|
}
|
|
else{
|
|
this->Show();
|
|
}
|
|
}
|
|
else if( !bShow ){
|
|
this->Hide();
|
|
|
|
// 释放模拟键盘设备
|
|
HRESULT hResult = f_MM_FreeRealTimeMIDIStream();
|
|
if (hResult != S_OK) {
|
|
DebugPrint("Free realtime midi stream error.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void __fastcall TKeyBoard::CloseClick(System::TObject* Sender)
|
|
{
|
|
// ShowKeyboard( false );
|
|
Application->MainForm->Perform( UM_SHOW_KB, NULL, NULL );
|
|
}
|