ホーム >プログラム >Delphi 6 ローテクTips >TWindowsMediaPlayerのTips

TWindowsMediaPlayerはTMediaPlayerよりもずっとパワフルで利用価値も大いにあります。
とはいえ一筋縄でいかないことも多々ありまして。
そんなわけでWindowsMediaPlayerを使う上でのTips。


マウスでつかんで移動
タイトルバーをつかんで移動する以外にプレーヤー本体をつかんで移動できると使い勝手が良くなることがあります。
その場合OnMouseDownイベントに以下のように記述するといけます。
procedure TForm1.WindowsMediaPlayer1MouseDown(Sender: TObject; nButton, nShiftState: Smallint; fX, fY: Integer);
begin
  if (nButton = VK_LBUTTON) then begin
    //移動
    SendMessage(Handle, WM_SYSCOMMAND, SC_SIZE or 9, 0);
  end;
end;
他のコンポーネントでフォームを移動させる時には必要なReleaseCaptureは必要ありません。
これだけでいけます。 ちなみにSendMessageで送るメッセージはいつの間にか私はSC_MOVEではなくSC_SIZEになっていてこの形で落ち着いてしまっています。
ビデオ再生エリアをクリックしてもアクティブにならない
フォームが非アクティブになっている時に、再生ボタンやシークバーのあるコントロール領域をクリックするとフォームがアクティブになります。
まぁ普通はそうですよね。
ところがビデオを再生している時にビデオが表示されているエリアを触ってもアクティブになりません。



上の図の赤枠で囲ったビデオが写っている部分をマウスでクリックしてもアクティブにならないのです。
この部分はWindowsMediaPlayer本体のメニューで「視覚エフェクト」を「視覚エフェクトなし」にしていて音声だけのメディアを再生している場合にはクリックするとアクティブになります。
「視覚エフェクト」を「視覚エフェクトなし」以外のものにしていると見た目にぎやかにはなりますが、音声だけのメディアであってもクリックしてもアクティブになりません。
何かしら映像が写っているとだめという感じです。
解決策としてはWindowsMediaPlayerのOnClickイベントかOnMouseDownイベント、あるいはOnMouseUpイベントでフォームをアクティブにする処理を行います。
procedure TForm1.WindowsMediaPlayer1Click(Sender: TObject; nButton, nShiftState: Smallint; fX, fY: Integer);
begin
  SetForegroundWindow(Handle);
end;
SetForegroundWindowの他にSetActiveWindowやWindows.SetFocusなども使えると思います。
右マウスアップイベントが二回発生する
ビデオが再生されている時だけなのですが、ビデオ再生エリアで右クリックするとマウスアップのイベントが二回発生します。
procedure TForm1.WindowsMediaPlayer1MouseUp(Sender: TObject; nButton, nShiftState: Smallint; fX, fY: Integer);
begin
  myDebug.gpcDebugAdd(nButton);
end;
このコードを動かしてみます。そしてビデオを再生していない状態とビデオを再生させた状態で左クリック、右クリック、中クリックしてみます。
結果は以下の通り。



1が左ボタン、2が右ボタン、4が中ボタンです。
左ボタンと中ボタンはそれぞれ1回ずつしか発生していません。
右ボタンは一度目(ビデオを再生してない状態)では1回だけですが、ビデオを再生した状態では2回イベントが発生しています。
決して手が滑って右ボタンをダブルクリックしてしまったわけではありません。
なぜかこうなるのです。
と、いうことで場合によっては右マウスアップイベントを捨てなければならない場合が出てきます。
ややこしいです。
ポップアップメニューのオートポップアップが無効になる


「ビデオ再生エリアをクリックしてもアクティブにならない」問題と同じような感じなのですが、ビデオを再生していたり視覚エフェクトが有効になっていたりすると赤枠で囲った部分でPopupMenuプロパティで指定したポップアップメニューのオートポップアップが無効になります。
右クリックしてもメニューがポップアップしないということです。
解決策としては、手っ取り早いのはオートポップアップをやめてマニュアルでポップアップさせることです。
カーソル指定が効かない
これまたビデオの再生エリアの問題なのですが、ビデオを再生している時はカーソルプロパティで指定したカーソルが無視されます。
というか、ビデオの場合はコントロールパネルで指定したカーソルですら無視されてシステムデフォルトの矢印に変わってしまいます。
音声のみのメディアで視覚エフェクトがONになっている場合はちょっと違って、カーソルプロパティの指定は無視されますがコントロールパネルで指定したカーソルは有効になります。
またビデオの時にアスペクト比が違うことでできる上下あるいは左右の余白部分はカーソル指定は効きます(ちなみにこの部分を右クリックしてもオートポップアップは効きません)


