ドラッグ&ドロップされた複数のWMAファイルの画像を変更するGUIプログラム(32/64bit)

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

概要

ドラッグ&ドロップされた複数のWMAファイルのアルバムアートの変更を行います。

テスト環境

コンパイラ

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

実行環境

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

動作例


プログラムソースの概要

gwmaimg4.cpp

_tWinMain

ダイアログを表示します。

DlgProc1

ダイアログボックスの初期化時にDlgProc1関数にWM_INITDIALOGメッセージが発生するので、ドラッグ&ドロップを許可します。
ドラッグ&ドロップ
WMAファイルがドラッグ&ドロップされるとDlgProc1関数にWM_DROPFILESメッセージが発生するので、ファイル名を取得します。
OKボタン
ボタンがクリックされると、DlgProc1関数にWM_COMMANDメッセージが発生するので、OKボタンのメッセージの場合、Jpegファイルを取得するコモンダイアログボックスを表示し、ファイル名が得られたならファイルサイズを調べます。
ファイルサイズ分のメモリをGlobalAlloc APIで確保しハンドルを取得します。その後メモリをロックし先頭のアドレスを取得します。
メモリをストリームとして扱うため、CreateStreamOnHGlobal を実行しメモリストリームのハンドルを得ます。(ここでは画像を表示しないのでメモリーストリム化は不要ですが、コードの流用をしています。)
そのアドレスにJpegイメージを読み込みます。
WMAファイルのWM/Picture属性を検索し、属性が無ければAddAttribute、有ればModifyAttributeで画像を追加または変更します。

ソースコード

gwmaimg4.cpp

// ドラッグ&ドロップされたWMAファイルのアルバムアートを変更する

#include <windows.h>
#include <tchar.h>
#include <wmsdk.h>
#include <stdio.h>
#include "resource.h"

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


// ファイル名を取得する
BOOL GetFileName(TCHAR* fname,int sz);

// ダイアログボックスのプロシージャー
LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

// WMAファイルのアルバムアートを変更する
bool wma_jpg_chg(IWMMetadataEditor* pEditor,TCHAR* fname);

//      メモリストリームを作成する
bool jpg_stream(IStream** pIStream,BYTE** jpg_mem,int sz,HGLOBAL* hBuf);

TCHAR* file=0;
BYTE* jpg_mem=0;
int sz;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInst,TCHAR* lpszCmdLine, int nCmdShow){
        TCHAR f[MAX_PATH];
        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(DialogBox(hInstance, TEXT("DLG1"), 0, (DLGPROC)DlgProc1)){

        }
        return 0;
}


// ダイアログボックスのプロシージャー

LRESULT CALLBACK DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
        IWMMetadataEditor* pEditor=NULL;
        HRESULT hr;
        TCHAR buf[MAX_PATH];
        HDROP hDrop;
        UINT fmax;
        FILE* fp;
        static HGLOBAL hBuf=0;
        static IStream* pIStream=0;
        int i;

        static bool edit=false;
        switch (msg) {
                case WM_INITDIALOG:
                        DragAcceptFiles(hDlg, TRUE);
                        if (file)
                                SendMessage(GetDlgItem(hDlg, IDC_LISTBOX1), LB_ADDSTRING, 0, (LPARAM)file);
                        return TRUE;
                case WM_DROPFILES:
                        hDrop = (HDROP)wParam;
                        fmax = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
                        for (i = 0; i < (int)fmax; i++) {
                                DragQueryFile(hDrop, i, buf, sizeof(buf) / sizeof(TCHAR));
                                SendMessage(GetDlgItem(hDlg, IDC_LISTBOX1), LB_ADDSTRING, 0, (LPARAM)buf);
                        }
                        DragFinish(hDrop);
                        break;
                case WM_COMMAND:
                        switch (LOWORD(wParam)) {
                                case IDOK:
                                        fmax = (UINT)SendMessage(GetDlgItem(hDlg, IDC_LISTBOX1), LB_GETCOUNT, 0, 0);
                                        if(0<fmax){
                                                if(GetFileName(buf,sizeof(buf)/sizeof(TCHAR))){
                                                        if(_tfopen_s(&fp,buf,_TEXT("rb"))==0){
                                                                fseek(fp,0,SEEK_END);
                                                                sz=ftell(fp);
                                                                fseek(fp,0,SEEK_SET);
                                                                if(jpg_stream(&pIStream,&jpg_mem,sz,&hBuf)==false){
                                                                        MessageBox(hDlg,_TEXT("メモリ確保に失敗しました。"),_TEXT("エラー"),MB_OK);
                                                                        fclose(fp);
                                                                        GlobalFree(hBuf);
                                                                        EndDialog(hDlg, TRUE);
                                                                }
                                                                fread(jpg_mem,sizeof(BYTE),sz,fp);
                                                                fclose(fp);

                                                                hr = WMCreateEditor(&pEditor);      // オブジェクトを作成
                                                                for (i = 0; i < (int)fmax; i++){
                                                                        SendMessage(GetDlgItem(hDlg, IDC_LISTBOX1), LB_GETTEXT, i, (LPARAM)buf);
                                                                        wma_jpg_chg(pEditor, buf);
                                                                }
                                                                MessageBox(hDlg, _TEXT("変換しました"), _TEXT("メッセージ"), MB_OK);
                                                        }
                                                }else{
                                                                MessageBox(hDlg, _TEXT("Jpegファイルが開けません"), _TEXT("エラー"), MB_OK);
                                                }
                                        }
                                        EndDialog(hDlg, TRUE);
                                        return TRUE;
                                case IDCANCEL:
                                        EndDialog(hDlg,FALSE);
                                default:
                                        return FALSE;
                        }
                        default:
                                return FALSE;
        }
        return TRUE;
}

