顯示具有 XAML 標籤的文章。 顯示所有文章
顯示具有 XAML 標籤的文章。 顯示所有文章

2009年10月13日 星期二

如何讓WPF控制項產生陰影效果

WPF中可以利用BitmapEffect(點陣圖效果), 使控制項呈現一些影像特效;如: Blur(模糊效果), Shadow(陰影效果), Bevel(斜面), Emboss(凹凸)和色彩光暈等....

在這篇文章中, 我們先來介紹會使控制像看起來比較有立體感的陰影效果.

由於BitmapEffect Visual 物件上的屬性, 因此, 我們可將BitmapEffect套用至任何視覺物件(例如 Button,Image, DrawingVisual 或 UIElement)上. 例如我們可以利用DropShadowBitmapEffect 物件建立 WPF 物件的各種下拉式陰影效果.

它提供下列屬性來讓你自訂陰影效果:
  • Color - 設定陰影的顏色
  • Opacity - 設定陰影的透明度, 設定範圍為0 至1, 預設值是1
  • ShadowDepth - 控制陰影的寬,有效值的範圍為 0 至 300。預設值為 5
  • Direction - 控制陰影的方向。請將這個屬性的方向值設定為介於 0 與 360 之間的度數. 0表示陰影會顯示在物件的正右方, 隨著Direction的增加, 陰影會逆時針方向移動
  • Softness - 控制陰影的柔和度或模糊,值 0.0 表示沒有模糊,而值 1.0 則表示全部模糊

下面的範例中, 我們將圖1透過DropShadowBitmapEffect 的效果, 產生出如圖片2的陰影效果:

XAML檔如下所示:

<Image Source="tulips.jpg"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="80, 50, 80, 50"
Name="image1"
Stretch="Fill" >
<Image.BitmapEffect>
<DropShadowBitmapEffect ShadowDepth="20"
Direction="300"
Color="Black"
Opacity="0.5"
Softness="0.25" />
</Image.BitmapEffect>
</Image>



[圖1]沒有陰影效果



[圖2]加上陰影效果



需要注意的地方:
WPF 點陣圖效果是在軟體模式中呈現. 而且是由UI執行緒執行, 而不是呈現的執行緒, 因此使用點陣圖效果會對效能有很大的影響(效能和元素的數量成正比), 所以最好在少量而且是靜態的內容才使用這些效果. 尤其在大型視覺物件上使用點陣圖效果, 或者以點陣圖效果的屬性建立動畫時, 效能會降低最多.


參考文章 :
MSDN - 點陣圖效果概觀
MSDN - 建立含陰影的文字

2009年8月9日 星期日

WPF 面板 - Layout Properties

UI設計時必須考慮控制項的位置,大小和排列(有不同的面板配置), 來作版面配置(Layout), 版面配置還必須根據視窗大小不同, 而作相對的改變, 因此, 我們先來了解版面配置的一些基本屬性:

這篇文章先說明子控制項常見的版面配置方式:

  • Width and Height - 控制項的寬和高, 如果設成Auto的話, 它們的值會變成Double.NaN, 這時後你就必須透過 ActualHeightActualWidth(唯讀屬性)來取得畫面配置後的高和寬. 注意: Width / Height的值是可以改變的, 但ActualHeight / ActualWidth是不行的.

  • MinWidth, MaxWidth, MinHeight, and MaxHeight -控制項的最小/最大寬和高; 注意: 如果你同時在元件中設定了Height, ActualHeight, MinHeightMaxHeight, 如果Height落在MinHeightMaxHeight 之間, Height的優先權為最高, 但是如果衝突發生時, 它們的優先順序如下(Width屬性一樣):MinHeight > MaxHeight > Height > ActualHeight
  • HorizontalAlignment and VerticalAlignment - 子項目相對於母容器的水平和垂直對齊(例如, Button在StackPanel中的水平或垂直對齊); HorizontalAlignment對齊的方式可分成: Left, Center, Right, Sretch(子控制項會延伸填滿母容器的配置版面空間). VerticalAlignment對齊方式為: Top, Center, Bottom ,Stretch; 注意:Stretch為預設值, 如果有設定WidthHeight, 則以WidthHeight值為優先, 下面為HorizontalAlignment 範例說明:

