Files
AC_Pro/KeyBoard.cpp
2026-06-13 00:05:19 +08:00

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