嗨嗨嗨~
Today事有点多,先留个代码。
#if defined(_WIN32) | defined(WIN32)
#include <windows.h>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <unordered_map>
#define CHOOSE 1
#define UNCHOOSE 0
HMIDIOUT* hMidiOut = new HMIDIOUT;
namespace std {
string hmusicname[128] = {"1 大钢琴(声学钢琴)", "2 明亮的钢琴", "3 电钢琴", "4 酒吧钢琴", "5 柔和的电钢琴", "6 加合唱效果的电钢琴", "7 羽管键琴(拨弦古钢琴)", "8 科拉维科特琴(击弦古钢琴)", "9 钢片琴", "10 钟琴", "11 八音盒", "12 颤音琴", "13 马林巴", "14 木琴", "15 管钟", "16 大扬琴", "17 击杆风琴", "18 打击式风琴", "19 摇滚风琴", "20 教堂风琴", "21 簧管风琴", "22 手风琴", "23 口琴", "24 探戈手风琴", "25 尼龙弦吉他", "26 钢弦吉他", "27 爵士电吉他", "28 清音电吉他", "29 闷音电吉他", "30 加驱动效果的电吉他", "31 加失真效果的电吉他", "32 吉他和音", "33 大贝司(声学贝司)", "34 电贝司(指弹)", "35 电贝司(拨片)", "36 无品贝司", "37 掌击1", "38 掌击2", "39 电子合成1", "40 电子合成2", "41 小提琴", "42 中提琴", "43 大提琴", "44 低音大提琴", "45 弦乐群颤音音色", "46 弦乐群拨弦音色", "47 竖琴", "48 定音鼓", "49 弦乐合奏音色1", "50 弦乐合奏音色2", "51 合成弦乐合奏音色1", "52 合成弦乐合奏音色2", "53 人声合唱 “啊”", "54 人声 “嘟”", "55 合成人声", "56 管弦乐敲击齐奏", "57 小号", "58 长号", "59 大号", "60 加弱音器小号", "61 法国号(圆号)", "62 铜管组(铜管乐器合奏音色)", "63 合成铜管音色1", "64 合成铜管音色2", "65 高音萨克斯风", "66 次中音萨克斯风", "67 中音萨克斯风", "68 低音萨克斯风", "69 双簧管", "70 英国管", "71 巴松(大管)", "72 单簧管(黑管)", "73 短笛", "74 长笛", "75 竖笛", "76 排箫", "77 Bottle Blow", "78 日本尺八", "79 口哨声", "80 奥卡雷那", "81 合成主音1 (方波)", "82 合成主音2 (锯齿波)", "83 合成主音3", "84 合成主音4", "85 合成主音5", "86 合成主音6 (人声)", "87 合成主音7 (平行五度)", "88 合成主音8 (贝司加主音)", "89 合成音色1 (新世纪)", "90 合成音色2 (温暖)", "91 合成音色3", "92 合成音色4 (合唱)", "93 合成音色5", "94 合成音色6 (金属声)", "95 合成音色7 (光环)", "96 合成音色8", "97 合成效果1 (雨声)", "98 合成效果2 (音轨)", "99 合成效果3 (水晶)", "100 合成效果4 (大气)", "101 合成效果5 (明亮)", "102 合成效果6 (鬼怪)", "103 合成效果7 (回声)", "104 合成效果8 (科幻)", "105 西塔尔(印度)", "106 班卓琴(美洲)", "107 三昧线(日本)", "108 十三弦筝(日本)", "109 卡林巴", "110 风笛", "111 民族提琴", "112 山奈", "113 叮当铃", "114 Agogo", "115 钢鼓", "116 木鱼", "117 太鼓", "118 通通鼓", "119 合成鼓", "120 铜钹", "121 吉他换把杂音", "122 呼吸声", "123 海浪声", "124 鸟鸣", "125 电话铃", "126 直升机", "127 鼓掌声", "128 枪击声"};
vector<string> hmusic[17];
vector<RECT> edit;
int thisarea = 1;
unordered_map<string, long> table;
string to_str(int x)
{
string ret = "", temp = "";
if (x < 0)
{
ret = "-";
x = -x;
}
while (x != 0)
{
temp = char(x % 10 + '0') + temp;
x /= 10;
}
return ret + temp;
}
void init()
{
string each[13] = {"", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
long num = 0;
for (long i = -1; i <= 9; i++)
{
for (long j = 1; j <= 12; j++)
{
if (num == 127)
{
break;
}
string key = to_str(i) + each[j];
table[key] = num++;
}
}
string typen[16] = {"1 琴", "2 色彩打击乐器", "3 风琴", "4 吉他", "5 贝司", "6 弦乐", "7 合奏/合唱", "8 铜管", "9 簧管", "10 笛", "11 合成主音", "12 合成音色", "13 合成效果", "14 民间乐器", "15 打击乐器", "16 声音效果"};
num = 0;
for (int i = 0; i < 16; i++)
{
hmusic[i + 1].push_back(typen[i]);
for (int j = 1; j <= 8; j++)
{
hmusic[i + 1].push_back(hmusicname[num++]);
}
}
}
string getDevName(string s)
{
for (int i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
{
return s.substr(i + 1, s.size() - i);
}
}
}
struct Note {
vector<RECT> place;
string name;
int stair;
void splay()
{
midiOutShortMsg(*hMidiOut, 0x007f0090 + table[to_str(stair) + name] * 256);
}
void cplay()
{
midiOutShortMsg(*hMidiOut, 0x00000080 + table[to_str(stair) + name] * 256);
}
bool judge(POINT p)
{
if (place.size() == 1)
{
return ((p.x >= place[0].left && p.x <= place[0].right) && (p.y >= place[0].top && p.y <= place[0].bottom));
}
else
{
bool flag = 0;
for (int i = 0; i < place.size(); i++)
{
flag = flag | ((p.x >= place[i].left && p.x <= place[i].right) && (p.y >= place[i].top && p.y <= place[i].bottom));
}
return flag;
}
}
};
vector<Note> keyboard;
}
RECT buttonDraw(HDC hdc, bool flag, int startx, int starty, int x, int y, std::string str)
{
RECT ret;
HBRUSH hbr;
if (flag) hbr = CreateSolidBrush(RGB(25, 25, 225));
else hbr = CreateSolidBrush(RGB(0, 0, 0));
RECT r;
r.bottom = starty + y;
r.top = starty;
r.left = startx;
r.right = startx + x;
ret.bottom = r.bottom;
ret.top = r.top;
ret.left = r.left;
ret.right = r.right;
FillRect(hdc, &r, hbr);
r.bottom -= 2;
r.top += 2;
r.left += 2;
r.right -= 2;
hbr = CreateSolidBrush(RGB(255, 255, 255));
FillRect(hdc, &r, hbr);
TextOut(hdc, startx + 13, starty + (y - 14) / 2, str.c_str(), str.size());
return ret;
}
void buttonDrawEx(HDC hdc, int choose = 1, int area = 1)
{
int menux = 25, menuy = 195;
bool flag = std::edit.empty();
for (int i = 1; i <= 16; i++)
{
RECT r = buttonDraw(hdc, (area == i), menux, menuy, 150, 25, std::hmusic[i][0]);
if (flag) std::edit.push_back(r);
menuy += 35;
}
int startx = 215, starty = 195;
if (std::thisarea != area) for (int i = 1; i <= 8; i++) std::edit.pop_back();
for (int i = 1; i <= 8; i++)
{
RECT r = buttonDraw(hdc, (choose == i), startx, starty, 250, 25 ,std::hmusic[area][i]);
if (flag || std::thisarea != area) std::edit.push_back(r);
starty += 35;
}
std::thisarea = area;
}
void whiteDraw(HDC hdc, int startx, int stw)
{
HBRUSH hbr = CreateSolidBrush(RGB(0, 0, 0));
RECT r;
RECT RinN;
std::Note n;
n.place.clear();
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "C";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx;
RinN.right = startx + 12;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 108, std::to_str(stw).c_str(), 1);
TextOut(hdc, startx + 6, 122, "C", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "D";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 12;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "D", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "E";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 20;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "E", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "F";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 12;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "F", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "G";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 12;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "G", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "A";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 12;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "A", 1);
startx += 20;
n.place.clear();
hbr = CreateSolidBrush(RGB(0, 0, 0));
r.bottom = 140;
r.top = 65;
r.left = startx;
r.right = startx + 20;
FillRect(hdc, &r, hbr);
hbr = CreateSolidBrush(RGB(255, 255, 255));
r.bottom -= 1;
r.top += 1;
r.left += 1;
r.right -= 1;
FillRect(hdc, &r, hbr);
n.name = "B";
n.stair = stw;
RinN.bottom = 140;
RinN.top = 99;
RinN.left = startx;
RinN.right = startx + 20;
n.place.push_back(RinN);
RinN.bottom = 100;
RinN.top = 65;
RinN.left = startx + 8;
RinN.right = startx + 20;
n.place.push_back(RinN);
std::keyboard.push_back(n);
TextOut(hdc, startx + 6, 122, "B", 1);
stw++;
}
void blackDraw(HDC hdc, int startx, int stb)
{
HBRUSH hbr = CreateSolidBrush(RGB(0, 0, 0));
RECT r;
std::Note n;
n.place.clear();
r.bottom = 100;
r.top = 65;
r.left = startx + 13;
r.right = startx + 27;
FillRect(hdc, &r, hbr);
n.name = "C#";
n.stair = stb;
n.place.push_back(r);
std::keyboard.push_back(n);
startx += 20;
n.place.clear();
r.bottom = 100;
r.top = 65;
r.left = startx + 13;
r.right = startx + 27;
FillRect(hdc, &r, hbr);
n.name = "D#";
n.stair = stb;
n.place.push_back(r);
std::keyboard.push_back(n);
startx += 40;
n.place.clear();
r.bottom = 100;
r.top = 65;
r.left = startx + 13;
r.right = startx + 27;
FillRect(hdc, &r, hbr);
n.name = "F#";
n.stair = stb;
n.place.push_back(r);
std::keyboard.push_back(n);
startx += 20;
n.place.clear();
r.bottom = 100;
r.top = 65;
r.left = startx + 13;
r.right = startx + 27;
FillRect(hdc, &r, hbr);
n.name = "G#";
n.stair = stb;
n.place.push_back(r);
std::keyboard.push_back(n);
startx += 20;
n.place.clear();
r.bottom = 100;
r.top = 65;
r.left = startx + 13;
r.right = startx + 27;
FillRect(hdc, &r, hbr);
n.name = "A#";
n.stair = stb;
n.place.push_back(r);
std::keyboard.push_back(n);
stb++;
}
bool flag = 0;
bool judge(POINT p, RECT r)
{
return (p.y <= r.bottom && p.y >= r.top && p.x >= r.left && p.x <= r.right);
}
int area = 1, choose[17] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
RECT again;
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hbr;
POINT ptClient;
switch(Message) {
case WM_LBUTTONDOWN: {
startjudge:{}
GetCursorPos(&ptClient);
ScreenToClient(hwnd, &ptClient);
if(judge(ptClient, again))
{
InvalidateRect(hwnd, NULL, FALSE);
}
for (int i = 0; i < std::keyboard.size(); i++)
{
if (std::keyboard[i].judge(ptClient))
{
std::keyboard[i].splay();
while ((GetAsyncKeyState(VK_LBUTTON) & 0X8000) ? 1 : 0)
{
usleep(20);
GetCursorPos(&ptClient);
ScreenToClient(hwnd, &ptClient);
if (!std::keyboard[i].judge(ptClient))
{
std::keyboard[i].cplay();
goto startjudge;
}
}
std::keyboard[i].cplay();
break;
}
}
for (int i = 1; i <= 16; i++)
{
if (judge(ptClient, std::edit[i - 1]))
{
area = i;
midiOutShortMsg(*hMidiOut, 0x00C0 + (area * 8 + choose[area] - 9) * 256);
InvalidateRect(hwnd, NULL, TRUE);
}
}
for (int i = 1; i <= 8; i++)
{
if (judge(ptClient, std::edit[i + 15]))
{
midiOutShortMsg(*hMidiOut, 0x00C0 + (area * 8 + i - 9) * 256);
choose[area] = i;
InvalidateRect(hwnd, NULL, TRUE);
}
}
break;
}
case WM_CHAR: {
if (wParam < '1' || wParam > '9')
{
break;
}
else
{
std::keyboard[20 + int(wParam - '0')].splay();
while ((GetAsyncKeyState(wParam) & 0x8000) ? 1 : 0)
{
usleep(20);
}
std::keyboard[20 + int(wParam - '0')].cplay();
}
break;
}
case WM_PAINT: {
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 15, 10, "Again", 5);
std::string dev = "当前音色:" + std::getDevName(std::hmusic[area][choose[area]]);
TextOut(hdc, 515, 200, dev.c_str(), dev.size());
buttonDrawEx(hdc, choose[area], area);
int sx = 20;
for (int i = 1; i <= 7; i++)
{
whiteDraw(hdc, sx, i);
sx += 140;
}
sx = 20;
for (int i = 1; i <= 7; i++)
{
blackDraw(hdc, sx, i);
sx += 140;
}
HBRUSH hBr = CreateSolidBrush(RGB(0, 0, 0));
RECT r;
r.left = 20;
r.right = 1000;
r.bottom = 65;
r.top = 27;
FillRect(hdc, &r, hBr);
hBr = CreateSolidBrush(RGB(127, 127, 127));
r.left = 20;
r.right = 1000;
r.bottom = 65;
r.top = 63;
FillRect(hdc, &r, hBr);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY: {
midiOutReset(*hMidiOut);
midiOutClose(*hMidiOut);
delete hMidiOut;
PostQuitMessage(0);
break;
}
default: return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
again.bottom = 27;
again.top = 10;
again.left = 15;
again.right = 55;
std::init();
midiOutOpen(hMidiOut, midiOutGetNumDevs() - 1, 0, 0, 0);
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
memset(&wc,0,sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = "WindowClass";
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "WindowClass", "Piano", WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
1030,
805,
NULL,NULL,hInstance,NULL);
if(hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
#else
#include <iostream>
using namespace std;
int main()
{
cout << "Unexpect Error\n";
cout << "----------------------\n";
cout << " Detail:\n";
cout << " The programme is not running on Windows system.\n";
return -32767;
}
#endif
记得在项目属性->参数->链接器里加上
-lwinmm
不然会逝世。
更新
本次更新新增乐器切换,windows系统判断,并且对于音符播放进行了更新,将通道换为0通道,停止播放不是暴力将力度设为0,而是用“0x00000080+音符”关闭播放。