<Border Background="LightBlue"
BorderBrush="Black"
BorderThickness="2"
Padding="15">
<StackPanel Background="White"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<TextBlock Margin="5,0,5,30"
FontSize="20"
Foreground="Red"
VerticalAlignment="Top"
HorizontalAlignment="Center">
HorizontalAlignment Sample
</TextBlock>
<Button Background="Gold"
HorizontalAlignment="Center"
Margin="10">Left</Button>
<Button Background="LightGreen"
HorizontalAlignment="Right">Right</Button>
<Button Background="Honeydew"
HorizontalAlignment="Center">Center</Button>
<Button Background="Ivory"
HorizontalAlignment="Stretch">Stretch</Button>
</StackPanel>
</Border>

結果如圖示:



[圖1] HorizontalAlignment Sample

  • Margin - 控制元素外的邊界的大小. 例如 Margin="0,10,5,25"(邊界順序為, 左, 上,右,下); 或是寫成Margin="10" 來設定成均等邊界,正確使用Margin可以精確控制項目的呈現位置.
  • Padding- 控制元素邊界內的大小
下面為MarignPadding的範例說明:

首先, 我們拉出一個StackPanel, 然後塞入四個button, XAML檔和畫面如下:

<StackPanel>
<Button Name="button1"
Background="AliceBlue">Button
</Button>

<Button Name="button2"
Background="Beige">Button 2
</Button>

<Button Name="button3"
Background="Pink">Button 3
</Button>

<Button Name="button4"
Background="LightGreen">Button 4
</Button>
</StackPanel>


[圖2] 沒有Margin和Padding

然後, 我們在每個button的屬性中加入 Margin = "10", 可以看到下面的畫面中, button和其他項目有對應的邊界.

<Button Name="button1"
Background="AliceBlue"
Height="40"
Margin="10">Button
</Button>


[圖3] Margin Sample

然後, 我們再把Margin屬性換為Padding = "10", 可以看到下面的畫面, 每個button content的內邊界都作增加.

<Button Name="button1"
Background="AliceBlue"
Height="40"
Padding="10">Button
</Button>



[圖4] Padding Sample
  • HorizontalContentAlignment and VerticalContentAlignment - 除了控制項可以作水平或垂直對齊外, 控制項的內容也有這樣的對齊方式, 請看下面範例和圖示.

<StackPanel>
<Button Name="button1"
Background="AliceBlue"
Height="40"
HorizontalContentAlignment="Left">Button
</Button>

<Button Name="button2"
Background="Beige"
Height="40"
HorizontalContentAlignment="Right">Button 2
</Button>

<Button Name="button3"
Background="Pink"
Height="40"
VerticalContentAlignment="Top">Button 3
</Button>

<Button Name="button4"
Background="LightGreen"
Height="40"
VerticalContentAlignment="Bottom">Button 4
</Button>
</StackPanel>


[圖5] HorizontalContentAlignment Sample

2009年8月3日 星期一

WPF功能 - 3D 繪圖

3D繪圖是WPF的特色之一, 利用WPF提供的3D功能, 你可以在應用程式中製做出很棒3D特效.
下面會先介紹WPF 3D繪圖的基本概念, 並且以3D Cube的範例作為說明.


1. 座標系統
圖1 顯示WPF使用的2D和3D座標系, WPF的3D座標系和Direct3D一樣, 是採用右手座標系(OpenGL是使用左手座標系)

[圖 1] 2D和3D座標系統


2. 3D畫布
你可以使用Viewport3D(
投影3D場景的平面)來當作一個3D畫布, 類似2D中Window或Grid.


<Viewport3D>
Children
</Viewport3D>



3. 相機 - Camera
你必須在3D場景中指定相機的位置方向和視野, WPF 提供兩種攝影機, 如下:

a. OrthographicCamera - 垂直投射的攝影機, 它不會因為攝影機的距離而改變尺寸, 適合CAD或2D繪圖

b. PerspectiveCamera - 透視投射的攝影機, 離攝影機越遠的物體, 看起來會縮小和變短, 類似真實世界所看到的影像


另外Camera中還一些參數可設定:
  • Position(攝影機的座標 )
  • LookDirection(攝影機拍攝的方向 )
  • UpDirection(攝影機的法向量 )
  • FiledOfView(攝影機的拍攝角度 , PerspectiveCamera才可以設定)
  • Width(觀景的寬度, OrthographicCamera 才可以設定)
攝影機在XAML的寫法如下所示:


<Viewport3D.Camera>
<PerspectiveCamera x:Name="camera"
Position="0,0,5"
LookDirection="0,0,-10"
UpDirection="0,1,0"
FieldOfView="45" />
</Viewport3D.Camera>


1. 3D模型
- ModelVisual3D

a. Light

如果在3D場景中沒有打光的話, 畫面會是一片黑暗.

