NonSoft

WMPで再生中の曲のタイトルを取得する
サンプル(C#.NET)


 サンプル(ソース/コード)
Windows Media Playerで再生中の曲のタイトルを取得するサンプル(C#.NET)です。
Windows Live Messenger ミュージック プラグインを使用しています。
※Windows Live Messenger 2009(Windows7またはXP)または2011(Windows7)で動作確認

Windows Media Playerは、Windows Live Messenger プラグインを使用すると、
再生を開始した曲の情報をMsnMsgrUIManagerというウィンドウクラスに送信します。

このサンプルは、Windows Live Messengerが持っているMsnMsgrUIManagerウィンドウクラスと
同等の機能を実装する事で、Windows Media Playerからこのサンプルにも曲の情報を送ってもらう、
というサンプルです。

ポイントは、RegisterClassExとCreateWindowExでウィンドウクラスを作成して、
自作のWndProcでWindows Live Messengerから送られてくるWindowsメッセージ(WM_COPYDATA)を
処理する事です。WM_COPYDATAメッセージにはCOPYDATASTRUCTと言うデータが付いて来ますので
そのCOPYDATASTRUCTから再生中の曲の情報(タイトル、アーチスト名、アルバム名)を取り出します。

VB.NETのサンプルはこちらです。
WMPで再生中の曲のタイトルを取得するサンプル(VB.NET)

このサンプルを使用したWindows Media Player関係のツールはこちらです。
WMP再生中タイトル保存ツール(KpcWmpInfo)

★クラス(Class1.cs)
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;

class Class1
{
    // 再生を開始した曲の情報を送信するイベントの定義
    public class WmpInfEventArgs : EventArgs
    {
        public String WmpInf;
    }
    public delegate void WmpEventHandler(object sender, WmpInfEventArgs e);
    public event WmpEventHandler WmpEvt;
    protected virtual void OnWmpEvt(WmpInfEventArgs e)
    {
        if (WmpEvt != null)
        {
            WmpEvt(this, e);
        }
    }

    // ウィンドウクラスの名前
    private const String ClassName = "MsnMsgrUIManager";

    // ウィンドウクラス登録API
    private delegate int D_WNDPROC(int hWnd, int wMsg, int wParam, int lParam);
    [StructLayout(LayoutKind.Sequential)]
    private struct WNDCLASSEX
    {
        public int cbSize;              // 構造体サイズ
        public int style;               // スタイル
        public D_WNDPROC lpfnWndProc;   // ウィンドウ処理関数
        public int cbClsExtra;          // 拡張情報1
        public int cbWndExtra;          // 拡張情報2
        public int hInstance;           // インスタンのスハンドル
        public int hIcon;               // アイコンのハンドル
        public int hCursor;             // カーソルのハンドル
        public int hbrBackground;       // ウィンドウ背景のハンドル
        public int lpszMenuName;        // メニューの名前
        public String lpszClassName;    // ウィンドウクラスの名前
        public int hIconSm;             // 小さいアイコンのハンドル
    };
    [DllImport("user32.dll", EntryPoint = "RegisterClassExA")]
    private static extern int RegisterClassEx(ref WNDCLASSEX wcex);

    // ウィンドウ作成API
    [DllImport("user32.dll", EntryPoint = "CreateWindowExA")]
    private static extern int CreateWindowEx(
        int dwExStyle, String lpClassName,
        String lpWindowName, int dwStyle, 
        int X, int Y, int nWidth, int nHeight,
        int hWndParent, int hMenu,
        int hInstance, int lpParam);

    // ウィンドウ破棄API
    [DllImport("user32.dll")]
    private static extern int DestroyWindow(int hWnd);

    // メッセージ取得API
    [DllImport("user32.dll", EntryPoint = "GetMessageA")]
    private static extern int GetMessage(
        ref Message lpMsg, int hWnd, 
        int wMsgFilterMin, int wMsgFilterMax);

    // ウィンドウプロシージャへのメッセージ送信API
    [DllImport("user32.dll")]
    private static extern int TranslateMessage(ref Message lpMsg);
    [DllImport("user32.dll", EntryPoint = "DispatchMessageA")]
    private static extern int DispatchMessage(ref Message lpMsg);

    // デフォルトのメッセージ処理API
    [DllImport("user32.dll", EntryPoint = "DefWindowProcA")]
    private static extern int DefWindowProc(
        int hWnd, int wMsg, int wParam, int lParam);

    //' メッセージ送信API
    [DllImport("user32.dll", EntryPoint = "SendMessageA")]
    private static extern int SendMessage(
        int hWnd, int wMsg, int wParam, int lParam);
    [DllImport("user32.dll", EntryPoint = "PostMessageA")]
    private static extern int PostMessage(
        int hWnd, int wMsg, int wParam, int lParam);

    // ウィンドウ・メッセージの定義
    private const int WM_NULL = 0x0;
    private const int WM_DESTROY = 0x2;
    private const int WM_CLOSE = 0x10;
    private const int WM_QUIT = 0x12;

    // Windows Media Playerからのメッセージ定義
    private const int WM_COPYDATA = 0x4A;
    [StructLayout(LayoutKind.Sequential)]
    private struct COPYDATASTRUCT
    {
        public int dwData;
        public int cbData;
        public int data;
    };

    // ウィンドウ処理関数をデリゲート変数に保存
    // (ガベージ コレクションされたデリゲートのエラー例外の対応)
    private D_WNDPROC MsgFromWMP_WndProc;

    // ウィンドウクラスのスレッド
    private Thread MsgFromWMP_Thread = null;

    // ウィンドウクラスのハンドル
    private int MsgFromWMP_hWnd = 0;

    // Windows Media Playerからのメッセージ受信処理開始
    public void Start_GetMsgFromWMP()
    {
        try
        {
            MsgFromWMP_WndProc = MyWndProc;
            MsgFromWMP_Thread = new Thread(new ThreadStart(GetMsgFromWMP));
            if (MsgFromWMP_Thread != null)
            {
                MsgFromWMP_Thread.Start();
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    // Windows Media Playerからのメッセージ受信処理終了
    public void End_GetMsgFromWMP()
    {
        try
        {
            if (MsgFromWMP_hWnd != 0)
            {
                SendMessage(MsgFromWMP_hWnd, WM_DESTROY, 0, 0);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    // Windows Media Playerからのメッセージ受信処理
    private void GetMsgFromWMP()
    {
        try
        {
            // ウィンドウクラス登録
            WNDCLASSEX wcex = new WNDCLASSEX();
            wcex.cbSize = Marshal.SizeOf(wcex);
            wcex.hInstance =
                (int)Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().ManifestModule);
            wcex.lpszClassName = ClassName;
            wcex.lpfnWndProc = MsgFromWMP_WndProc;
            wcex.style = 0;
            wcex.hIcon = 0;
            wcex.hIconSm = 0;
            wcex.hCursor = 0;
            wcex.lpszMenuName = 0;
            wcex.cbClsExtra = 0;
            wcex.cbWndExtra = 0;
            wcex.hbrBackground = 0;
            int a = RegisterClassEx(ref wcex);

            // ウィンドウ作成
            MsgFromWMP_hWnd =
                CreateWindowEx(0, wcex.lpszClassName, wcex.lpszClassName,
                0, 0, 0, 0, 0, 0, 0, wcex.hInstance, 0);

            if (MsgFromWMP_hWnd != 0)
            {
                // メッセージ取得
                int rtn;
                Message mmm = new Message();
                while (true)
                {
                    rtn = GetMessage(ref mmm, MsgFromWMP_hWnd, 0, 0);
                    if (rtn <= 0) break;
                    // ウィンドウプロシージャへのメッセージ送信
                    try { TranslateMessage(ref mmm); }
                    catch (Exception) { }
                    try { DispatchMessage(ref mmm); }
                    catch (Exception) { }
                }
            }
        }
        catch (Exception) { }
        finally
        {
            // ウィンドウ破棄
            try { DestroyWindow(MsgFromWMP_hWnd); }
            catch (Exception) { }
            // ウィンドウクラスのハンドル初期化
            MsgFromWMP_hWnd = 0;
        }
    }

    // カスタマイズしたウィンドウ処理関数
    private int MyWndProc(int hWnd, int wMsg, int wParam, int lParam)
    {
        try
        {
            switch (wMsg)
            {
                case WM_COPYDATA:
                // Windows Media Playerからのメッセージを受信した時の処理
                    COPYDATASTRUCT cpd =
                        (COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)lParam,
                        typeof(COPYDATASTRUCT));
                    string str = Marshal.PtrToStringUni((IntPtr)cpd.data, cpd.cbData);
                    String[] dat = str.Split(new string[] { "\\0" }, StringSplitOptions.None);
                    WmpInfEventArgs e = new WmpInfEventArgs();
                    if (dat[4] != "" || dat[5] != "" || dat[6] != "")
                    {
                        e.WmpInf = dat[4] + "\t" + dat[5] + "\t" + dat[6];
                    }
                    else
                    {
                        e.WmpInf = "";
                    }
                    OnWmpEvt(e);
                    return 0;
                case WM_DESTROY:
                    PostMessage(hWnd, WM_QUIT, 0, 0);
                    break;
                case WM_CLOSE:
                    break;
                case WM_QUIT:
                    break;
                case WM_NULL:
                    break;
            }
            // デフォルトのメッセージ処理
            return DefWindowProc(hWnd, wMsg, wParam, lParam);
        }
        catch (Exception) { }
        return 0;
    }
}

★フォーム(Form1.cs)
public partial class Form1 : Form
{
    // Windows Media Playerからのメッセージ受信処理オブジェクト
    private Class1 WmpObj = new Class1();

    private void Form1_Load(object sender, EventArgs e)
    {
        // Windows Media Playerからのメッセージ受信処理開始
        WmpObj.WmpEvt += WmpObj_WmpInfoEvt;
        WmpObj.Start_GetMsgFromWMP();
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        // Windows Media Playerからのメッセージ受信処理終了
        WmpObj.End_GetMsgFromWMP();
    }

    // デリゲートの宣言(有効で無いスレッド間の操作用)
    private delegate void D_DspMyTextBox(String inf);

    private void WmpObj_WmpInfoEvt(
        System.Object sender, Class1.WmpInfEventArgs e)
    {

        // TextBox1に再生中の曲情報を表示(有効で無いスレッド間の操作用)
        textBox1.Invoke(new D_DspMyTextBox(DspMyTextBox), e.WmpInf);
    }

    public void DspMyTextBox(String inf)
    {
        // TextBox1に再生中の曲情報を表示
        textBox1.Text = inf.Replace("\t", "\r\n");
    }
}