カーソルプロパティで指定したハンドカーソル(crHandPoint)


ビデオが表示されているエリアに持っていくと、、
デフォルトの小さい矢印に変わってしまいます。
下の図のカーソルと比べてみると大きさが違うのが分かると思います。
私は拡大ポインタにしているのです。


「視覚エフェクト」ありの音声メディアの場合カーソルプロパティの指定は無視されコントロールパネルで指定したカーソルになります(私は拡大ポインタにしています)。


ビデオを再生している場合でもこのように余白部分はカーソルプロパティ指定のカーソルになります。
とはいえオートポップアップは無効です。

左マウスボタンでドラッグして移動、右マウスボタンのクリックでポップアップメニューを行うサンプルです。

function gfnsClassNameGet(const hHandle: HWND): AnsiString;
//ウィンドウハンドルhHandleのクラス名を返す
const
  lci_LEN = 256;
var
  lp_Buff: PAnsiChar;
begin
  Result := '';
  lp_Buff := AllocMem(lci_LEN);
  try
    GetClassName(hHandle, lp_Buff, lci_LEN -1);
    Result := AnsiString(lp_Buff);
  finally
    FreeMem(lp_Buff);
  end;
end;


procedure TForm1.WindowsMediaPlayer1MouseDown(Sender: TObject; nButton, nShiftState: Smallint; fX, fY: Integer);
begin
  if (nButton = VK_LBUTTON) then begin
    //移動
    SendMessage(Handle, WM_SYSCOMMAND, SC_SIZE or 9, 0);
  end else begin
    SetForegroundWindow(Handle);
    if (nButton = VK_RBUTTON) then begin
      //ビデオが映っていると二回マウスアップイベントが発生するので一度マウスアップ
      //イベントを捨てる。そのためのフラグとしてTagを利用
      mnuPopupMenu1.Tag := 1;
    end;
  end;
end;

procedure TForm1.WindowsMediaPlayer1MouseUp(Sender: TObject; nButton, nShiftState: Smallint; fX, fY: Integer);
var
  ls_ClassName: AnsiString;
  lpt_Pos: TPoint;
begin
  if (nButton = VK_RBUTTON) then begin
    lpt_Pos := Point(0, 0);
    GetCursorPos(lpt_Pos);
    //ビデオを再生していてクリックポイントが再生エリアかどうかをWMPVideoWindowウィンドウのあるなしで判定
    ls_ClassName := gfnsClassNameGet(WindowFromPoint(lpt_Pos));
    if (ls_ClassName = 'WMPVideoWindow')
    or (ls_ClassName = 'VideoRenderer')
    then begin
      mnuPopupMenu1.Tag := mnuPopupMenu1.Tag - 1;
      if (mnuPopupMenu1.Tag >= 0) then Exit;
    end;
    mnuPopupMenu1.Popup(lpt_Pos.X, lpt_Pos.Y);
  end;
end;

右マウスイベントが二回発生するのはビデオが再生されている時にビデオの再生エリアで右クリックした時だけなので、クリックしたポイントがビデオ再生エリアなのか、またビデオが再生されているのかを判定する必要があります。
ビデオが再生されているかどうかはメディアの大きさで判定することもできます。
ビデオ再生エリアなのかどうかはメディアのオリジナルサイズとメディアプレーヤーの大きさから算出することもできそうですが、1ドット程度の誤差が出そうでうまくありません。
一番確実そうなのがビデオを再生している時はWMPVideoWindowというクラス名のウィンドウ(あるいはVideoRendererというクラス名のウィンドウ)が作られるのでそれで判定することと思います。
オーバーレイが無効になっている場合でもこれでいけます。