none
Button、RepeatButtonのMouseLeftButtonUpイベントが取れない RRS feed

  • 質問

  • いつも参考にさせて頂いてます。

    現在、smf:SMFPlayerを使ってオリジナルのプレイヤーを作成しています。

    検索しても同じ内容の質問がなかったので僕だけなのかも知れませんが

    やりたいことがなかなかできないのため質問させて頂きました。

    やりたいのは以下のことです。

    「再生中に再生ボタンをマウスでクリックしたまま(長押し)2秒経過すると早送り再生になり、クリックをやめると通常再生になる」

    msdnで調べると、ButtonコントロールにMouseLeftButtonDownとMouseLeftButtonUpイベントがあったのでそれをもとに仕様を考えました。

    http://msdn.microsoft.com/ja-jp/library/ms609089.aspx

    ※ちなみにRepeatButtonコントロールは長押しできそうでしたが、同じ処理が繰り返されるだけで、短押しと長押しで別な処理の場合には向かなそうなのでやめました。

     

    長押し処理の概要
    ・MouseLeftButtonDownイベント受信でタイマー発行
    ・タイマー発火(2秒)以内にMouseLeftButtonUpイベント受信したらタイマーを停止して通常のClick処理を実行する
    ・タイマー発火(2秒)したら長押しと判定し、ボタンに設定されている長押しの処理(ここでは早送り再生)を実行する。
    ・長押しの処理はMouseLeftButtonUpイベント受信で終了する

     

    しかし実際に以下のように実装してみるとMouseLeftButtonDownイベントもMouseLeftButtonUpイベントも飛んできませんでした。

    【xaml】

    <Button x:Name="btnPause" 中略 MouseLeftButtonDown="onMouseDownFunc" MouseLeftButtonUp="onMouseUpFunc" />

    ※再生中はポーズボタンを表示するために実際の名前に"btnPause"を付けています。

    【C#】

    private void onMouseDownFunc(object sender, MouseButtonEventArgs e)
    {
        debuglog.Content = "MouseDown";
    }
    private void onMouseUpFunc(object sender, MouseButtonEventArgs e)
    {
        debuglog.Content = "MouseUp";
    }

    環境がおかしいのかわかりませんが、標準インストールした他のマシンでも同じでした。

    msdnにはイベントが発生すると明記されているんですが...

    マウス ポインターがこの要素上にあるときにマウスの左ボタンが押されると発生します。

    マウス ポインターがこの要素上にあるときにマウスの左ボタンが離されると発生します。」

    ちなみに以下のC#コードを追記して試してみましたがイベントは飛んできませんでした。

    btnPause.MouseLeftButtonDown += new MouseButtonEventHandler(onMouseDownFunc);

    btnPause.MouseLeftButtonUp += new MouseButtonEventHandler(onMouseUpFunc);

    また、以下のようにするとマウスダウンとアップのイベントは飛んでくるようになったのですが、すべてのボタンからイベントが飛んできてしまいます。

    AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(onMouseDownFunc), true);

    AddHandler(Button.MouseLeftButtonUpEvent, new MouseButtonEventHandler(onMouseUpFunc), true);

    これだと、複数のボタンでそれぞれ異なった長押し処理がある場合は、1回のマウスダウンで、追加したすべてのイベントハンドラーに処理が飛んでしまって無駄な気もしますし、また判別が複雑になってしまいそうです。

    (たとえば再生ボタン→早送り、1秒正ジャンプボタン→正ジャンプ連続、1秒逆ジャンプ→逆ジャンプ連続)

     

    以下のように特定のボタンのマウスダウンイベントとマウスアップイベントの受信を実現するためには何が必要なのかわからずに行き詰まっています。

    <Button x:Name="btnPause" 中略 MouseLeftButtonDown="onMouseDownFunc" MouseLeftButtonUp="onMouseUpFunc" />

    設定やオプションなどで見落としているところはないか、処理で不足しているところなどないか、何か良い解決手段はないか、などアドバイスをいただけないでしょうか?

    以上よろしくお願いします。

     

    使用している環境はWindows7で、Visual Studio2010、Expression Studio 4 Ultimate、Silverlight4です。

    2011年5月27日 0:45

回答

  • AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(onMouseDownFunc), true);

    これに気づいたのなら、WPF にはルーティングイベントという仕組みがあり、ルーティングイベントには「処理済み」という概念がある、ということはなんとなく分かると思います。詳しくは ルーティング イベントの概要 をお読みください。

    Button の類はマウスクリックなどの操作を抽象化した Click イベントを提供するため(フォーカスがあるときのスペースバーや Enter キーの入力でもマウスクリックと同じ処理が行われることが期待されますから)、マウスボタン系のバブルイベントは処理済みとしてマークされます。

    トンネルイベント、つまり Preview がつくイベントを使用するか、あるいはいっそ ContentControl あたりから派生させたカスタムコントロールを作るか、ですね。

    • 回答としてマーク 山本春海 2011年6月2日 9:05
    2011年5月27日 2:55

すべての返信

  • AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(onMouseDownFunc), true);

    これに気づいたのなら、WPF にはルーティングイベントという仕組みがあり、ルーティングイベントには「処理済み」という概念がある、ということはなんとなく分かると思います。詳しくは ルーティング イベントの概要 をお読みください。

    Button の類はマウスクリックなどの操作を抽象化した Click イベントを提供するため(フォーカスがあるときのスペースバーや Enter キーの入力でもマウスクリックと同じ処理が行われることが期待されますから)、マウスボタン系のバブルイベントは処理済みとしてマークされます。

    トンネルイベント、つまり Preview がつくイベントを使用するか、あるいはいっそ ContentControl あたりから派生させたカスタムコントロールを作るか、ですね。

    • 回答としてマーク 山本春海 2011年6月2日 9:05
    2011年5月27日 2:55
  • Hongliangさま

     

    回答ありがとうございました。

    やはりButtonコントロールでは一般的なマウスダウン・アップイベントは簡単には取れないんですね。

    またいろいろ調査してみます。

    2011年5月29日 23:45