どこが間違っているかを、ご教示していただけないでしょうか。(音源は、ネット上に公開されている著作権フリーのものを利用しております) MFP【Marron Fields Production】
こちらのソースは最新のものではありません。
CustomDraw部分
► スポイラーを表示
#include "strdef.h"
LRESULT CustomDrawProc(HWND hWnd, InternalData indata,WPARAM wp, LPARAM lp)
{
LPNMHDR lpNotify = (LPNMHDR)lp;
LPNMCUSTOMDRAW lpDraw;
HBRUSH brush, oldBrush;
int Pos, max, pos_x;
RECT rc;
switch (lpNotify->code)
{
case NM_CUSTOMDRAW:
if (lpNotify->hwndFrom == indata.hTrack)
{
lpDraw = (LPNMCUSTOMDRAW)lpNotify;
switch (lpDraw->dwDrawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
switch (lpDraw->dwItemSpec)
{
case TBCD_CHANNEL:
//再生が終わった場所は青く塗る
//現在位置の取得
Pos = SendMessage(indata.hTrack, TBM_GETPOS, 0, 0);
//最大数の取得
max = indata.maxSrc;
if (!max)
max++;
//比計算
//max : rc.right-rc.left = pos : x
pos_x = (lpDraw->rc.right - lpDraw->rc.left)*Pos / max;
//とりあえず真っ白に塗り込む
FillRect(lpDraw->hdc, &lpDraw->rc, (HBRUSH)GetStockObject(WHITE_BRUSH));
//左側
rc = lpDraw->rc;
rc.right =(LONG)pos_x;
// rc.left = 0;
brush = CreateSolidBrush(RGB(0, 0, 255));
oldBrush = (HBRUSH)SelectObject(lpDraw->hdc, brush);
FillRect(lpDraw->hdc, &rc, brush);
SelectObject(lpDraw->hdc, oldBrush);
DeleteObject(brush);
return CDRF_SKIPDEFAULT;
case TBCD_THUMB:
brush = CreateSolidBrush(RGB(255, 255, 255));
oldBrush = (HBRUSH)SelectObject(lpDraw->hdc, brush);
Ellipse(lpDraw->hdc, lpDraw->rc.left, lpDraw->rc.top, lpDraw->rc.right, lpDraw->rc.bottom);
SelectObject(lpDraw->hdc, oldBrush);
DeleteObject(brush);
return CDRF_SKIPDEFAULT;
}
break;
}
break;
}
}
return FORWARD_WM_NOTIFY(hWnd, wp, lp, DefWindowProc);
}
► スポイラーを表示
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
static InternalData indata;
static MCI_PLAY_PARMS play;
static MCI_STATUS_PARMS mciStatus;
static HWND hMCI;
RECT rc;
switch (msg) {
case WM_DESTROY:
mciSendCommandW(indata.open.wDeviceID, MCI_CLOSE, 0, 0);
PostQuitMessage(0);
return 0;
case WM_CREATE:
InitCommonControls();
InitSoundStruct(L"C:\\Games\\Minecraft\\testsound.mp3", L"MPEGVideo", &indata.open);
SetTimer(hwnd, 1, 999, NULL);
play.dwCallback = (DWORD)hwnd;
//トラックバー作成
indata.hTrack = CreateTrackbar(hwnd);
return 0;
case WM_TIMER:
if (indata.Status)
{
DWORD dwSrc, dwMin, dwSrc_all, dwMin_all;
WCHAR Temp[512];
mciStatus.dwItem = MCI_STATUS_POSITION;
mciSendCommandW(indata.open.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&mciStatus);
//秒と分を取得(今は使っていない)
dwSrc = mciStatus.dwReturn / 1000; //msrc->src
dwMin = dwSrc / 60;
dwSrc %= 60;
dwSrc_all = indata.maxSrc % 60;
dwMin_all = indata.maxSrc / 60;
swprintf_s(Temp, L"%02d:%02d", dwMin, dwSrc);
SendMessageW(indata.hTrack, TBM_SETPOS, TRUE, mciStatus.dwReturn / 1000);
SetWindowTextW(hwnd, Temp);
}
return 0;
case WM_LBUTTONDOWN:
mciSendCommandW(indata.open.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD_PTR)& play);
//長さを取得
//とりあえず戻り値は'm'srcにする
mciStatus.dwItem = MCI_FORMAT_MILLISECONDS;
mciSendCommandW(indata.open.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&mciStatus);
//局の長さを取得
mciStatus.dwItem = MCI_STATUS_LENGTH;
mciSendCommandW(indata.open.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&mciStatus);
indata.Status = TRUE;
indata.maxSrc = mciStatus.dwReturn / 1000;
//トラックバーに関する設定(最後まで再生したときにつまみが一番右側にいるようにする)
SendMessageW(indata.hTrack, TBM_SETRANGE, TRUE, MAKELPARAM(0, indata.maxSrc));
return 0;
case WM_SIZE:
GetClientRect(hwnd, &rc);
MoveWindow(indata.hTrack, 0, rc.bottom - 25, LOWORD(lp), HIWORD(lp), TRUE);
return 0;
case WM_NOTIFY:
return CustomDrawProc(hwnd, indata, wp, lp);
case MM_MCINOTIFY:
if (lp == indata.open.wDeviceID) {
if (wp == MCI_NOTIFY_SUCCESSFUL) {
//シークバーを先頭に戻す
mciSendCommandW(indata.open.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, 0);
//再生終了
indata.Status = FALSE;
}
return 0;
}
break;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
► スポイラーを表示
int InitSoundStruct(LPCWSTR lpFilePath,LPCWSTR lpstrDeviceType,MCI_OPEN_PARMSW *retTemp)
{
MCI_OPEN_PARMSW MPEGStruct;
MCIERROR result;
TCHAR MsgBuf[1024];
ZeroMemory(&MPEGStruct, sizeof(MCI_OPEN_PARMSW));
MPEGStruct.lpstrDeviceType = lpstrDeviceType;
MPEGStruct.lpstrElementName = lpFilePath;
result = mciSendCommandW(
0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD_PTR)&MPEGStruct
);
if (result)
{
mciGetErrorStringW(result, MsgBuf, sizeof(MsgBuf));
OutputDebugStringEx(L"%s\n",MsgBuf);
*retTemp = MPEGStruct;
return
create_temp_file(lpFilePath, lpstrDeviceType, retTemp);
}
*retTemp = MPEGStruct;
return TRUE;
}
//synchsafeを10新数に変換
int unsynchsafe(char size[4])
{
int ToRet = 0;
if ((size[0] & 0x0F) || ((size[0] | size[1] | size[2] | size[3]) & 0x80))
{
}
else {
int Footer = size[0] & 0x10;
ToRet = size[0] << 21;
ToRet += size[1] << 14;
ToRet += size[2] << 7;
ToRet += size[3];
ToRet += 10;
if (Footer)
ToRet += 10;
}
return ToRet;
}
//ID3タグがあるとき、(少なくとも自分の環境では)MCIは読み込んでくれないのでとりあえずtempファイルに書き出し、それを読み込ませる
int create_temp_file(LPCWSTR lpFilePath,LPCWSTR lpstrDeviceType,MCI_OPEN_PARMSW *retTemp)
{
FILE *fp,*wfp;
ID3V2HEADER head; //ID3プロファイルがあるかどうか
DWORD size = 0;
char mp3head[3] = { 0 }, temp[16] = { 0 };
// char _size[32];
_wfopen_s(&fp, lpFilePath, L"rb");
if (!fp)
{
OutputDebugStringEx(
L"%s:ファイル\"%s\"\nの読み込みに失敗しました。\n",
__FUNCSIG__, lpFilePath
);
return 0;
}
ZeroMemory(&head, sizeof(head));
fread(&head, sizeof(head), 1, fp);
//strcmpだと比較できない(\0がないため)
if (head.tag[0] != 'I' ||
head.tag[1] != 'D' ||
head.tag[2] != '3'
)
{
OutputDebugStringW(L"ID3 header not found\n");
fclose(fp);
return 0;
}
//
//
//syncfaceを普通の10進数に変換
size = unsynchsafe(head.size);
//headerはとりあえず読み飛ばす
long file_size;
char *buffer;
//ファイルサイズを取得する
//戦闘に移動
fseek(fp, 0, SEEK_SET);
if (fseek(fp, 0, SEEK_END) != 0) {
/* エラー処理 */
goto err;
}
file_size = ftell(fp);
if (file_size == -1) {
/* エラー処理 */
goto err;
}
buffer = (char*)malloc(file_size - size);
if (buffer == NULL) {
/* エラー処理 */
goto err;
}
//mp3の先頭に移動
fseek(fp, size, SEEK_SET);
//本体読み込み
fread(buffer, file_size - size, 1, fp);
_wfopen_s(&wfp, TEMP_FILE_NAME, L"wb");
if (!wfp)
goto err;
fwrite(buffer, file_size - size, 1, wfp);
fclose(fp);
fclose(wfp);
free(buffer);
{
MCI_OPEN_PARMSW MPEGStruct;
MCIERROR result;
TCHAR MsgBuf[1024];
ZeroMemory(&MPEGStruct, sizeof(MCI_OPEN_PARMSW));
MPEGStruct.lpstrDeviceType = lpstrDeviceType;
MPEGStruct.lpstrElementName = TEMP_FILE_NAME;
result = mciSendCommandW(
0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD_PTR)&MPEGStruct
);
if (result)
{
mciGetErrorStringW(result, MsgBuf, sizeof(MsgBuf));
OutputDebugStringEx(L"%s",MsgBuf);
*retTemp = MPEGStruct;
goto Err;
}
*retTemp = MPEGStruct;
return TRUE;
}
return TRUE;
err:
fclose(fp);
return FALSE;
}
► スポイラーを表示
include <windows.h>
#include <stdio.h>
#include <string.h>
#include <mmsystem.h>
#include <windows.h>
#include <vfw.h>
#include <commctrl.h>
#include <stdio.h>
#include <assert.h>
#include <tchar.h>
#include <shlwapi.h>
#include <windowsx.h>
#pragma comment( lib, "shlwapi.lib" )
#pragma comment(lib,"msvfw32.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib, "comctl32.lib")
#define TEMP_FILE_NAME L"soundfile.mp3"
typedef struct tagID3V2HEADER
{
char tag[3];
char version[2];
char flags;
char size[4]; //syncface
} ID3V2HEADER;
typedef struct tagInternalData
{
//現在再生しているデータに関するもの
DWORD maxSrc; //現在再生しているものの、長さ(単位:src)
MCI_OPEN_PARMS open;
BOOL Status; //現在再生しているかどうか
//トラックバーコントロール
HWND hTrack;
}InternalData;
int InitSoundStruct(LPCWSTR lpFilePath, LPCWSTR lpstrDeviceType, MCI_OPEN_PARMSW *retTemp);
//ID3ヘッダに関する処理
int create_temp_file(LPCWSTR lpFilePath, LPCWSTR lpstrDeviceType, MCI_OPEN_PARMSW *retTemp);
HWND CreateTrackbar(HWND hWnd);
LRESULT CustomDrawProc(HWND hWnd, InternalData indata , WPARAM wp, LPARAM lp);
//OutputDebugStringWの改良版
int OutputDebugStringEx(LPCWSTR lpOutputString, ...);