「ID3タグの読み込み 第3部」では、MFCを使った用例とサンプルプログラムを紹介します。
MFCにおいてこのCID3Fileクラスを使用して、実際に画像を表示する方法を解説します。
まずはCID3Fileクラスのインスタンスへのポインタ定義のあるダイヤログクラスのヘッダーファイルの一部分です。
class CMP3File;
class CID3File;
class CImageDlg;
// CMp3PropDlg dialog
class CMp3PropDlg : public CDialog
{
DECLARE_DYNAMIC(CMp3PropDlg)
public:
CMp3PropDlg(CMP3File* pMP3File,CWnd* pParent = NULL); // standard constructor
virtual ~CMp3PropDlg();
// Dialog Data
enum { IDD = IDD_DIALOG_MP3PROPERTIES };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
//ダイヤログ上のあるコントロールの更新
void Update();
//リストビューのアップデート
BOOL UpdateListView();
protected:
virtual void OnOK();
CMP3File* m_pMP3File; //対象とするCMP3Fileクラスへのポインタ
private:
CID3File* m_pId3v1; //ID3v1タグを処理する為のCID3Fileクラスへのポインタ
CID3File* m_pId3v2; //ID3v2タグを処理する為のCID3Fileクラスへのポインタ
CImageDlg* m_pDlgImage;//画像表示用ダイヤログクラスへのポインタ
int m_iItemClicked; //最後にクリックされたリストビューの行番号
...
...
//タグバージョンの設定
BOOL SetTagVersion(CID3File* pID3File,int iItem);
...
...
BOOL m_bID3TagModified; //ID3タグの内容変更フラグ
CListCtrl m_listID3Tag; //ID3タグの内容を表示する為のリストビュー用DDX変数
...
...
//リストビュー右クリックイベント処理
afx_msg void OnNMRclickListId3tag(NMHDR *pNMHDR, LRESULT *pResult);
//新規フレームの挿入
afx_msg void OnPopupInsertframe();
//指定行フレームの編集
afx_msg void OnPopupEditframe();
//指定行フレームの削除
afx_msg void OnPopupDeleteframe();
//すべてのID3タグの削除
afx_msg void OnPopupDeletetag();
//ID3タグの生データをMP3ファイルに書き込みます。
afx_msg void OnBnClickedButtonSaveID3tag();
};
次にダイヤログクラスの初期化関数です。
BOOL CMp3PropDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
//CID3Fileクラスのインスタンスを作成します。
m_pId3v1=new CID3File();
m_pId3v2=new CID3File();
m_bID3TagModified=FALSE;
//画像表示用のモードレスダイヤログを作成します。
m_pDlgImage=new CImageDlg(this);
m_pDlgImage->Create(IDD_DIALOG_IMAGE);
...
...
//ダイヤログ上のすべてのコントロールを更新します。
void Update();
GotoDlgCtrl(&m_comboChannel);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
ダイヤログ上のすべてのコントロールを更新する関数です。
//ダイヤログ上のすべてのコントロールの更新
void CMp3PropDlg::Update()
{
ASSERT(AfxIsValidAddress(m_pMP3File,sizeof(CMP3File)));
...
...
//リストビューの内容を更新します。
UpdateListView();
//ダイヤログ上のコントロールを更新します。
UpdateData(FALSE);
}
ID3タグの内容を読み出して、リストビューの内容を更新する関数です。
//リストビューの更新
BOOL CMp3PropDlg::UpdateListView()
{
ASSERT(AfxIsValidAddress(m_pMP3File,sizeof(CMP3File)));
ASSERT(AfxIsValidAddress(m_pId3v1,sizeof(CID3File)));
ASSERT(AfxIsValidAddress(m_pId3v2,sizeof(CID3File)));
//現在のCMP3Fileクラス内にあるID3v1/ID3v2タグの生データのサイズ及び、ポインタを取得します。
int v1size=(int)m_pMP3File->m_byteId3v1.GetSize();
int v2size=(int)m_pMP3File->m_byteId3v2.GetSize();
BYTE* v1data=m_pMP3File->m_byteId3v1.GetData();
BYTE* v2data=m_pMP3File->m_byteId3v2.GetData();
//ID3v1/ID3v2タグの内容を解析します。
int v1frames=0;
int v2frames=0;
if ((v1size)&&(v1data))
v1frames=m_pId3v1->Parse(v1data,v1size);
if ((v2size)&&(v2data))
v2frames=m_pId3v2->Parse(v2data,v2size);
//リストビューのアイテムを削除します。
m_listID3Tag.DeleteAllItems();
//リストビューにID3v1/ID3v2タグの内容を書き込みます。
UINT nFrames=v1frames+v2frames;
BOOL bImageAttached=FALSE; //最初の画像だけ読み出すようにします。
for (UINT i=0;i<nFrames;i++){
//ID3v1をすべて書き込んでから、その後にID3v2タグを書き込むようにします。
CID3File* pId3=(i<(UINT)v1frames)?m_pId3v1:m_pId3v2;
int indexFrame=(i<(UINT)v1frames)?i:i-v1frames;
//ID3v1/ID3v2タグに該当するCID3Fileクラスから、該当する番号のフレームの内容を読み出します。
pId3->GetFrame(indexFrame);
//一番目のカラムにフレームIDを書き込みます。
int index=m_listID3Tag.InsertItem(i,(LPCTSTR)pId3->m_strID);
if (index==-1) break;
//二番目以降のカラムに、それぞれの項目に該当する内容を書き込みます。
int subItem=1;
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strTitle);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strDesc);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strText);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strTextEnc);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strImmediate);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strBinary);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strTimeStamp);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strPictureName);
m_listID3Tag.SetItemText(index,subItem++,pId3->m_strVersion);
//画像用メモリーファイルにデータがある場合。
UINT imageSize=pId3->m_memfileImage.GetLength();
if (imageSize){
ASSERT(m_pDlgImage);
//まだ画像を読み込んでいない場合。
if (!bImageAttached){
//引数に画像用メモリーファイルを入力して、画像表示用ダイヤログを更新します。
m_pDlgImage->Update(pId3->m_memfileImage,i);
//画像表示用ダイヤログのタイトルに画像名を書き込みます。
m_pDlgImage->SetWindowText(pId3->m_strPictureName.GetBuffer());
//画像表示用ダイヤログの表示状態を、このダイヤログ(親)に合わせます。
int iShow=(IsWindowVisible())?SW_SHOW:SW_HIDE;
m_pDlgImage->ShowWindow(iShow);
//画像読み込み済みにします。
bImageAttached=TRUE;
}
}
}
//表示画像がない場合は画像表示用ダイヤログを消します。
if (!bImageAttached){
m_pDlgImage->Update(0,0);
m_pDlgImage->ShowWindow(SW_HIDE);
}
return TRUE;
}
画像表示用ダイヤログでは、画像データからビットマップハンドルを得るために以下のインクルード定義が必要です。
#include "JpegFile.h"
#include "PNGFile.h"
上記インクルード定義で必要となるファイルです。尚以下のファイルの使い方等についてはJPEGファイルの読み込み、PNGファイルの読み込みをご参照ください。
JpegFile.h JpegFile.cpp
PNGFile.h PNGFile.cpp
画像表示用ダイヤログのクラス定義です。
// CImageDlg dialog
class CImageDlg : public CDialog
{
DECLARE_DYNAMIC(CImageDlg)
public:
CImageDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CImageDlg();
// Dialog Data
enum { IDD = IDD_DIALOG_IMAGE };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
CStatic m_stImage; //ID3タグの内容を表示する為のピクチャーボックス用DDX変数
int m_indexFrame; //現在のビットマップハンドルに関係するフレーム番号を保存します。
//ビットマップハンドルから、ピクチャーボックスを更新します。
void Update(HBITMAP hBitmap,int indexFrame);
//CFileクラスから画像を読み込んで、ピクチャーボックスを更新します。
void Update(CFile& infile,int indexFrame);
//現在ビットマップハンドルが、存在するかどうか?
BOOL HasImage(){return (m_stImage.GetBitmap())?TRUE:FALSE;};
};
最後に画像表示用ダイヤログの更新関数です。
//CFileクラスから画像を読み込んで、ピクチャーボックスを更新します。
void CImageDlg::Update(CFile& infile,int indexFrame)
{
//JPEG画像として読み込みます。
HBITMAP hBitmap=_JpegStreamIn(&infile);
//読み込めない場合は、PNG画像として再度読み込みます。
if (!hBitmap) hBitmap=_PNGStreamIn(&infile);
//読み込んだビットマップハンドルで、画像を更新します。
Update(hBitmap,indexFrame);
}
//ビットマップハンドルから、ピクチャーボックスを更新します。
void CImageDlg::Update(HBITMAP hBitmap,int indexFrame)
{
//ビットマップハンドルからBITMAP構造体を取得します。
BITMAP bm={0};
if (!::GetObject(hBitmap,sizeof(BITMAP),&bm)) hBitmap=0;
//ビットマップハンドルをピクチャーボックスに設定します。
HBITMAP hbmLast=m_stImage.SetBitmap(hBitmap);
::DeleteObject(hbmLast);
//画像フレームのフレーム番号を保存します。
if (indexFrame>0) m_indexFrame=indexFrame;
//ピクチャーボックスのサイズを画像サイズに合わせます。
CRect rcImage(0,0,bm.bmWidth,bm.bmHeight);
m_stImage.MoveWindow(&rcImage,FALSE);
//ダイヤログのクライアント領域を取得します。
CRect rcClientLast;
GetClientRect(&rcClientLast);
//新しいクライアント領域のサイズを、ピクチャーボックスに合わせます。
CRect rcClient=rcImage;
rcClient.OffsetRect(rcClientLast.TopLeft());
//新しいクライアント領域を元に、ダイヤログのサイズを算出します。
DWORD dwStyle=::GetWindowLong(GetSafeHwnd(),GWL_STYLE);
::AdjustWindowRect(&rcClient,dwStyle,FALSE);
//ダイヤログのサイズを再設定します。
CRect rcWnd=rcClient;
ClientToScreen(&rcWnd);
MoveWindow(&rcWnd,TRUE);
}
サンプルプログラム(VisualC++net2003ソリューション)MP3FileTest02.zip
上記のzipファイルをダウンロードして、前回の「libid3tagのインストール」で作成した「libid3tag-0.15.1b」フォルダーと「zlib」フォルダーがある同じフォルダー内にWinRAR等を使って解凍すると、「MP3FileTest02」という名のフォルダーが作成されます。
「MP3FileTest01A」フォルダー内にある「MP3FileTest.sln」を開いて「F5」キーを押すと、ビルド確認のダイヤログが表示されるので「Yes」を選択してソリューションをビルドします。
ビルドが終わると直ちにプログラムが自動起動して下の図にあるダイヤログが表示されます。
ダイヤログにある「ファイルを開く」ボタンを押すと、「ファイルを開く」ダイヤログが表示されます。
ID3タグの入ったMP3ファイルを選択し「開く」ボタンを押すと、コンボボックスにファイル名が表示され、スライドバーの動きに合わせて、MP3ファイルが再生されます。同時に「MP3のプロパティ」ダイヤログが表示され、画像があれば画像表示用ダイヤログも表示されます。
「MP3のプロパティ」ダイヤログのリストビューに、ID3タグの内容が表示されているか確認して下さい。
- ID3タグの書き込み(id3lib) 第2部
- ID3タグの書き込み(id3lib) 第1部
- ID3タグの読み込み(id3lib) 第3部
- ID3タグの読み込み(id3lib) 第2部
- ID3タグの読み込み(id3lib) 第1部
- id3libのインストール
- MP3ファイルの書き込み 第2部
- MP3ファイルの書き込み 第1部
- LAME ACMのインストール
- ID3タグの書き込み 第3部
- ID3タグの書き込み 第2部
- ID3タグの書き込み 第1部
- ID3タグの読み込み 第2部
- ID3タグの読み込み 第1部
- libid3tagのインストール
- MP3ファイルの再生 第2部
- MP3ファイルの再生 第1部