Apropos MIDI, bardzo prosty przykład:
#include <dinput.h>
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dxguid.lib")
char keys[] = {DIK_Z,DIK_S,DIK_X,DIK_D,DIK_C,DIK_V,DIK_G,DIK_B,DIK_H,DIK_N,DIK_J,DIK_M,DIK_COMMA,
DIK_Q,DIK_2,DIK_W,DIK_3,DIK_E,DIK_R,DIK_5,DIK_T,DIK_6,DIK_Y,DIK_7,DIK_U,DIK_I};
int main()
{
HMIDIOUT midiOut;
midiOutOpen(&midiOut, 0xFFFFFFFF, 0, 0, CALLBACK_NULL);
//midiOutSetVolume(midiOut, 0xFFFFFFFF);
midiOutShortMsg(midiOut, 0x007800C0 | (/*instrument*/0x10 << 8));
IDirectInput *di;
IDirectInputDevice *keyboard;
DIPROPDWORD dpd;
dpd.diph.dwSize = sizeof(dpd);
dpd.diph.dwHeaderSize = sizeof(dpd.diph);
dpd.diph.dwObj = 0;
dpd.diph.dwHow = DIPH_DEVICE;
dpd.dwData = 32;
DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, 0);
di->CreateDevice(GUID_SysKeyboard, &keyboard, 0);
keyboard->SetDataFormat(&c_dfDIKeyboard);
keyboard->SetCooperativeLevel(GetForegroundWindow(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
keyboard->SetProperty(DIPROP_BUFFERSIZE, &dpd.diph);
keyboard->Acquire();
BOOL run = true;
while (run)
{
Sleep(10);
DIDEVICEOBJECTDATA ddd;
DWORD dwInOut = 1;
while (run && !keyboard->GetDeviceData(sizeof(ddd), &ddd, &dwInOut, 0) && (dwInOut==1))
{
if (ddd.dwOfs == DIK_ESCAPE) {
run = false;
break;
}
for (int tone=0; tone < sizeof(keys); tone++)
{
if (ddd.dwOfs == keys[tone])
{
tone = (tone + 0x3C - (tone>12) ) << 8; // (tone>12) mamy dwa te same tony dla ,q
midiOutShortMsg(midiOut, tone | ((ddd.dwData & 0x80) ? 0x00400090 : 0x00000090));
break;
}
}
}
}
keyboard->Release();
di->Release();
midiOutClose(midiOut);
return 0;
}
Zamiast prymitywnego Sleep (pooling) można stworzyć drugie device i kazać mu blokować wątek póki stan klawiatury się nie zmieni:
Niestety, połączenie buforowania i event-notification w jednym device - działa do wciśnięcia pierwszego klawisza, dlatego potrzebne są dwa 'device' gdzie pierwsze buforuje klawisze, a drugie czeka na dane z klawiatury.
GetForegroundWindow() - wstawiłem dla konsolowego programu, ale równie dobrze działa z hwnd=0
IDirectInputDevice *keybwait;
di->CreateDevice(GUID_SysKeyboard, &keybwait, 0);
keybwait->SetDataFormat(&c_dfDIKeyboard);
keyboard->SetCooperativeLevel(GetForegroundWindow(), DISCL_NONEXCLUSIVE|DISCL_FOREGROUND);
HANDLE hEvent = CreateEvent(0,0,0,0);
keybwait->SetEventNotification(hEvent);
keybwait->Acquire();
BOOL run = true;
while (run && !WaitForSingleObject(hEvent, INFINITE))
{
// bez Sleep
}
keybwait->SetEventNotification(0);
CloseHandle(hEvent);
keybwait->Release();