NonSoft

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


 サンプル(ソース/コード)
Windows Media Playerで再生中の曲のタイトルを取得するサンプル(VB.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から再生中の曲の情報(タイトル、アーチスト名、アルバム名)を取り出します。

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

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

★クラス(Class1.vb)
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Threading

Public Class Class1
    ' 再生を開始した曲の情報を送信するイベントの定義
    Public Class WmpInfEventArgs
        Inherits EventArgs
        Public WmpInf As String
    End Class
    Public Event WmpEvt(ByVal sender As Object, ByVal e As WmpInfEventArgs)

    ' ウィンドウクラスの名前
    Private Const ClassName = "MsnMsgrUIManager"

    ' ウィンドウクラス登録API
    Private Delegate Function D_WNDPROC( _
        ByVal hWnd As Integer, ByVal wMsg As Integer, _
        ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    Private Structure WNDCLASSEX
        Public cbSize As Integer            ' 構造体サイズ
        Public style As Integer             ' スタイル
        Public lpfnWndProc As D_WNDPROC     ' ウィンドウ処理関数
        Public cbClsExtra As Integer        ' 拡張情報1
        Public cbWndExtra As Integer        ' 拡張情報2
        Public hInstance As Integer         ' インスタンのスハンドル
        Public hIcon As Integer             ' アイコンのハンドル
        Public hCursor As Integer           ' カーソルのハンドル
        Public hbrBackground As Integer     ' ウィンドウ背景のハンドル
        Public lpszMenuName As Integer      ' メニューの名前
        Public lpszClassName As String      ' ウィンドウクラスの名前
        Public hIconSm As Integer           ' 小さいアイコンのハンドル
    End Structure
    Private Declare Function RegisterClassEx Lib "user32.dll" _
        Alias "RegisterClassExA" _
        (ByRef wcex As WNDCLASSEX) As Integer

    ' ウィンドウ作成API
    Private Declare Function CreateWindowEx Lib "user32.dll" _
        Alias "CreateWindowExA" _
        (ByVal dwExStyle As Integer, ByVal lpClassName As String, _
         ByVal lpWindowName As String, ByVal dwStyle As Integer, _
         ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, _
         ByVal nHeight As Integer, ByVal hwndParent As Integer, _
         ByVal hMenu As Integer, ByVal hInstance As Integer, _
         ByVal lpParam As Integer) As Integer

    ' ウィンドウ破棄API
    Private Declare Function DestroyWindow Lib "user32.dll" _
        (ByVal hWnd As Integer) As Integer

    ' メッセージ取得API
    Private Declare Function GetMessage Lib "user32.dll" _
        Alias "GetMessageA" _
        (ByRef lpMsg As Message, ByVal hWnd As Integer, _
         ByVal wMsgFilterMin As Integer, ByVal wMsgFilterMax As Integer _
         ) As Integer

    ' ウィンドウプロシージャへのメッセージ送信API
    Private Declare Function TranslateMessage Lib "user32.dll" _
        (ByRef lpMsg As Message) As Integer
    Private Declare Function DispatchMessage Lib "user32.dll" _
        Alias "DispatchMessageA" _
        (ByRef lpMsg As Message) As Integer

    ' デフォルトのメッセージ処理API
    Private Declare Function DefWindowProc Lib "user32.dll" _
        Alias "DefWindowProcA" _
        (ByVal hWnd As Integer, ByVal wMsg As Integer, _
         ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    ' メッセージ送信API
    Private Declare Function SendMessage Lib "user32.dll" Alias _
        "SendMessageA" _
        (ByVal hWnd As Integer, ByVal wMsg As Integer, _
         ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    Private Declare Function PostMessage Lib "user32.dll" _
        Alias "PostMessageA" _
        (ByVal hWnd As Integer, ByVal wMsg As Integer, _
         ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    ' ウィンドウ・メッセージの定義
    Private Const WM_NULL = &H0
    Private Const WM_DESTROY = &H2
    Private Const WM_CLOSE = &H10
    Private Const WM_QUIT = &H12

    ' Windows Media Playerからのメッセージ定義
    Private Const WM_COPYDATA = &H4A
    Private Structure COPYDATASTRUCT
        Public dwData As Integer
        Public cbData As Integer
        Public data As Integer
    End Structure

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

    ' ウィンドウクラスのスレッド
    Private MsgFromWMP_Thread As Thread = Nothing

    ' ウィンドウクラスのハンドル
    Private MsgFromWMP_hWnd As Integer = 0

    ' Windows Media Playerからのメッセージ受信処理開始
    Public Sub Start_GetMsgFromWMP()
        Try
            MsgFromWMP_Thread = New Thread(New ThreadStart(AddressOf GetMsgFromWMP))
            If MsgFromWMP_Thread Is Nothing = False Then
                MsgFromWMP_Thread.Start()
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Sub

    ' Windows Media Playerからのメッセージ受信処理終了
    Public Sub End_GetMsgFromWMP()
        Try
            If MsgFromWMP_hWnd <> 0 Then
                SendMessage(MsgFromWMP_hWnd, WM_DESTROY, 0, 0)
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Sub

    ' Windows Media Playerからのメッセージ受信処理
    Private Sub GetMsgFromWMP()
        Try
            ' ウィンドウクラス登録
            Dim wcex As New WNDCLASSEX
            wcex.cbSize = Marshal.SizeOf(wcex)
            wcex.hInstance = _
                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
            Dim a As Integer = RegisterClassEx(wcex)

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

            If MsgFromWMP_hWnd <> 0 Then
                ' メッセージ取得
                Dim rtn As Integer
                Dim mmm As New Message
                Do
                    rtn = GetMessage(mmm, MsgFromWMP_hWnd, 0, 0)
                    If rtn <= 0 Then Exit Do
                    ' ウィンドウプロシージャへのメッセージ送信
                    Try : TranslateMessage(mmm) : Catch ex As Exception : End Try
                    Try : DispatchMessage(mmm) : Catch ex As Exception : End Try
                Loop
            End If
        Catch ex As Exception
        Finally
            ' ウィンドウ破棄
            'Try : DestroyWindow(MsgFromWMP_hWnd) : Catch ex As Exception : End Try
            ' ウィンドウクラスのハンドル初期化
            MsgFromWMP_hWnd = 0
        End Try
    End Sub

    ' カスタマイズしたウィンドウ処理関数
    Private Function MyWndProc( _
        ByVal hWnd As Integer, ByVal wMsg As Integer, _
        ByVal wParam As Integer, ByVal lParam As Integer) As Integer
        Try
            Select Case wMsg
                Case WM_COPYDATA
                    ' Windows Media Playerからのメッセージを受信した時の処理
                    Dim cpd As COPYDATASTRUCT = _
                        Marshal.PtrToStructure(CType(lParam, IntPtr), _
                        GetType(COPYDATASTRUCT))
                    Dim str As String = Marshal.PtrToStringUni(cpd.data, cpd.cbData)
                    Dim dat As String() = Strings.Split(str, "\0")
                    Dim e As New WmpInfEventArgs
                    If dat(4) <> "" Or dat(5) <> "" Or dat(6) <> "" Then
                        e.WmpInf = dat(4) & vbTab & dat(5) & vbTab & dat(6)
                    Else
                        e.WmpInf = ""
                    End If
                    RaiseEvent WmpEvt(Me, e)
                    Return 0
                Case WM_DESTROY
                    PostMessage(hWnd, WM_QUIT, 0, 0)
                Case WM_CLOSE
                Case WM_QUIT
                Case WM_NULL
            End Select
            ' デフォルトのメッセージ処理
            Return DefWindowProc(hWnd, wMsg, wParam, lParam)
        Catch ex As Exception
        End Try
        Return 0
    End Function
End Class

★フォーム(Form1.vb)
Public Class Form1
    ' Windows Media Playerからのメッセージ受信処理オブジェクト
    Private WithEvents WmpObj As New Class1

    Private Sub Form1_Load( _
        ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles MyBase.Load

        ' Windows Media Playerからのメッセージ受信処理開始
        WmpObj.Start_GetMsgFromWMP()
    End Sub

    Private Sub Form1_FormClosed( _
        ByVal sender As System.Object, _
        ByVal e As System.Windows.Forms.FormClosedEventArgs) _
        Handles MyBase.FormClosed

        ' Windows Media Playerからのメッセージ受信処理終了
        WmpObj.End_GetMsgFromWMP()
    End Sub

    ' デリゲートの宣言(有効で無いスレッド間の操作用)
    Private Delegate Sub D_DspMyTextBox(ByVal inf As String)

    Private Sub WmpObj_WmpInfoEvt( _
        ByVal sender As System.Object, ByVal e As Class1.WmpInfEventArgs) _
        Handles WmpObj.WmpEvt

        ' TextBox1に再生中の曲情報を表示(有効で無いスレッド間の操作用)
        TextBox1.Invoke(New D_DspMyTextBox(AddressOf DspMyTextBox), e.WmpInf)
    End Sub

    Private Sub DspMyTextBox(ByVal inf As String)
        ' TextBox1に再生中の曲情報を表示
        TextBox1.Text = inf.Replace(vbTab, vbCrLf)
    End Sub
End Class