//INCLUDES #include "framework.h" #include "resource.h" #include #include //IMPORTS using std::wstring; //CONTROL IDS #define IDC_DIRLABEL 201 #define IDC_BROWSEBTN 202 #define IDC_LIST 203 #define IDC_NPLABEL 204 #define IDC_PLAYBTN 205 #define IDC_STOPBTN 206 //STATIC DEFINES #define EXT_LENGTH 2 #define STATE_CHANGE 333 //STRING TABLE #define PROGRAM_NAME L"ClickPlay" #define NOT_PLAYING_LABEL L"Nic nie jest odtwarzane" #define PLAY_LABEL L"Odtwarzaj" #define PAUSE_LABEL L"Pauza" #define NO_DIR_LOADED_LABEL L"Nie wybrano folderu" //GLOBAL VARS HFONT hFont = CreateFont(18, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Segoe UI")); HINSTANCE globalInstance; MSG msg; wstring ext[EXT_LENGTH] = { L"mp3", L"wav" }; //PATH VARS wstring path; wstring selected; //STATE VARS /* * -1 - not ready * 0 - ready * 1 - playback active * 2 - playback paused */ int currentState = -1; BOOL isAutoPlayEnabled = TRUE; BOOL isLoopEnabled = FALSE; BOOL isQueued = FALSE; //CONTROLS HWND mainWindow; HWND dirLabel; HWND browseButton; HWND filesListCtrl; HWND playButton; HWND stopButton; HWND npLabel; HMENU menuBar; //HOOKS LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); //ENTRY POINT int WINAPI WinMain(HINSTANCE currentInst, HINSTANCE previousInst, LPSTR lpCmdLine, int nCmdShow) { globalInstance = currentInst; //CREATE & REGISTER WINDOW CLASS WNDCLASSEX windowClass = { 0 }; windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.lpfnWndProc = WndProc; windowClass.hInstance = currentInst; windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW); windowClass.lpszClassName = PROGRAM_NAME; windowClass.hIcon = (HICON)LoadImage(currentInst, L"ClickPlay.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_SHARED); windowClass.hIconSm = (HICON)LoadImage(currentInst, L"small.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_SHARED); if (!RegisterClassEx(&windowClass)) { return 1; } //LOAD KEYBOARD SHORTCUT TABLE HACCEL shortcuts = LoadAccelerators(currentInst, MAKEINTRESOURCE(IDC_CLICKPLAY)); //LOAD MENU BAR menuBar = LoadMenu(currentInst, (LPCWSTR)IDC_MENU); //CREATE MAIN WINDOW mainWindow = CreateWindowEx(WS_EX_CLIENTEDGE, windowClass.lpszClassName, PROGRAM_NAME, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 400, 620, NULL, menuBar, currentInst, NULL); SendMessage(mainWindow, WM_SETFONT, (WPARAM)hFont, TRUE); SendMessage(mainWindow, STATE_CHANGE, -1, NULL); ShowWindow(mainWindow, nCmdShow); UpdateWindow(mainWindow); //INITIALIZE MESSAGE LOOP while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, shortcuts, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return 0; } //CREATE CONTROLS void CreateControls(HWND window) { dirLabel = CreateWindowEx(0, L"STATIC", NO_DIR_LOADED_LABEL, WS_CHILD | WS_VISIBLE, 10, 10, 250, 40, window, (HMENU)IDC_DIRLABEL, globalInstance, NULL); SendMessage(dirLabel, WM_SETFONT, (WPARAM)hFont, TRUE); browseButton = CreateWindowEx(0, L"BUTTON", L"Przeglądaj", WS_CHILD | WS_VISIBLE, 275, 10, 100, 30, window, (HMENU)IDC_BROWSEBTN, globalInstance, NULL); SendMessage(browseButton, WM_SETFONT, (WPARAM)hFont, TRUE); filesListCtrl = CreateWindowEx(0, L"LISTBOX", NULL, LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_VSCROLL, 0, 50, 400, 425, window, (HMENU)IDC_LIST, globalInstance, NULL); SendMessage(filesListCtrl, WM_SETFONT, (WPARAM)hFont, TRUE); npLabel = CreateWindowEx(0, L"STATIC", NOT_PLAYING_LABEL, SS_CENTER | WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, -5, 460, 400, 40, window, (HMENU)IDC_NPLABEL, globalInstance, NULL); SendMessage(npLabel, WM_SETFONT, (WPARAM)hFont, TRUE); playButton = CreateWindowEx(0, L"BUTTON", PLAY_LABEL, WS_CHILD | WS_VISIBLE, 75, 515, 100, 30, window, (HMENU)IDC_PLAYBTN, globalInstance, NULL); SendMessage(playButton, WM_SETFONT, (WPARAM)hFont, TRUE); stopButton = CreateWindowEx(0, L"BUTTON", L"Zatrzymaj", WS_CHILD | WS_VISIBLE, 195, 515, 100, 30, window, (HMENU)IDC_STOPBTN, globalInstance, NULL); SendMessage(stopButton, WM_SETFONT, (WPARAM)hFont, TRUE); } //GET SELECTED INDEX int GetIndex() { LRESULT listItemsCount = SendMessage(filesListCtrl, LB_GETCOUNT, NULL, NULL); for (int i = 0; i < listItemsCount; i++) { if (SendMessage(filesListCtrl, LB_GETSEL, (WPARAM)i, NULL) > 0) { return i; } } return -1; } //REMOVE SELECTION void UnloadSelection() { mciSendString(L"close mp3", NULL, 0, mainWindow); selected.clear(); } //LOAD SELECTION /* * ERROR CODES * -1 - invalid index * -2 - file not found * -3 - path not loaded */ int LoadSelection(int index) { UnloadSelection(); if (index != -1) { LRESULT selectedLength = SendMessage(filesListCtrl, LB_GETTEXTLEN, (WPARAM)index, NULL); TCHAR* selectionBuffer = new TCHAR[selectedLength]; SendMessage(filesListCtrl, LB_GETTEXT, (WPARAM)index, (LPARAM)selectionBuffer); if (!path.empty()) { wstring fullPath = path + L"\\" + selectionBuffer; WIN32_FIND_DATA fileData; HANDLE fileExist = FindFirstFile(fullPath.c_str(), &fileData); if (fileExist == INVALID_HANDLE_VALUE) { MessageBox(mainWindow, L"Wskazany plik nie został odnaleziony. Upewnij się, że nie został przeniesiony lub naciśnij klawisz F5, aby pozbyć się niedziałających pozycji.", L"Nie znaleziono pliku", MB_ICONERROR); return -2; } else { wstring fullCommandS = L"open \"" + fullPath + L"\" type mpegvideo alias mp3"; LPCWSTR fullCommand = fullCommandS.c_str(); mciSendString(fullCommand, NULL, 0, mainWindow); selected = wstring(selectionBuffer); return 0; } } else { MessageBox(mainWindow, L"Naruszenie dostępu do stanu programu. Proces zostanie zakończony.", L"Błąd krytyczny", MB_ICONERROR); ExitProcess(0); return -3; } } else { return -1; } } //UNLOAD DIRECTORY void UnloadDir() { SendMessage(filesListCtrl, LB_RESETCONTENT, NULL, NULL); path.clear(); if (!selected.empty()) { UnloadSelection(); } } //LOAD DIRECTORY /* * ERROR CODES * -1 - empty string * -2 - invalid directory */ int LoadDir(wstring dir) { UnloadDir(); if (!dir.empty()) { DWORD dirA = GetFileAttributes(dir.c_str()); if (dirA & FILE_ATTRIBUTE_DIRECTORY) { SendMessage(filesListCtrl, LB_RESETCONTENT, NULL, NULL); for (int i = 0; i < EXT_LENGTH; i++) { wstring findPathS = dir + L"\\*." + ext[i]; LPCWSTR findPath = findPathS.c_str(); WIN32_FIND_DATA dirData; HANDLE finder = FindFirstFile(findPath, &dirData); if (finder != INVALID_HANDLE_VALUE) { do { SendMessage(filesListCtrl, LB_ADDSTRING, NULL, (LPARAM)dirData.cFileName); } while (FindNextFile(finder, &dirData)); } } path = dir; return 0; } else { MessageBox(mainWindow, L"Program nie może uzyskać dostępu do wskazanego katalogu.", L"Nieprawidłowy katalog", MB_ICONERROR); return -2; } } else { MessageBox(mainWindow, L"Nie załadowano folderu. Użyj przycisku PRZEGLĄDAJ, aby załadaować katalog.", L"Brak katalogu", MB_ICONERROR); return -1; } } //INITALIZE FOLDER PICKER BOOL FolderBrowseDialog(HWND window) { BROWSEINFO dialog = { 0 }; dialog.hwndOwner = window; dialog.ulFlags = BIF_NEWDIALOGSTYLE; dialog.lpszTitle = L"Wybierz folder, który ma zostać otwarty przez program"; LPITEMIDLIST pid = SHBrowseForFolder(&dialog); TCHAR currentPath[MAX_PATH]; if (pid != 0) { SHGetPathFromIDList(pid, currentPath); if (LoadDir((wstring)currentPath) == 0) { SetCurrentDirectory(path.c_str()); SetWindowText(dirLabel, path.c_str()); return TRUE; } else { return FALSE; } } else { return FALSE; } } //MESSAGE LOOP LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int windowId, windowEvent; switch (msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: CreateControls(hwnd); break; case WM_COMMAND: windowId = LOWORD(wParam); windowEvent = HIWORD(wParam); switch (windowId) { case IDC_BROWSEBTN: if (FolderBrowseDialog(mainWindow) == TRUE) { SendMessage(mainWindow, STATE_CHANGE, 0, NULL); } break; case IDC_LIST: if (windowEvent == LBN_SELCHANGE) { if (currentState == 1 || currentState == 2) { currentState = 1; isQueued = TRUE; } if (LoadSelection(GetIndex()) == 0) { if (isAutoPlayEnabled == TRUE) { SendMessage(mainWindow, STATE_CHANGE, 1, NULL); } } } break; case IDC_PLAYBTN: switch (currentState) { case 0: if (LoadSelection(GetIndex()) == 0) { SendMessage(mainWindow, STATE_CHANGE, 1, NULL); } else { MessageBox(mainWindow, L"Podczas odtwarzania wystąpił błąd", L"Błąd odtwarzacza", MB_ICONERROR); } break; case 1: SendMessage(mainWindow, STATE_CHANGE, 2, NULL); break; case 2: SendMessage(mainWindow, STATE_CHANGE, 1, NULL); break; } break; case IDC_STOPBTN: isQueued = FALSE; SendMessage(mainWindow, MM_MCINOTIFY, 0, 0); break; case IDM_EXIT: SendMessage(mainWindow, WM_CLOSE, NULL, NULL); break; case IDM_ABOUT: DialogBox(globalInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), mainWindow, About); break; case ID_REFRESH: LoadDir(path); break; case ID_OPCJE_ONCLICK: if (isAutoPlayEnabled) { CheckMenuItem(menuBar, ID_OPCJE_ONCLICK, MF_UNCHECKED); isAutoPlayEnabled = FALSE; } else { CheckMenuItem(menuBar, ID_OPCJE_ONCLICK, MF_CHECKED); isAutoPlayEnabled = TRUE; } break; case ID_OPCJE_LOOP: if (isLoopEnabled) { CheckMenuItem(menuBar, ID_OPCJE_LOOP, MF_UNCHECKED); isLoopEnabled = FALSE; } else { CheckMenuItem(menuBar, ID_OPCJE_LOOP, MF_CHECKED); isLoopEnabled = TRUE; } break; case ID_POMOC_KBSHR: MessageBox(mainWindow, L"F1 = ekran skrótów klawiszowych\nF2 = ekran Informacje\nF5 = odśwież listę plików", L"Skróty klawiszowe", MB_ICONASTERISK); break; case ID_PLIK_CLOSEDIR: SendMessage(mainWindow, STATE_CHANGE, -1, NULL); break; } break; case MM_MCINOTIFY: if (!isQueued) { UnloadSelection(); SendMessage(mainWindow, STATE_CHANGE, 0, NULL); } else { isQueued = FALSE; } break; case STATE_CHANGE: switch ((int)wParam) { case -1: UnloadSelection(); UnloadDir(); EnableWindow(filesListCtrl, FALSE); EnableWindow(playButton, FALSE); EnableWindow(stopButton, FALSE); EnableMenuItem(menuBar, ID_REFRESH, MF_DISABLED); SetWindowText(dirLabel, NO_DIR_LOADED_LABEL); SetWindowText(npLabel, L"-"); SetWindowText(playButton, PLAY_LABEL); break; case 0: if (!path.empty()) { EnableWindow(filesListCtrl, TRUE); EnableWindow(playButton, TRUE); EnableWindow(stopButton, TRUE); EnableMenuItem(menuBar, ID_REFRESH, MF_ENABLED); SetWindowText(npLabel, NOT_PLAYING_LABEL); SetWindowText(playButton, PLAY_LABEL); break; } else { SendMessage(mainWindow, STATE_CHANGE, -1, 0); break; } case 1: if (!path.empty() && !selected.empty()) { if (currentState == 2) { mciSendString(L"resume mp3", NULL, 0, mainWindow); } else { if (isLoopEnabled) { mciSendString(L"play mp3 repeat", NULL, 0, mainWindow); } else { mciSendString(L"play mp3 notify", NULL, 0, mainWindow); } } EnableWindow(filesListCtrl, TRUE); EnableWindow(playButton, TRUE); EnableWindow(stopButton, TRUE); EnableMenuItem(menuBar, ID_REFRESH, MF_DISABLED); SetWindowText(npLabel, selected.c_str()); SetWindowText(playButton, PAUSE_LABEL); break; } else { SendMessage(mainWindow, STATE_CHANGE, 0, NULL); break; } case 2: mciSendString(L"pause mp3", NULL, 0, mainWindow); wstring pauseStringWS = selected + L" [PAUZA]"; LPCWSTR pauseString = pauseStringWS.c_str(); EnableWindow(filesListCtrl, TRUE); EnableWindow(playButton, TRUE); EnableWindow(stopButton, TRUE); EnableMenuItem(menuBar, ID_REFRESH, MF_DISABLED); SetWindowText(npLabel, pauseString); SetWindowText(playButton, L"Wznów"); break; } currentState = (int)wParam; break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return NULL; } //ABOUT DIALOG LOOP INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }