複数のWMAファイルアーティスト名・タイトルをCSVファイルに出力するGUIプログラム(32/64bit)

icon 項目のみ表示/展開表示の切り替え

概要

本プログラムにWMAファイルをドラッグ&ドロップするとタイトル、アルバムタイトル、アーティスト等をリスとビューに表示します。 右上の終了アイコンをクリックするとCSVファイル名を入力するコモンダイアログボックスが表示されるので、ファイル名を入力するとCSVファイルが作成されます。
ファイル名の指定時は自動的に拡張子は付かないので入力時に付加してください。
なお、CSVファイルはSJISで出力されます。

次に作成されたCSVファイルの例を示します。

"ファイル名","トラック","タイトル","参加アーティスト","アーティスト","アルバム","フルパス"
"01 ~introduction~.wma","1","~introduction~","島谷ひとみ","島谷ひとみ","シャンティ","D:\01 ~introduction~.wma"
"02 シャンティ.wma","2","シャンティ","島谷ひとみ","島谷ひとみ","シャンティ","D:\02 シャンティ.wma"
"03 亜麻色の髪の乙女.wma","3","亜麻色の髪の乙女","島谷ひとみ","島谷ひとみ","シャンティ","D:\03 亜麻色の髪の乙女.wma"
"14 farewell.wma","14","farewell","島谷ひとみ","島谷ひとみ","シャンティ","D:\14 farewell.wma"
"15 colors.wma","15","colors","島谷ひとみ","島谷ひとみ","シャンティ","D:\15 colors.wma"
"16 亜麻色の髪の乙女(ヒロ・クレタニ・リミックス).wma","16","亜麻色の髪の乙女(ヒロ・クレタニ・リミックス)","島谷ひとみ","島谷ひとみ","シャンティ","D:\16 亜麻色の髪の乙女(ヒロ・クレタニ・リミックス).wma"
"17.Single Hits Non-stop Mega Mix-Trans Misson Mega Mix- .wma","17","Single Hits Non-stop Mega Mix-Trans Misson Mega Mix- ","島谷ひとみ","島谷ひとみ","シャンティ","D:\17.Single Hits Non-stop Mega Mix-Trans Misson Mega Mix- .wma"
CSVファイルは、Excelなどの表計算ソフトやメモ帳などのテキストエディタで編集することができます。

変更履歴

2014.05.07 初版
2014.05.18 動作例の画像が表示されていなかったのを修正

テスト環境

コンパイラ

Visual C++ 2008/2013 Express 32/64bit UNICODE

実行環境

Windows XP Professional Service Pack 3 32bit(Virtual Box上の仮想マシーン)
Windows 7 Enterprise Service Pack 1 64bit

動作例

本プログラムの実行状態

プログラムソースの概要

gwmalist.cpp

_tWinMain

起動前にドラッグ&ドロップされた場合、そのファイル名を保存します。その後、ウィンドウを表示します。

WndProc

ウィンドウの初期化時にWndProc関数にWM_CREATEメッセージが発生するので、リスとビューの作成を行いドラッグ&ドロップを許可します。
ウィンドウサイズの変更時
ウィンドウのサイズ変更時にWndProc関数にWM_SIZEメッセージが発生するので、リスとビューの大きさをウィンドウにあわせて変更します。
ドラッグ&ドロップ
本プログラム起動時に引数があった場合は、リストボックスにその内容を設定します。 ファイルがドラッグ&ドラッグされるとWndProc関数にWM_DROPFILESメッセージが発生するので、DragQueryFile関数で最初にファイルの個数を取得し、次にファイル名を取得します。
取得されたファイル名より、wma_title_get関数でタイトル等を取得しリスとビューに表示します。
ウィンドウ終了時
ウィンドウが終了されるときにWndProc関数にWM_DESTROYメッセージが発生するので、CSVファイル名を取得するコモンダイアログボックスを表示します。
ファイル名が入力されたとき、そのファイルにタイトル等を出力し終了します。

wma_title_get

GetAttributeByName APIでWMAファイルからタイトル等を取得しリスとビューに内容を表示します。

ソースコード

gwmalist.cpp