// ファイル名を取得する

BOOL GetFileName(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("wma\0");
        o.nFilterIndex=1;
        return GetOpenFileName(&o);
}

TCHAR* errstr(HRESULT v){
        switch(v){
                case S_OK:      return _TEXT("成功");
                case E_INVALIDARG:      return _TEXT("違法なパラメータの組合せ、データ型または属性が、使われました。");
                case E_NOTIMPL: return _TEXT("実装されません。");
                case E_POINTER: return _TEXT("ポインターは、有効でありません");
                case NS_E_ATTRIBUTE_READ_ONLY:  return _TEXT("属性は変わることができません。");
                case NS_E_INVALID_REQUEST:      return _TEXT("wStreamNumは有効な番号でありません、または、属性がwIndexにありません");
                default: return _TEXT("不明なエラーです。");
        }
}

// WMAファイルのアルバムアートを変更する

bool wma_jpg_chg(IWMMetadataEditor* pEditor,TCHAR* fname){

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

        hr=pEditor->Open(fname);
        pEditor->QueryInterface(IID_IWMHeaderInfo3,(void**)&pHeaderInfo);

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

        TCHAR* getname;
        TCHAR pwszTitle[1024];

        WM_PICTURE pP;
        int index=-1;
        WORD cAttr=0;
        DWORD cbValue=0;

        hr = pHeaderInfo->GetAttributeCountEx(0xffff,&cAttr);
        for(int i=0;i<cAttr;i++){
                cbLength=sizeof(pwszTitle)/sizeof(TCHAR);
                hr=pHeaderInfo->GetAttributeByIndexEx(wStreamNum,i,pwszTitle,&cbLength,&Type,NULL,NULL,&cbValue);
                if(_tcscmp(pwszTitle,g_wszWMPicture)==0){
                        index=i;
                        break;
                }
        }

        Type=WMT_TYPE_BINARY;
        getname=(TCHAR*)g_wszWMPicture;
        pP.bPictureType=3;
        pP.dwDataLen=sz;
        pP.pbData=jpg_mem;
        pP.pwszDescription=_TEXT("");
        pP.pwszMIMEType=_TEXT("image/jpeg");
        cbLength = (WORD)(sz+(_tcslen(pP.pwszDescription)+_tcslen(pP.pwszMIMEType)+2)*sizeof(TCHAR)+sizeof(pP));
        WORD d=0;
        if(index<0)
                hr=pHeaderInfo->AddAttribute(wStreamNum, getname,&d,Type,0,(BYTE*)&pP,cbLength);
        else
                hr=pHeaderInfo->ModifyAttribute(wStreamNum, index, Type,0,(BYTE*)&pP,cbLength);
        if(hr!=S_OK){
                MessageBox(0,errstr(hr),_TEXT("Set/Modify Attribute API Error"),MB_OK);

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

//      メモリストリームを作成する

bool jpg_stream(IStream** pIStream,BYTE** jpg_mem,int sz,HGLOBAL* hBuf){
        *hBuf=GlobalAlloc(GMEM_MOVEABLE,sz);
        if(*hBuf==0){
                MessageBox(0,_TEXT("GlobalAlloc APIでのメモリの確保に失敗しました"),_TEXT("エラー"),MB_OK);
                return false;
        }
        *jpg_mem=(BYTE*)GlobalLock(*hBuf);
        if(*jpg_mem==0){
                MessageBox(0,_TEXT("GlobalLock APIでのメモリのロックに失敗しました"),_TEXT("エラー"),MB_OK);
                GlobalFree(*hBuf);
                return false;
        }
        *pIStream=0;
        if(CreateStreamOnHGlobal(*hBuf,FALSE,pIStream)!=S_OK){
                MessageBox(0,_TEXT("CreateStreamOnHGlobal APIでのメモリストリームの作成に失敗しました"),_TEXT("エラー"),MB_OK);
                GlobalFree(*hBuf);
                return false;
        }
        return true;
}

resource.h

#define IDC_LISTBOX1    2001

resource.rc

#include <windows.h>
#include "resource.h"


DLG1 DIALOG DISCARDABLE  0, 0, 320, 221
STYLE DS_MODALFRAME | WS_POPUP
CAPTION "WMAファイルアルバムアートの変更"
FONT 9, "MS Pゴシック"
BEGIN
        LTEXT                   "ここへファイルをドラッグドロップしてください", -1, 7, 7, 168, 10

        CONTROL "ListBox", IDC_LISTBOX1, "LISTBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_DISABLENOSCROLL, 7, 21, 306, 163

        DEFPUSHBUTTON   "OK(&O)",IDOK,100,197,50,14
        PUSHBUTTON      "キャンセル(&C)",IDCANCEL,157,197,50,14
END

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