Deep Zoom Composerでは、最後エクスポートするときに、Visual Studio用のプロジェクトを生成してくれる。この中に、MouseWheelHelper.csという奇妙なファイルがあったので、読んでみた。
どうも、Silverlightのコントロールでは、マウスホイールに関するイベントを、直接的には取得できない模様。マウスホイールのイベントは、HtmlPage.Windowや、HtmlPage.Documentから取得するみたい。それを設定しているのが、
HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel);
HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel);
HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel);
という部分。Workerクラスのコンストラクタ、行番号90行目近辺で行われている。
3つイベントをセットしているのは、おそらくブラウザの違いを吸収するためではないかと思われる。
で、このイベントはページ全体にかかるイベントなので、XAPのコントロールのみならず、ページ全体のものがやってきてしまう。これをぶんどってしまうと、ページのスクロールが、ホイールでできなくなってしまう。
これを防ぐために、
element.MouseEnter += this.HandleMouseEnter;
element.MouseLeave += this.HandleMouseLeave;
element.MouseMove += this.HandleMouseMove;
とやって、マウスが自分の範囲にあるかどうかをチェックしている。MouseWheelHelperのコンストラクタ、54行目近辺。
自分の範囲にある間だけ、ホイールのイベントをハンドルするようにしなければならない。
ホイールのイベントハンドラでは、
if (eventObj.GetProperty("wheelDelta") != null) {
…
if (HtmlPage.Window.GetProperty("opera") != null)
…
} else if (eventObj.GetProperty("detail") != null) {
…
if (HtmlPage.BrowserInformation.UserAgent.IndexOf("Macintosh") != -1)
…
}
となっていて、いろんなブラウザでどんな風にホイールイベントの値を取得すればいいかを吸収している。
このコードは、Deep Zoomに限らず、Silverlightでホイールイベントをとるのに使えそうだ。