WPF提供下面幾種光源, 供使用者使用:

  • AmbientLight(周遭光源, 光線來自四處)
  • DirectionalLight(方向光源, 類似太陽光)
  • PointLight(點光源, 類似燈泡或蠟燭)
  • SpotLight(聚光燈)
下面程式碼(XAML)顯示燈光的使用:

<ModelVisual3D>
<ModelVisual3D.Content>
<DirectionalLight x:Name="light" Direction="-1,-1,-1" Color="White"/>
</ModelVisual3D.Content>
</ModelVisual3D>


b. MeshGeometry3D
WPF是利用
三角形建立來3D模型, 其相關的參數如下:

  • Position(三角形的頂點)
  • TriangleIndices(指定頂點的連接順序)
  • Normals(三角形面的法向量, 可指定正面和反面)
  • TextureCoordinates(指定貼圖座標)
下面的程式碼顯示如何產生一個矩形的平面:


<MeshGeometry3D
Positions="-1 -1 0 1 -1 0 -1 1 0 1 1 0"
Normals="0 0 1 0 0 1 0 0 1 0 0 1"
TextureCoordinates="0 1 1 1 0 0 1 0"
TriangleIndices="0 1 2 1 3 2" />
</GeometryModel3D.Geometry>


c. Material
我們可以為3D模型加上材質, WPF提供下面這些材質來作設定.
  • DiffuseMaterial
  • SpecularMaterial
  • EmissiveMaterial
下列程式碼式碼(XAML)顯示顯示如何使用材質:


<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<SolidColorBrush Color="Cyan">
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>


看完上面介紹後, 我們就用XAML寫一個3D Cube. 程式碼如下所示:

<Window x:Class="WPF3DCube.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Window1" Height="407" Width="342">

<Grid>

<Viewport3D Name="viewport3D1">



<!--Setup Camera-->

<Viewport3D.Camera>

<PerspectiveCamera

x:Name="camera"

Position="6 5 4"

LookDirection="-6 -5 -4"

FieldOfView="30">

</PerspectiveCamera>

</Viewport3D.Camera>



<!--Setup Light-->

<ModelVisual3D>

<ModelVisual3D.Content>

<DirectionalLight x:Name="light"

Direction="-1,-1,-1"

Color="White"/>

</ModelVisual3D.Content>          

</ModelVisual3D>



<ModelVisual3D>

<ModelVisual3D.Content>                  

<GeometryModel3D>


<!--Build 3D Cube-->

<GeometryModel3D.Geometry>

<MeshGeometry3D x:Name="cube"

Positions="0 0 0  1 0 0
0 1 0  1 1 0
0 0 1  1 0 1
0 1 1  1 1 1"

TriangleIndices="2 3 1  2 1 0  7 1 3
7 5 1  6 5 7  6 4 5
6 2 0  2 0 4  2 7 3
2 6 7  0 1 5  0 5 4">

</MeshGeometry3D>                          

</GeometryModel3D.Geometry>                    



<!--Setup Material-->

<GeometryModel3D.Material>                         

<DiffuseMaterial x:Name="matDiffuseMain">

<DiffuseMaterial.Brush>

<SolidColorBrush Color="Bisque"/>

<DiffuseMaterial.Brush>

</DiffuseMaterial>

</GeometryModel3D.Material>



</GeometryModel3D>

</ModelVisual3D.Content>

</ModelVisual3D>

</Viewport3D>

</Grid>
</Window>


其結果如下所示:


[圖 2] 3D Cube

參考文章 :
MSDN - WPF 3D Graphics
CodeProject :
WPF 3D Primer

2009年8月2日 星期日

WPF功能 -2D Transform

WPF提供2D Transform的功能, 可以讓你對控制元件或2D圖形作轉換.

Transform的類別有下面幾種:


RotateTransform(旋轉)
  • Angle - 旋轉角度
  • CenterX - 旋轉中心的X座標
  • CenterY- 旋轉中心的Y座標

下面的XAML檔示範如何將一個button旋轉45度

<Button Height="37"
Margin="100"
Name="rotateButton"
VerticalAlignment="Top"
Content="Rotate">
<Button.RenderTransform>
<RotateTransform Angle="45">
</RotateTransform>
</Button.RenderTransform>
</Button>


如果將上例改用C#,其程式碼如下所示:

rotateButton.Height = 37;
rotateButton.Margin = new Thickness(100);
rotateButton.VerticalAlignment = VerticalAlignment.Top;
rotateButton.Content = "Rotate";
RotateTransform rotateT = new RotateTransform();
rotateT.Angle = 45;
rotateButton.RenderTransform = rotateT;



[圖1] Rotate Button

