最近のMSN Messenger1やLive Messengerには、Windows Media Player(以下WMP)やiTunesで再生中の曲のタイトルを表示する機能があります。
しかし僕はWMPもiTunesも使っていないので、この機能を利用することが出来ません。
ということで、前回のmixi station同様、MSN Messengerに通知する機能も自作のプレイヤーに組み込んでみました。

上のスクリーンショットの、赤枠で囲った部分が、再生中の曲を表示している部分です。
送信方法は、mixi stationのときと同様に、WMPに組み込まれたプラグインが、MSN Messengerに曲情報を送るという仕組みのようです。
とはいえ自分で調べるのは面倒なので、今回も偉人の力を借ります。:p
この記事によると、どうやら送信は次のようにして行っているようです。
以下引用。
MsnMsgrUIManagerクラスに対してメッセージを送信している
メッセージの種類は WM_COPYDATA
COPYDATASTRUCT構造体は以下のように使う
- dwData : 1351 (固定)
- cbData : データの長さ(NULL含)
- lpData : データへのポインタ
データには以下の内容を、それぞれ「\0」(NULLでは無くただの文字)で連結し、UTF-16にエンコードしたものを使用する
- アプリ名 : 自分のアプリ名です。ちなみに、iTunesは「ITunes」が、WMPでは空です。
- Music : 文字列「Music」を指定します。
- 1 または 0 : これは、終了を通知するものです。0を指定して送ると、以後は表示メッセージ欄には楽曲名は表示されません。
- 表示書式 : 曲名やアーティストを表示するときの書式です。デフォルトは「{0} - {1}」です。
- 曲名 : 曲名です。書式の {0} に展開されます。
- アーティスト : アーティストです。書式の {1} に展開されます。
- アルバム : アルバム名です。書式の {2} に展開されます。
- (検証してないけど、↑この辺は\0区切りで延々続けられるかも・・?)
引用元にも書いてありますが、区切り文字として扱っている「\0」は、ヌル文字ではなく "\\0" ですので、注意してください。2
これらを元に、MSN Messengerに曲情報を送るプログラムを、C#で書いてみました。
以下はその一部です。
C/C++で書きたい場合は、上で挙げた参考にしたページにC++のサンプルソースがありましたので、そちらを参考にしてください。
using System;
using System.Runtime.InteropServices;
private const int WM_COPYDATA = 0x004A;
private struct COPYDATASTRUCT {
public int dwData;
public uint cbData;
public IntPtr lpData;
}
[DllImport("user32.dll")]
private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private extern static int SendMessage(IntPtr hWnd, int msg, int wParam, ref COPYDATASTRUCT lParam);
private void SendToMsnMsgr(string title, string artist) {
// MsnMsgrUIManagerクラスを検索
IntPtr msgr = FindWindow("MsnMsgrUIManager", null);
// 発見したら
if (msgr != IntPtr.Zero) {
// 曲データの連結
string buf = @"myplayer\0Music\01\0{0} - {1}\0" + title + @"\0" + artist + @"\0\0";
// COPYDATASTRUCT構造体
COPYDATASTRUCT cds;
cds.dwData = 1351; // マジックナンバー
cds.cbData = (uint)(buf.Length + 1) * 2; // データのサイズ
cds.lpData = Marshal.StringToHGlobalUni(buf); // データへの参照
// Messengerに対してWM_COPYDATAメッセージを送る
Win32API.SendMessage(msgr, WM_COPYDATA, 0, ref cds);
// メモリの解放
Marshal.FreeHGlobal(cds.lpData);
}
}