// ドラッグ&ドロップされたWMAファイルのタイトル・アルバムタイトル・アーティスト名等をリストビューに表示する。
// 終了時にリストビューの内容をCSVファイルに保存する。

#include <windows.h>
#include <shlwapi.h>
#include <commctrl.h>
#include <tchar.h>
#include <wmsdk.h>
#include <stdio.h>

#pragma comment(lib,"shlwapi.lib")
#pragma comment(lib,"wmvcore.lib")


// 保存ファイル名の取得
BOOL GetSaveFileName(TCHAR* fname,int sz);

// WMAファイルのタイトル・アルバムタイトル・アーティスト名等をリスとビューに表示
bool wma_title_get(IWMMetadataEditor* pEditor,TCHAR* fname,int row);

// ウィンドウプロシージャー
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

// リスとビューの指定された行よりタイトル等を取得しファイルへ出力
void put_csv(FILE* fp,int row);

#define ID_LISTVIEW 2010


TCHAR* file=0;
HWND hList;
TCHAR* szClassName=TEXT("WMAlist");
HINSTANCE hInst;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,TCHAR* lpszCmdLine, int nCmdShow){
        hInst=hInstance;
        TCHAR f[MAX_PATH];
        HWND hWnd;
        MSG lpMsg;
          WNDCLASS myProg;
        if(lpszCmdLine[0]){
                if(lpszCmdLine[0]==_T('\"')){
                        _tcscpy_s(f,sizeof(f)/sizeof(TCHAR),lpszCmdLine+1);
                        f[ _tcslen(f) -1]=_T('\0');
                        file=f;
                }else
                        file=lpszCmdLine;
        }
        if(!hPreInst) {
                myProg.style=CS_HREDRAW | CS_VREDRAW;
                myProg.lpfnWndProc=WndProc;
                myProg.cbClsExtra=0;
                myProg.cbWndExtra=0;
                myProg.hInstance=hInstance;
                myProg.hIcon=NULL;
                myProg.hCursor=LoadCursor(NULL, IDC_ARROW);
                myProg.hbrBackground=(HBRUSH__ *)GetStockObject(WHITE_BRUSH);
                myProg.lpszMenuName=NULL;
                myProg.lpszClassName=szClassName;
                if(!RegisterClass(&myProg))
                        return FALSE;
        }
        hWnd = CreateWindow(szClassName,
                        TEXT("WMAファイルプロパティー一覧"),
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        CW_USEDEFAULT,
                        NULL,
                        NULL,
                        hInstance,
                        NULL);
                ShowWindow(hWnd, nCmdShow);
                UpdateWindow(hWnd);
                while (GetMessage(&lpMsg, NULL, 0, 0)) {
                        TranslateMessage(&lpMsg);
                        DispatchMessage(&lpMsg);
                }
                return int(lpMsg.wParam);
}

// 保存ファイル名の取得

BOOL GetSaveFileName(TCHAR* fname,int sz){
        OPENFILENAME o;
        fname[0]=_T('\0');
        ZeroMemory(&o,sizeof(o));
        o.lStructSize=sizeof(o);
        o.Flags=0;
        o.lpstrFile=fname;
        o.nMaxFile=sz;
        o.lpstrFilter=_TEXT("CSV(カンマ区切り)(*.CSV)\0");
        o.nFilterIndex=1;
        return GetSaveFileName(&o);
}

// リスとビューの指定された行よりタイトル等を取得しファイルへ出力

void put_csv(FILE* fp,int row){
        TCHAR buf[1024];
        char sjis[1024*2];

        LVITEM item;
        item.mask=LVIF_TEXT;
        item.iItem=row;
        item.pszText=buf;
        item.cchTextMax=sizeof(buf)/sizeof(TCHAR);
        for(int n=0;n<7;n++){
                item.iSubItem=n;
                ListView_GetItem(hList,&item);
                WideCharToMultiByte(932,0,buf,-1,sjis,sizeof(sjis),NULL,NULL);
                fprintf(fp,"\"%s\"",sjis);
                if(n != 6)
                        fprintf(fp,",");
                else
                        fprintf(fp,"\n");
        }
}

