コマンドラインから取得したパスで、曲をmciSendCommandで再生しようとしているのですが、'\'がエスケープ文字としてとらえられてしまい、パスを正しく取得できません。このような状態になります↓。
warning C4129: 'D' : エスケープ シーケンスとして正しく認識されませんでした。
'\'を'\\'にすればいいというところまでは分かるのですが、文字列の操作が良く分かりません。
どうしたらよいか教えてもらえないでしょうか。
よろしくお願いします。
> '\'がエスケープ文字としてとらえられてしまい、パスを正しく取得できません。
コマンドラインオプションからの入力……ですよね??
> warning C4129: 'D' : エスケープ シーケンスとして正しく認識されませんでした。
該当するソースの周辺のコードを掲示されてはどうでしょう?
ソースはこんな感じです↓。
#include <windows.h>
#pragma comment(lib, "winmm.lib") // winmm.libをリンク
#define WS_NORESIZE WS_OVERLAPPED | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU
/* 変数宣言 */
int Width = 640;
int Height = 480;
LPSTR lpFileName; //ファイル名
MCI_OPEN_PARMS Mop;
MCIERROR mciErr;
TCHAR mciErrStr[512];
/* プロトタイプ宣言 */
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HWND hWnd;
MSG Msg;
WNDCLASS Wc;
lpFileName = lpCmdLine; //ファイル名の取得
ZeroMemory(&Wc, sizeof (WNDCLASS));
Wc.cbClsExtra = 0;
Wc.cbWndExtra = 0;
Wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
Wc.hCursor = LoadCursor(NULL, IDC_ARROW);
Wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
Wc.lpfnWndProc = (WNDPROC)WindowProc;
Wc.lpszClassName = TEXT("Form");
Wc.lpszMenuName = NULL;
Wc.style = CS_HREDRAW | CS_VREDRAW;
if (RegisterClass(&Wc) == 0) return -1;
hWnd = CreateWindowEx(WS_EX_CONTROLPARENT | WS_EX_WINDOWEDGE, TEXT("Form"),
TEXT("Caption"), WS_NORESIZE, 0, 0,
Width, Height, NULL, NULL, hInstance, NULL);
if (hWnd == NULL) return -1;
ShowWindow(hWnd, SW_SHOW);
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wPalam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
ZeroMemory(&Mop, sizeof (MCI_OPEN_PARMS));
Mop.dwCallback = (DWORD)hWnd;
Mop.lpstrAlias = NULL;
Mop.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_WAVEFORM_AUDIO;
Mop.lpstrElementName = lpFileName;
mciErr = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE |
MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT, (DWORD)&Mop);
if (mciErr)
{
mciGetErrorString(mciErr, mciErrStr, 512);
MessageBox(hWnd, mciErrStr, NULL, MB_OK | MB_ICONERROR);
}
else
mciSendCommand(Mop.wDeviceID, MCI_PLAY, 0, 0);
break;
case WM_DESTROY:
mciSendCommand(Mop.wDeviceID, MCI_CLOSE, 0, 0);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, uMsg, wPalam, lParam));
}
return 0;
}
どう見てもそのような警告は発せられないはずですが。
どの行でその警告が発せられたのですか?
68 : Mop.lpstrElementName = lpFileName; のところです。
コンパイル時にはエラーは出ないんですが、
Exeにファイル(*.wav)をドロップすると
"指定されたファイルが見つかりません。パスとファイル名が正しいかどうか確認してください。"
というメッセージが出たので、lpFileNameにファイルのフルパスを入れてコンパイルすると
'D' : "エスケープ シーケンスとして正しく認識されませんでした。"
というメッセージが出たんです。
例えば
C:\abc\testfile
というファイルを送ると「ファイルが見つからない」というメッセージが出るので
LPSTR lpFileName = "C:\abc\testfile";
として試したら「エスケープシークエンスとして(略)」というエラーが出たということですか?
もしそういう手法を取ったならエラーが出るのは当然です
理由はエスケープシークエンスの記述方法を調べればわかります
見当違いでしたらごめんなさい
むしろここではファイルが開けるかどうかだけを見るのではなく、
WinMainの引数として送られてくるlpCmdLineが指している内容が
本当に自分が意図したパスと同じであるかを調べてみては?
例えばMessageBox(hWnd,lpCmdLine,"test",MB_OK);
などで表示してみるとか
もしかしたら意図したものと違う内容が送られてきていて、
それゆえにファイルをうまく開けないのかもしれませんし
ちょっとよくない書き方があるので訂正
>もしそういう手法を取ったならエラーが出るのは当然です
手法というより書き方ですね
手法は別に問題ないですし
>'\'を含んだパスをそのまま文字列として扱ったら
>エラーが出るのは当然です
と書くべきでしたか
lpCmdLineは"D:\Music Folder\Test File.wav"と、うまくとれていました。
さっきいろいろ試したところ、
パスの中に空白があるとエラーが起きました。
Mop.lpstrElementName = "D:\MusicFolder\TestFile.wav" ○
Mop.lpstrElementName = "D:\Music Folder\Test File.wav" ×
空白があっても"D:\\Music Folder\\Test File.wav"とするとうまくいくんです。
それと"D:/Music Folder/Test File.wav"と'\'を'/'にしてもうまくいきました。
後はこれをlpCmdLineから受け取ったときに処理するだけだと思うんですけど
どうしたらいいでしょうか。
この場合lpCmdLineから受け取ったパスで開けない理由は\のせいではないです。
Windowsはプログラム起動時にドロップされたファイルのパスの中に空白があると""で囲んできますが、(XP Homeで確認)
ファイルを開く時に""で囲まれていると別のパスになってオープンに失敗するので、
「ファイルが見つかりません」と出てしまいます。
よって、MCIに投げる前に""で囲まれているかを確認して
囲まれていた場合は消去する必要があります。
解決しました。
fukuさんの言われたとおり、'"'を取り除いたらうまくいきました。
ありがとうございます。
ツイート | ![]() |