Изменение ориентации экрана (Silverlight)
Дополнительные материалы к занятию можно скачать  здесь.
здесь.
Пользователи держат телефоны по-разному. При этом в зависимости от того, как они его держат, может меняться ориентация экрана. Вертикальная ориентация, когда высота экрана больше его ширины, является портретной (Portrait). Ландшафтная ориентация (Landscape) - это когда телефон повёрнут и ширина экрана больше его высоты. Вы можете создавать приложения, работающие при любой ориентации экрана, но по умолчанию Windows Phone 7 Silverlight приложения запускаются в портретной ориентации. При этом игры, написанные на XNA, запускаются в ландшафтной ориентации (считается, что игры выглядят лучше на широком экране). В данной статье мы сосредоточимся на Silverlight приложениях и рассмотрим ситуацию, когда ориентация экрана меняется в процессе работы приложения [29].
Главная страница по умолчанию работает только в портретном режиме
После создания нового проекта Windows Phone Silverlight приложения в XAML коде страницы MainPage.xaml можно найти следующий отрывок:
SupportedOrientations="Portrait" Orientation="Portrait"
    Это значит, что страница декларирует поддержку только портретной ориентации, в которой, собственно, и работает. Свойство SupportedOrientations может принимать одно из следующих значений:
Данные значения интуитивно понятны.
Свойство Orientation определяет, в какой ориентации страница запускается. Если Вы хотите, чтобы страница запускалась в ландшафтном режиме, не забудьте добавить этот режим в список поддерживаемых. Свойство Orientation может принимать следующие значения:
| Landscape | 
| LandscapeLeft (телефон опрокинут на левый бок) | 
| LandscapeRight (телефон опрокинут на правый бок) | 
| Portrait | 
| PortraitDown (нормальная вертикальная позиция) | 
| PortraitUp (телефон перевёрнут) | 
Из списка видно, что можно задать не только портретную или ландшафтную ориентацию, но и то, в какую сторону будет повёрнут телефон при той или иной ориентации. Это позволяет очень четко указать с какой ориентацией будет запускаться страница [29].
На данном занятии мы займемся изменением ориентации экрана с портретной в ландшафтную.
По умолчанию программы, написанные на Silverlight для Windows Phone 7, выполняются в портретном режиме, а написанные на XNA - в альбомном. Эти настройки по умолчанию можно изменить.
Создадим новое приложение Silverlight Windows Phone 7. По умолчанию используются свойства: SupportedOrientations="Portrait" Orientation="Portrait":
<phone:PhoneApplicationPage 
    x:Class="WindowsPhoneApplication21.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Портретная ориентация" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="По умолчанию" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" 
   FontSize="64" />
        </StackPanel>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
    </Grid>
</phone:PhoneApplicationPage>
    Начальные настройки можно изменить (SupportedOrientations="Landscape"Orientation="Landscape"):
<phone:PhoneApplicationPage 
    x:Class="WindowsPhoneApplication21.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="728" d:DesignHeight="480"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Landscape"  Orientation="Landscape"
    shell:SystemTray.IsVisible="True">
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="Ландшафтная ориентация" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Изменена" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" 
 FontSize="64" />
        </StackPanel>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>
    </Grid>
</phone:PhoneApplicationPage>
    (WindowsPhoneApplication21)
То же самое можно проделать и с XNA-приложениями.
Создадим стандартный проект XNA, в котором на экране будет отображаться строка текста. За основу был взят проект из книги Чарльза Петзольда (Программируем Windows Phone 7)
Далее, добавим к проекту шрифт Segoe: Имя проекта(Content) -> Add -> New Item -> Sprite Font -> Segoe
Затем внесем небольшие изменения в xml-файл описания шрифта:
<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
  <Asset Type="Graphics:FontDescription">
    <FontName>Segoe UI Mono</FontName>
    <Size>32</Size>
    <Spacing>0</Spacing>
    <UseKerning>true</UseKerning>
    <Style>Bold</Style>
    <CharacterRegions>
      <CharacterRegion>
        <Start> </Start>
        <End>~</End>
      </CharacterRegion>
    </CharacterRegions>
  </Asset>
</XnaContent>
    После этого изменим код файла Game1.cs (Чарльз Петзольд):
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame9
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        string text = "Landscape Orientation";
        SpriteFont Segoe;
        Vector2 textSize;
        Vector2 textPosition;
        
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Segoe=this.Content.Load<SpriteFont>("Segoe");
            textSize = Segoe.MeasureString(text);
        }
        protected override void UnloadContent()
        {
        }
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            Viewport viewport =this.GraphicsDevice.Viewport;
            textPosition=new Vector2((viewport.Width-textSize.X)/2,(viewport.Height-textSize.Y)/2);
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            spriteBatch.Begin();
            spriteBatch.DrawString(Segoe,text,textPosition,Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
    
                            Листинг
                        .
                    
Запускаем проект:
Для изменения ориентации с альбомной на портретную внесем небольшие изменения в файл Game1.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame9
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        string text = "Portrait";
        SpriteFont Segoe;
        Vector2 textSize;
        Vector2 textPosition;
        
        
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.SupportedOrientations = DisplayOrientation.Portrait;
            TargetElapsedTime = TimeSpan.FromTicks(333333);
            graphics.PreferredBackBufferWidth = 480;
            graphics.PreferredBackBufferHeight = 800;
        }
        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Segoe=this.Content.Load<SpriteFont>("Segoe");
            textSize = Segoe.MeasureString(text);
        }
        protected override void UnloadContent()
        {
        }
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
            Viewport viewport =this.GraphicsDevice.Viewport;
            textPosition=new Vector2((viewport.Width-textSize.X)/2,(viewport.Height-textSize.Y)/2);
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            spriteBatch.Begin();
            spriteBatch.DrawString(Segoe,text,textPosition,Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
    
                            Листинг
                        .
                    
В результате получаем:
 
                             