// ウィンドウプロシージャー


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    LV_COLUMN lvcol;
        IWMMetadataEditor* pEditor=NULL;
        HRESULT hr;
        TCHAR buf[MAX_PATH];
        HDROP hDrop;
        UINT fmax;
        int i,n;
        FILE* fp;

        switch(msg){
        case WM_CREATE:
                hList = CreateWindowEx(0,
                        WC_LISTVIEW, TEXT(""),
                        WS_CHILD | WS_VISIBLE | LVS_REPORT,
                        0, 0, 0, 0,
                        hWnd,
                        (HMENU)ID_LISTVIEW,
                        hInst,
                        NULL);
                lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
                lvcol.fmt = LVCFMT_LEFT;
                lvcol.cx = 64;
                lvcol.pszText = TEXT("ファイル名");
                lvcol.iSubItem = 0;
                ListView_InsertColumn(hList, 0, &lvcol);

                lvcol.cx = 48;
                lvcol.pszText = TEXT("トラック");
                lvcol.iSubItem = 1;
                ListView_InsertColumn(hList, 1, &lvcol);

                lvcol.cx = 48;
                lvcol.pszText = TEXT("タイトル");
                lvcol.iSubItem = 2;
                ListView_InsertColumn(hList, 2, &lvcol);

                lvcol.cx = 128;
                lvcol.pszText = TEXT("参加アーティスト");
                lvcol.iSubItem = 3;
                ListView_InsertColumn(hList, 3, &lvcol);

                lvcol.cx = 128;
                lvcol.pszText = TEXT("アーティスト");
                lvcol.iSubItem = 4;
                ListView_InsertColumn(hList, 4, &lvcol);

                lvcol.cx = 128;
                lvcol.pszText = TEXT("アルバム");
                lvcol.iSubItem = 5;
                ListView_InsertColumn(hList, 5, &lvcol);

                lvcol.cx = 128;
                lvcol.pszText = TEXT("フルパス");
                lvcol.iSubItem = 6;
                ListView_InsertColumn(hList, 6, &lvcol);
                DragAcceptFiles(hWnd, TRUE);
                break;

        case WM_DROPFILES:
                hDrop = (HDROP)wParam;
                fmax = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
                hr = WMCreateEditor(&pEditor);      // オブジェクトを作成
                n=(int)SendMessage(hList,LVM_GETITEMCOUNT,0,0);
                for (i = 0; i < (int)fmax; i++) {
                        DragQueryFile(hDrop, i, buf, sizeof(buf) / sizeof(TCHAR));
                        wma_title_get(pEditor,buf,n+i);
                }
                DragFinish(hDrop);
                break;
        case WM_SIZE:
                MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
                break;
        case WM_DESTROY:
                n=(int)SendMessage(hList,LVM_GETITEMCOUNT,0,0);
                if(0<n){
                        if(GetSaveFileName(buf,sizeof(buf)/sizeof(TCHAR))){
                                if(_tfopen_s(&fp,buf,_TEXT("w"))==0){
                                        fprintf(fp,"\"ファイル名\",\"トラック\",\"タイトル\",\"参加アーティスト\",\"アーティスト\",\"アルバム\",\"フルパス\"\n");
                                        for(i=0;i<n;i++)
                                                put_csv(fp,i);
                                        fclose(fp);
                                }
                        }
                }
                PostQuitMessage(0);
                break;
        default:
                return(DefWindowProc(hWnd, msg, wParam, lParam));
        }
        return (0L);
}

// WMAファイルのタイトル・アルバムタイトル・アーティスト名等をリスとビューに表示


