連載
» 2014年08月29日 09時58分 UPDATE

WinRT/Metro TIPS:コントロールの位置とサイズを取得するには?[ユニバーサルWindowsアプリ開発]

GeneralTransformクラスを使ってユニバーサルWindowsアプリでコントロールの位置とサイズを取得する方法を解説する。

[山本康彦(http://www.bluewatersoft.jp/),BluewaterSoft]
WinRT/Metro TIPS
業務アプリInsider/Insider.NET

powered by Insider.NET

「WinRT/Metro TIPS」のインデックス

連載目次

 画面上のコントロールの位置やサイズを知りたいと思ったことはないだろうか? 例えば、ポップアップを出す位置を、タップされたコントロールの近くにしたいことがあるだろう。また、ゲームを作るときにコントロールの位置を取得できないと、恐らく困ってしまうだろう。そこで本稿では、コントロールの位置とサイズを画面上の座標と長さで取得する方法を説明する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #88」からダウンロードできる。

事前準備

 ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Express 2013 for Windowsを使っている。

  • SLAT対応のPC*1
  • 2014年4月のアップデート*2適用済みの64bit版Windows 8.1 Pro版以上*3
  • Visual Studio 2013 Update 2(またはそれ以降)*4を適用済みのVisual Studio 2013(以降、VS 2013)*5

*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

コントロールの画面上での位置とサイズを取得するメソッド(上:C#、下:VB)
画面上の位置とサイズを知りたいコントロールのオブジェクトを、このGetElementRectメソッドに引数として渡す。返値はRectクラス(Windows.Foundation名前空間)のオブジェクトで、そのLeftプロパティ/Topプロパティが画面上での位置(コントロールの左上の座標)を、Widthプロパティ/Heightプロパティが画面上でのサイズを表している。

 なお、位置(コントロールの左上の座標)だけを知りたいときは、TransformBoundsメソッドではなく、TransformPointメソッドを使うと速度が若干上がるはずだ(そのときの引数には「new Point(0.0, 0.0)」を与える)。

実行結果

 C#の共有プロジェクト(VBではPCL)にユーザーコントロールを置き、いくつかコントロールを配置した。それらのコントロールがタップされたときのイベントハンドラーで、上記のGetElementRectメソッドを呼び出して、得られた位置とサイズを表示するUIを作った(次の画像)。詳細は、別途公開のサンプルコードをご覧いただきたい。

作成したサンプルアプリ(Windows 8.1)
作成したサンプルアプリ(Windows Phone 8.1エミュレーター) 作成したサンプルアプリ(上:Windows 8.1、下:Windows Phone 8.1エミュレーター)

 画面には、緑色の四角や青色の円などのコントロールが並んでいる。それらのコントロールを、上の段ではScrollViewerコントロール(Windows.UI.Xaml.Controls名前空間)に収めて、スクロール時の座標変化を確認できるようにしてある。下の段では上と同じサイズに宣言されているコントロールをViewboxコントロール(Windows.UI.Xaml.Controls名前空間)に収めてあり(結果的にコントロールのサイズは縮小される)、コントロールのサイズの変化を確認できるようになっている。また、GetElementRectメソッドで得られた位置とサイズを示す赤い四角を重ねて表示するように作ってある(次の画像を参照)。

 上の段で円をタップしたときの結果は、次の画像のようになる。スクロールさせると、それによって移動した座標が得られている。

スクロールに伴って、得られる座標が変わる(Windows 8.1)
スクロールに伴って、得られる座標が変わる(Windows Phone 8.1エミュレーター) スクロールに伴って、得られる座標が変わる(上:Windows 8.1、下:Windows Phone 8.1エミュレーター)
横方向の位置(赤丸内)に注目してほしい。スクロールによる位置の変化が、正しく取得できている。

 下の段で円をタップしたときの結果は、次の画像のようだ。Viewboxコントロールによって縮小されたサイズが得られている。

ViewBoxコントロールで拡大/縮小されたサイズが得られる(Windows 8.1)
ViewBoxコントロールで拡大/縮小されたサイズが得られる(Windows Phone 8.1エミュレーター) ViewBoxコントロールで拡大/縮小されたサイズが得られる(上:Windows 8.1、下:Windows Phone 8.1エミュレーター)
上段と下段のコントロールのサイズは、XAMLコード上では同じ設定である(円のサイズは高さ/幅ともに100ピクセル)。下段は、Viewboxコントロールによって縮小表示されている。得られたサイズ(赤丸内)は、縮小後の値になっている。

まとめ

 GeneralTransformクラスを利用して、コントロールの画面上の位置とサイズを取得できる。得られる値は、スクロールや拡大・縮小した後のもの、すなわち見た目通りの結果になる。

「WinRT/Metro TIPS」のインデックス

WinRT/Metro TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。