在上面範例中, 元件並不是以自己的中心點作旋轉, 因為WPF Transform的原點, 預設是在元件的左上角. 因此, 如果你想繞著物件的中心點作旋轉的話, 可以改變CenterX,CenterY, 或設定RenderTransformOrigin屬性, 不過設定CenterX和CenterY, 必須設定絕對座標, 相對上比較困難. 因此將 RenderTransformOrigin設為相對的(0.5,0.5)比較容易作到. 使用RenderTransformOrigin的XAML檔如下所示


<Button Height="37"
Margin="100"
Name="rotateButton"
VerticalAlignment="Top"
Content="Rotate"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<RotateTransform Angle="45">
</RotateTransform>
</Button.RenderTransform>
</Button>




C#的程式碼如下所示:

rotateButton.Height = 37;
rotateButton.Margin = new Thickness(100);
rotateButton.VerticalAlignment = VerticalAlignment.Top;
rotateButton.Content = "Rotate";
rotateButton.RenderTransformOrigin = new Point(0.5, 0.5);
RotateTransform rotateT = new RotateTransform();
rotateT.Angle = 45;
rotateButton.RenderTransform = rotateT;




[圖2] Rotate Button+RenterTransformOrigin



ScaleTransform(縮放)
  • ScaleX - X軸的縮放比例
  • ScaleY - Y軸的縮放比例
  • CenterX - 縮放中心的X座標
  • CenterY - 縮放中心的Y座標
下面的XAML檔示範如何將一個button放大2倍


<Button Height="37"
Margin="100"
Name="scaleButton"
VerticalAlignment="Top"
Content="Scale"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2">
</ScaleTransform>
</Button.RenderTransform>
</Button>




[圖 3] ScaleTransform

你也可以將ScaleY設為負值, button中的文字就會像倒影, 呈現上下顛倒(reflection). 程式碼如下所示:


<Button Height="37"
Margin="100"
Name="scaleButton"
VerticalAlignment="Top"
Content="Scale"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="-1">
</Scaleransform>
</Button.RenderTransform>
</Button>




[圖 4] 顛倒的button



TranslteTransform(平移)
  • X - 移動的X軸座標
  • Y - 移動的Y軸座標
下面的XAML檔示範如何將一個button往右和下各移動50



<Button Height="37"
Margin="100"
Name="translateButton"
VerticalAlignment="Top"
Content="Translate"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<TranslateTransform X="50" Y="50">
</TranslateTransform>
</Button.RenderTransform>
</Button>



[圖 5] TranslateTransform



SkewTransform(傾斜)

  • AngleX - X軸的傾斜角度
  • AngleY- Y軸的傾斜角度
  • CenterX - 傾斜中心的X座標
  • CenterY - 傾斜中心的Y座標

下面的XAML檔示範如何將一個button作傾斜:


<Button Height="37"
Margin="100"
Name="skewButton"
VerticalAlignment="Top"
Content="Skew"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<SkewTransform AngleX="20" AngleY="30">
</SkewTransform>
</Button.RenderTransform>
</Button>





[圖 6] SkewTransform

TransformGroup

若你要同時對一個元件作旋轉,平移和縮放, 可以使用TransformGroup將這些轉換放在一起. 但你必須小心, 使用多重轉換時, 順序非常重要, 例如, 如果先旋轉在平移, 和先平移在作旋轉, 這兩種轉換的最後結果會不一樣.

下面的XAML示範如何使用TransformGroup


<Button Height="37"
Margin="100"
Name="transformButton"
VerticalAlignment="Top"
Content="Group"
RenterTransformOrigin=".5,.5">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="2">
</ScaleTransform>
<RotateTransform Angle="45">
</RotateTransform>
</TransformGroup>
</Button.RenderTransform>
</Button>




C#的程式碼如下所示


skewButton.Height = 37;
skewButton.Margin = new Thickness(100);
skewButton.VerticalAlignment = VerticalAlignment.Top;
skewButton.Content = "Group";
skewButton.RenderTransformOrigin = new Point(0.5, 0.5);

ScaleTransform scaleT = new ScaleTransform();
scaleT.ScaleX = 2;

RotateTransform rotateT = new RotateTransform();
rotateT.Angle = 45;

TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(scaleT);
transformGroup.Children.Add(rotateT);

skewButton.RenderTransform = transformGroup;





[圖 7] TransformGroup

附註: 除了上述的RenderTransform外, 另外還有一個叫LayoutTransform的轉換. LayoutTransform 會影響到UI配置的結果, 因為它會在UI畫面配置之前作套用, 而RenderTransform是在UI畫面已經配置完後才作套用.