bool wma_title_get(IWMMetadataEditor* pEditor,TCHAR* fname,int row){
        LV_ITEM item;
        item.mask = LVIF_TEXT  | LVIF_PARAM;
        item.pszText = PathFindFileName(fname); //      ファイル名の位置を取得
        item.iItem = row;
        item.iSubItem = 0;
        item.lParam = row;
        ListView_InsertItem(hList, &item);

        bool flag=true;
        HRESULT hr;
        IWMHeaderInfo3* pHeaderInfo=NULL;

        hr=pEditor->Open(fname);
        if(FAILED(hr)){
                MessageBox(0,fname,_TEXT("ファイルが開けません"),MB_OK);
                return false;

        }
        pEditor->QueryInterface(IID_IWMHeaderInfo3,(void**)&pHeaderInfo);

        WORD wStreamNum = 0;
        WMT_ATTR_DATATYPE Type;
        WORD cbLength=0;

        TCHAR* getname;
        TCHAR pwszTitle[1024];

//      トラック番号を取得
        Type=WMT_TYPE_STRING;
        getname=_TEXT("WM/TrackNumber");
        pwszTitle[0]=_T('\0');

        hr=pHeaderInfo->GetAttributeByName(&wStreamNum,getname,&Type, NULL, &cbLength );
        hr = pHeaderInfo->GetAttributeByName( &wStreamNum, getname, &Type,(BYTE *) pwszTitle, &cbLength );
        if(Type==WMT_TYPE_DWORD){
                DWORD v=*((DWORD*)pwszTitle);
                _stprintf_s(pwszTitle,sizeof(pwszTitle)/sizeof(TCHAR),_TEXT("%i"),v);

        }
        item.mask = LVIF_TEXT;
        item.pszText = pwszTitle;
        item.iItem = row;
        item.iSubItem = 1;
        ListView_SetItem(hList, &item);

//      タイトルを取得
        Type=WMT_TYPE_STRING;
        getname=_TEXT("Title");
        pwszTitle[0]=_T('\0');
        hr=pHeaderInfo->GetAttributeByName(&wStreamNum,getname,&Type, NULL, &cbLength );
        hr = pHeaderInfo->GetAttributeByName( &wStreamNum, getname, &Type,(BYTE *) pwszTitle, &cbLength );

        item.mask = LVIF_TEXT;
        item.pszText = pwszTitle;
        item.iItem = row;
        item.iSubItem = 2;
        ListView_SetItem(hList, &item);

//      参加アーティストを取得
        Type=WMT_TYPE_STRING;
        getname=_TEXT("Author");
        pwszTitle[0]=_T('\0');
        hr=pHeaderInfo->GetAttributeByName(&wStreamNum,getname,&Type, NULL, &cbLength );
        hr = pHeaderInfo->GetAttributeByName( &wStreamNum, getname, &Type,(BYTE *) pwszTitle, &cbLength );

        item.mask = LVIF_TEXT;
        item.pszText = pwszTitle;
        item.iItem = row;
        item.iSubItem = 3;
        ListView_SetItem(hList, &item);

        Type=WMT_TYPE_STRING;
        getname=_TEXT("WM/AlbumArtist");
        pwszTitle[0]=_T('\0');
        hr=pHeaderInfo->GetAttributeByName(&wStreamNum,getname,&Type, NULL, &cbLength );
        hr = pHeaderInfo->GetAttributeByName( &wStreamNum, getname, &Type,(BYTE *) pwszTitle, &cbLength );

        item.mask = LVIF_TEXT;
        item.pszText = pwszTitle;
        item.iItem = row;
        item.iSubItem = 4;
        ListView_SetItem(hList, &item);

//      アルバムアーティストを取得
        Type=WMT_TYPE_STRING;
        getname=_TEXT("WM/AlbumTitle");
        pwszTitle[0]=_T('\0');
        hr=pHeaderInfo->GetAttributeByName(&wStreamNum,getname,&Type, NULL, &cbLength );
        hr = pHeaderInfo->GetAttributeByName( &wStreamNum, getname, &Type,(BYTE *) pwszTitle, &cbLength );

        item.mask = LVIF_TEXT;
        item.pszText = pwszTitle;
        item.iItem = row;
        item.iSubItem = 5;
        ListView_SetItem(hList, &item);

//      ファイル名の表示
        item.mask = LVIF_TEXT;
        item.pszText = fname;
        item.iItem = row;
        item.iSubItem = 6;
        ListView_SetItem(hList, &item);

        pHeaderInfo->Release();
        pEditor->Close();
        return flag;
}

実行ファイルとソースファイルのダウンロード