Hmm, niezależnie od całego MCI... Gdyby twój PlayCallback
ruszył, to następnie rekurencyjnie by się wywoływał w nieskończoność, aż do przepełnienia stosu :|
static LRESULT CALLBACK PlayCallback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// coś tam robisz w switch... a potem zawsze dochodzisz to linijki:
return PlayCallback(hwnd,uMsg,wParam,lParam);
}
Ogólnie sprawa rysuje się tak: Musisz stworzyć sobie w tle wątek (funkcja CreateThread
). W w tym wątku musisz sobie utworzyć pomocnicze okno, a w obsłudze tego okna odbierać MM_MCINOTIFY
. Klasę okna rejestrujesz funkcją RegisterClassEx
, wypełniając strukturę WNDCLASSEX
. Większość pól domyślnie, z istotnych to będzie hInstance
oraz lpfnWndProc
. Pierwsze ustawiasz na GetModuleHandle(NULL)
- jako aplikacja konsolowa, to chyba innego sposobu nie ma. A drugie pole to na swoją funkcję callbackową. Okno sobie tworzysz funkcją CreateWindowEx
. Z ciekawszych argumentów to będzie na pewno styl okna jako WS_EX_TOOLWINDOW
, uchwyt rodzica to możesz sobie dać na HWND_DESKTOP
, a hInstance
znowu na GetModuleHandle(NULL)
. No i oczywiście lpszClassName
podajesz taką samą, jak klasa okna, którą rejestrowałeś przed chwilą.
Nie wiem, na jakim etapie jesteś - taki ogólny zarys może będzie Ci wygodniej wykorzystać w swoim programie, niż gotowy kod. Kluczowe sprawy są. Zarys napisałem po wygrzebaniu i przetrawieniu programiku, który sobie lata temu uklepałem w ramach eksperymentów. Nie jest długi, więc też dołączę - może będzie łatwiej Ci przykładowy kod przerobić.
Disclaimer: przykład nie ma obsługi błędów, zwalniania zasobów, może w ogóle jest nieczytelny... nie wiem, nie znam się, takie miałem, takie daję ;)
#include <conio.h>
#include <cstdio>
#include <windows.h>
class MCIPlayer {
private:
HINSTANCE mInstance;
LPCSTR mClassName;
HANDLE mThread;
WNDCLASSEX mWindowClass;
HWND mWindowHandle;
void init();
static DWORD WINAPI procThread(void* param);
static LRESULT CALLBACK procWindow(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
public:
MCIPlayer(HINSTANCE instance, LPCSTR className);
~MCIPlayer();
void send(const char* command);
};
MCIPlayer::MCIPlayer(HINSTANCE instance, LPCSTR className) {
mInstance = instance;
mClassName = className;
mThread = CreateThread(NULL, 0, &procThread, this, 0, NULL);
}
MCIPlayer::~MCIPlayer() {
SendMessage(mWindowHandle, WM_DESTROY, 0, 0);
}
void MCIPlayer::init() {
memset(&mWindowClass, 0, sizeof(mWindowClass) );
mWindowClass.hInstance = mInstance;
mWindowClass.lpszClassName = mClassName;
mWindowClass.lpfnWndProc = &MCIPlayer::procWindow;
mWindowClass.style = CS_DBLCLKS;
mWindowClass.cbSize = sizeof (WNDCLASSEX);
mWindowClass.hIcon = NULL;
mWindowClass.hIconSm = NULL;
mWindowClass.hCursor = NULL;
mWindowClass.lpszMenuName = NULL;
mWindowClass.cbClsExtra = 0;
mWindowClass.cbWndExtra = 0;
mWindowClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
RegisterClassEx(&mWindowClass);
mWindowHandle = CreateWindowEx (
0,
mWindowClass.lpszClassName,
"",
WS_EX_TOOLWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
HWND_DESKTOP,
NULL,
mWindowClass.hInstance,
NULL
);
}
void MCIPlayer::send(const char* command) {
char response[128];
mciSendString(command, response, 128, mWindowHandle);
}
DWORD WINAPI MCIPlayer::procThread(void* param) {
MCIPlayer* that = (MCIPlayer*)param;
that->init();
MSG message;
while( GetMessage(&message, NULL, 0, 0) ){
TranslateMessage(&message);
DispatchMessage(&message);
}
return 0;
}
LRESULT CALLBACK MCIPlayer::procWindow(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case MM_MCINOTIFY:
printf("MCI > NOTIFY : %lx %lx\n", (long)wParam, (long)lParam);
break;
default:
printf("MSG > %08lx : %lx %lx\n", (long)message, (long)wParam, (long)lParam);
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
int main() {
printf(
" [0] exit\n"
" [1] play\n"
" [2] resume\n"
" [3] stop\n"
" [4] pause\n"
" [5] rewind\n"
);
MCIPlayer mci(GetModuleHandle(NULL), "MCIPlayerHelper");
mci.send("open music.mp3 type mpegvideo alias track1");
//mci.send("open alarm.wav type waveaudio alias track1");
while(true) switch(getch()) {
case 27 :
case '0': // stop & exit
mci.send("close track1 notify");
return 0;
case '1': // play
mci.send("play track1 notify");
break;
case '2': // resume
mci.send("resume track1 notify");
break;
case '3': // stop
mci.send("stop track1 notify");
break;
case '4': // pause
mci.send("pause track1 notify");
break;
case '5': // rewind
mci.send("seek track1 to start notify");
break;
}
return 0;
}