ユニバーサルプロジェクトの共有プロジェクトを用いて、画面サイズに関係する各種の情報を取得する方法を解説する。
powered by Insider.NET
画面のサイズを取得したいことはないだろうか? 特にユニバーサルプロジェクトの共有プロジェクトでUI(ユーザーインターフェース)を記述していると、対応すべき画面サイズが多いので、より切実だろう。本稿では、ウィンドウの論理的なサイズを取得する方法と、実際のピクセル数を求める方法の、両方について説明する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #86」からダウンロードできる。
ユニバーサルプロジェクトを使ってユニバーサル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 マイクロソフトのダウンロードページから誰でも入手できる。
*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションで構わない。Visual Studio Express 2013 Update 3 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsストアアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。
本稿では、紛らわしくない限り次の略称を用いる。
Visual Studio 2013 Update 2(およびUpdate 3)では、残念なことにVB用のユニバーサルプロジェクトのテンプレートは含まれていない*6。そのため、本稿で紹介するコードはC#のユニバーサルプロジェクトだけとさせていただく*7。
*6 VB用のユニバーサルプロジェクトは、来年にリリースされるといわれているVisual Studio「14」からの提供となるようだ。「Visual Studio UserVoice」(英語)のリクエストに対する、6月18日付けの「Visual Studio team (Product Team, Microsoft)」からの回答による。
*7 Visual Studio 2013 Update 2(またはそれ以降)のVBでユニバーサルWindowsアプリを作る場合のお勧めは、「The Visual Basic Team」のブログ記事(英語)によれば、PCLを使う方法のようである。しかし、本稿で説明するような「#if」ディレクティブを使う方法は、PCLでは利用できない。
論理サイズ、すなわちDIP単位でウィンドウのサイズを取得するには、Windowクラス(Windows.UI.Xaml名前空間)のBoundsプロパティを使えばよい。
DIP(=Device Independent Pixel、デバイス非依存ピクセル)とは、XAMLコードでコントロールのサイズなどを指定するときの単位である。1DIPは1論理インチの96分の1であり、1論理インチは72ポイントのフォントの高さと定義されている。
ウィンドウの論理サイズを取得するコードは、次のようになる。
Windows.Foundation.Rect logicalSize = Windows.UI.Xaml.Window.Current.Bounds;
double logicalWidth = logicalSize.Width; // 幅(DIP単位)
double logicalHeight = logicalSize.Height; // 高さ(DIP単位)
通常はXAMLコードで指定する寸法(すなわち、DIP単位)で考えているはずなので、この論理サイズが分かれば十分だろう。しかし、物理的なサイズ(実際のピクセル数)を知りたいこともある。そのときは、以降で説明するようにして、論理サイズにスケールファクターを掛け合わせる。
スケールファクター(「スケールプラトー」とも言う)を取得するには、WindowsではDisplayInformationクラス(Windows.Graphics.Display名前空間)のResolutionScaleプロパティを、PhoneではDisplayInformationクラスのRawPixelsPerViewPixelプロパティを使えばよい。
前述の論理サイズを物理的なピクセル数に換算するための係数が、スケールファクターだ。高解像度のモニターでは大きなスケールファクターが適用されており、以前のTIPSで述べたように*8、スケールファクターに応じた画像が自動的に使用される。スケールファクターが取得できれば、物理的なピクセル数に換算することもできるし、解像度に応じた適切な画像をコードで選ぶことも可能になる。
スケールファクターを取得するコードは、次のようになる。共有プロジェクトで記述する場合は、このように「#if」ディレクティブで切り分ける。
#if WINDOWS_APP
// Windows用のコード
Windows.Graphics.Display.ResolutionScale resolutionScale
= Windows.Graphics.Display.DisplayInformation.GetForCurrentView()
.ResolutionScale;
double scaleFactor = (double)resolutionScale / 100.0;
#endif
#if WINDOWS_PHONE_APP
// Phone用のコード
double scaleFactor = Windows.Graphics.Display.DisplayInformation.GetForCurrentView()
.RawPixelsPerViewPixel;
#endif
*8 「WinRT/Metro TIPS:解像度が変わっても画像をシャープに表示するには?[Win 8]」、「WinRT/Metro TIPS:WindowsとPhoneでリソースを切り分けるには?[ユニバーサルWindowsアプリ開発]」
前述した論理サイズにスケールファクターを掛ければよい。
ウィンドウの実際のピクセル数を求めるコードは、前述したコードの変数を使って、次のように書ける。
double physicalWidth = logicalWidth * scaleFactor; // 幅(ピクセル単位)
double physicalHeight = logicalHeight * scaleFactor; // 高さ(ピクセル単位)
DisplayInformationクラスのLogicalDpiプロパティを使えばよい。
1DIPは1論理インチの96分の1であることは前に述べた。これは、スケールファクターが100%のときには、1論理インチに実際のピクセルが96個あるということだ。1論理インチに実際のピクセルがいくつあるかを、論理DPI(=Dot Per Inch、1論理インチあたりのドット数)という。スケールファクターが100%のとき論理DPIは96であり、スケールファクターが200%なら論理DPIは192になる。
逆に言えば論理DPIを96で割ればスケールファクターになるから、論理DPIを使っても実際のピクセル数を求められるのだ。
論理DPIを取得するコードは、次のようになる。
float logicalDpi = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi;
以上で説明した論理DPI/論理サイズ/スケールファクター/実際のピクセル数(以降、物理サイズという)を、ウィンドウのサイズが変更されるたびに表示するアプリを作った(別途公開のサンプルコードを参照)。実行結果は、以下のようになる。
まず、Windowsで画面の向きの違いと複数アプリを表示したときを見てみよう。画面はシミュレーターの10.6インチ、物理サイズは1366×768ピクセル、スケールファクター100%のものだ。表示内容は上から順に、論理DPI/論理サイズ(幅×高さ)/スケールファクター/物理サイズ(幅×高さ)である。スケールファクターが100%なので、論理サイズと物理サイズは一致している。
次は、Windowsでスケールファクターが異なる場合である。画面はいずれもシミュレーターの10.6インチのものだが、スケールファクターは100%(物理サイズ1366×768)/140%(1920×1080)/180%(2560×1440)の3通りだ。後ろ2つの画像のサイズは、論理サイズに合わせて縮小してある。
最後は、Phoneでスケールファクターが異なる場合である。画面はいずれもエミュレーターのもので、「Emulator 8.1 WVGA 4 inch」(=物理サイズ480×800ピクセル、スケールファクター120%)、「Emulator 8.1 720P 4.7 inch」(=720×1280ピクセル、180%)、「Emulator 8.1 WXGA 4.5 inch」(=768×1280ピクセル、200%)の3通りだ。画像のサイズは、3つとも論理サイズに合わせて縮小してある。
画面(正確にはウィンドウ)の論理サイズは簡単に取得できる。別途取得したスケールファクターを使って、論理サイズを物理サイズ(実際のピクセル数)に変換できる。
画面のピクセル密度(=解像度)の扱いについては、次のドキュメントも参照してほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.