GeneralTransformクラスを使ってユニバーサルWindowsアプリでコントロールの位置とサイズを取得する方法を解説する。
powered by Insider.NET
画面上のコントロールの位置やサイズを知りたいと思ったことはないだろうか? 例えば、ポップアップを出す位置を、タップされたコントロールの近くにしたいことがあるだろう。また、ゲームを作るときにコントロールの位置を取得できないと、恐らく困ってしまうだろう。そこで本稿では、コントロールの位置とサイズを画面上の座標と長さで取得する方法を説明する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #88」からダウンロードできる。
ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Express 2013 for Windowsを使っている。
*1 SLAT対応ハードウェアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウェアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。
*3 Windows Phone 8.1エミュレーターを使用しないのであれば、32bit版のWindows 8.1でもよい。
*4 マイクロソフトのダウンロードページから誰でも入手できる(このURLはUpdate 3のもの)。
*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションで構わない。Visual Studio Express 2013 with Update 3 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsストアアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。
Visual Studio 2013 Update 2(およびUpdate 3)では、残念なことにVB用のユニバーサルプロジェクトのテンプレートは含まれていない*6。そのため、本稿で紹介するVBのコードはユニバーサルプロジェクトではなく、PCL(ポータブルクラスライブラリ)を使ったプロジェクトのものである*7。
*6 VB用のユニバーサルプロジェクトは、来年にリリースされるといわれているVisual Studio「14」からの提供となるようだ。「Visual Studio UserVoice」(英語)のリクエストに対する、6月18日付けの「Visual Studio team (Product Team, Microsoft)」からの回答による。
*7 Visual Studio 2013 Update 2(またはUpdate 3)のVBでユニバーサルWindowsアプリを作る場合のお勧めは、「The Visual Basic Team」のブログ記事(英語)によれば、PCLを使う方法のようである。PCLに置いたものは、コードだけでなくXAML(画面)やリソースディクショナリなども共通に利用できる。そこで別途公開のサンプルコードでも、VBはWindows用/Phone用/共通コード(PCL)の3プロジェクト構成とした。ユニバーサルプロジェクトで作らなくてもユニバーサルWindowsアプリはリリースできるのである(「WinRT/Metro TIPS:ユニバーサルプロジェクトで開発するには?」参照)。
GeneralTransformクラス(Windows.UI.Xaml.Media名前空間)を利用すればよい。
ただし、複数行にわたるため、メソッドにまとめておいて使うとよい。次のGetElementRectメソッドのようになる(次のコード)。
public static Windows.Foundation.Rect
GetElementRect(Windows.UI.Xaml.FrameworkElement element)
{
// 変換前のコントロールの位置とサイズ(位置は原点、サイズは原寸)
var originRect = new Windows.Foundation.Rect(
0.0, 0.0,
element.ActualWidth,
element.ActualHeight);
// コントロールの現在の位置とサイズへの変換を表すGeneralTransformを取得する。
// 引数に与えたコントロールからの相対変換が得られる。
// 引数がnullの場合は、画面上の座標になる
Windows.UI.Xaml.Media.GeneralTransform ctlTransform
= element.TransformToVisual(null);
// originRectに同じ変換を加えると、コントロールの画面上の位置とサイズになる
return ctlTransform.TransformBounds(originRect);
}
Public Shared Function GetElementRect _
(element As Windows.UI.Xaml.FrameworkElement) _
As Windows.Foundation.Rect
' 変換前のコントロールの位置とサイズ(位置は原点、サイズは原寸)
Dim originRect = New Windows.Foundation.Rect(
0.0, 0.0,
element.ActualWidth,
element.ActualHeight)
' コントロールの現在の位置とサイズへの変換を表すGeneralTransformを取得する。
' 引数に与えたコントロールからの相対変換が得られる。
' 引数がNothingの場合は、画面上の座標になる
Dim ctlTransform As Windows.UI.Xaml.Media.GeneralTransform _
= element.TransformToVisual(Nothing)
' originRectに同じ変換を加えると、コントロールの画面上の位置とサイズになる
Return ctlTransform.TransformBounds(originRect)
End Function
なお、位置(コントロールの左上の座標)だけを知りたいときは、TransformBoundsメソッドではなく、TransformPointメソッドを使うと速度が若干上がるはずだ(そのときの引数には「new Point(0.0, 0.0)」を与える)。
C#の共有プロジェクト(VBではPCL)にユーザーコントロールを置き、いくつかコントロールを配置した。それらのコントロールがタップされたときのイベントハンドラーで、上記のGetElementRectメソッドを呼び出して、得られた位置とサイズを表示するUIを作った(次の画像)。詳細は、別途公開のサンプルコードをご覧いただきたい。
画面には、緑色の四角や青色の円などのコントロールが並んでいる。それらのコントロールを、上の段ではScrollViewerコントロール(Windows.UI.Xaml.Controls名前空間)に収めて、スクロール時の座標変化を確認できるようにしてある。下の段では上と同じサイズに宣言されているコントロールをViewboxコントロール(Windows.UI.Xaml.Controls名前空間)に収めてあり(結果的にコントロールのサイズは縮小される)、コントロールのサイズの変化を確認できるようになっている。また、GetElementRectメソッドで得られた位置とサイズを示す赤い四角を重ねて表示するように作ってある(次の画像を参照)。
上の段で円をタップしたときの結果は、次の画像のようになる。スクロールさせると、それによって移動した座標が得られている。
下の段で円をタップしたときの結果は、次の画像のようだ。Viewboxコントロールによって縮小されたサイズが得られている。
GeneralTransformクラスを利用して、コントロールの画面上の位置とサイズを取得できる。得られる値は、スクロールや拡大・縮小した後のもの、すなわち見た目通りの結果になる。
Copyright© Digital Advantage Corp. All Rights Reserved.