DVDの再生でタイトル再生が始まったりメニューが選択されたりしたというようなイベントを取得するにはDVDNotifyイベントを使います。
が、これを指定するとエラーが出ます。
手がつけられないほど出ます。
//DVDNotifyイベント
procedure TForm1.MSWebDVD1DVDNotify(Sender: TObject; lEventCode: Integer; lParam1,
lParam2: OleVariant);
begin
//とりあえずなにもしない
end;
この状態で出てしまいます。
こちらのプログラムミスとかそういうレベルのことではないようです。
このようなエラーが立て続けに50個近く出ます。
Read of address の後の数値は 00000000 の場合もあれば 00000002 もあったり色々です。
イベントを解除すれば正常に動きます。
システムがおかしくなったのかとも思いC#で同じように作ってみたところ、そちらは問題なく動作しました。
ということでDelphi固有の問題であろうと判断。
OnDVDNotifyイベントの引数を見てみると、IntegerとOleVariantがあります。
とりあえずIntegerは問題なかろうということで、lParam1, lParam2のOleVariantを疑ってみました。
とはいえOleVariantというのが一体何なのか良く分かっていないので手探りの状態なのですが。
マイクロソフトのページでNotifyイベントを調べてみると、lParam1, lParam2に渡されるのは大体DWORDやULONGだったりします。
ならばいっそOleVariantではなくIntegerでいいのではないか?と、だめもとでIntegerに書き換えてコンポーネントを再コンパイルしてみました。
取り込んだ MSWEBDVDLib_TLB.pas を直接書き換えます。
結構勇気がいります。
// *********************************************************************//
// OLE Control Proxy class declaration
// Control Name : TMSWebDVD
// Help String : MSWebDVD Class
// Default Interface: IMSWebDVD
// Def. Intf. DISP? : No
// Event Interface: _IMSWebDVD
// TypeFlags : (2) CanCreate
// *********************************************************************//
TMSWebDVDDVDNotify = procedure(Sender: TObject; lEventCode: Integer; lParam1: OleVariant;
lParam2: OleVariant) of object;
TMSWebDVDPlayForwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
TMSWebDVDPlayBackwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
677〜8行にある文を書き換えます。
// *********************************************************************//
// OLE Control Proxy class declaration
// Control Name : TMSWebDVD
// Help String : MSWebDVD Class
// Default Interface: IMSWebDVD
// Def. Intf. DISP? : No
// Event Interface: _IMSWebDVD
// TypeFlags : (2) CanCreate
// *********************************************************************//
// TMSWebDVDDVDNotify = procedure(Sender: TObject; lEventCode: Integer;
lParam1: OleVariant;
//
lParam2: OleVariant) of object;
TMSWebDVDDVDNotify = procedure(Sender: TObject; lEventCode: Integer; lParam1, lParam2: Integer) of object;
TMSWebDVDPlayForwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
TMSWebDVDPlayBackwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
そしてプログラムもコンパイル。起動。
エラーは出ません。
lParam1、lParam2の値も期待通りのものが得られます。
じゃぁ、これでいいのかなぁと。
でも、Integerでいいわけないよねぇと。
で、OleVariantの定義を見てみようとしたらPOleVariantというのがありました。
これか?と。
先ほどのlParam1、lParam2の型をIntegerからPOleVariantに書き換え。
// *********************************************************************//
// OLE Control Proxy class declaration
// Control Name : TMSWebDVD
// Help String : MSWebDVD Class
// Default Interface: IMSWebDVD
// Def. Intf. DISP? : No
// Event Interface: _IMSWebDVD
// TypeFlags : (2) CanCreate
// *********************************************************************//
// TMSWebDVDDVDNotify = procedure(Sender: TObject; lEventCode: Integer;
lParam1: OleVariant;
//
lParam2: OleVariant) of object;
TMSWebDVDDVDNotify = procedure(Sender: TObject; lEventCode: Integer; lParam1, lParam2: POleVariant) of object;
TMSWebDVDPlayForwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
TMSWebDVDPlayBackwards = procedure(Sender: TObject; bEnabled: WordBool) of object;
再びコンポーネントを再コンパイル。
そしてプログラムもコンパイル。起動。
エラーは出ません。
値を得るにはDWORDやULONGなどでlParam1やlParam2をキャストしなければなりませんが、期待通りの値は得られます。
これで本当にいいのかどうか自信はまったくありませんが、少なくともIntegerに書き換えるよりはましなんじゃなかろうかなぁと。
で、エラーが出ていたときのRead of address の後の数値を見てみると、取り出したかった値と同じようなのです。
つまりOleVariantの場合は本来0や2という値を返すはずが、それをアドレスとみなしてしまうのでアクセス違反を起こしてエラーを出していたのではなかろうかと。
なんにせよこれで無事Notifyイベントを取得することができるようになりました。