使用WPF来创建 Metro UI_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 使用WPF来创建 Metro UI

使用WPF来创建 Metro UI

 2014/4/23 21:46:57  GC2013  博客园  我要评论(0)
  • 摘要:当我第一次运行Zune时,我为这些美丽的UI所折服。当时就说这肯定不是用WPF做的,因为这些字体是如此的清晰而且UI反映的也非常快速。。而且我从维基百科上也了解到Zune的第一个版本是2006年发布的,而WPF与.NET3.0却是2006年11月发布的。那么问题来了,如果它不是WPF做的,那它是用什么技术做到的呢?为了找到答案,我使用ProcessExplorer工具来看看Zune是如何启动的,默认情况下,.NET应用程序都是被用黄色高亮显示的。很好,这说明Zune肯定是.net应用程序了
  • 标签:创建 使用

当我第一次运行Zune时,我为这些美丽的UI所折服。当时就说这肯定不是用WPF做的,因为这些字体是如此的清晰而且UI反映的也非常快速。。而且我从维基百科上也了解到Zune的第一个版本是2006年发布的,而WPF与.NET 3.0却是 2006 年11月发布的。

  那么问题来了,如果它不是WPF做的,那它是用什么技术做到的呢?为了找到答案,我使用Process Explorer工具来看看Zune是如何启动的,默认情况下,.NET应用程序都是被用黄色高亮显示的。 使用WPF来创建 Metro UI
 

很好,这说明Zune肯定是.net 应用程序了,然后我们可以看到Zune需要如下库
使用WPF来创建 Metro UI

然后用 Reflector一看: https://github.com/moodmosaic/moodmosaic.github.com/raw/master/images/BuildingaMetroUIwithWPFimage5.png
  如你所见,根名空间是 Microsoft.Iris. 我在Google上搜到这玩意看上去就像某种原始的WPF组件 -- MCML   WPF能创造出类似的UI吗? 第一个难点就是就是设定WindowStyle为None。因为这有这有才能让标题栏以及边框不可见 使用WPF来创建 Metro UI
  那该如何移动窗体呢? 首先添加一个Shape(Rectangle),然后为它订阅PreviewMouseDown事件处理 01 class="comments">// Is this a double-click? 02 if (DateTime.Now.Subtract(m_headerLastClicked) <= s_doubleClick) 03 { 04   // Execute the code inside the event handler for the 05   // restore button click passing null for the sender 06   // and null for the event args. 07   HandleRestoreClick(nullnull); 08 } 09   10 m_headerLastClicked = DateTime.Now; 11   12 if (Mouse.LeftButton == MouseButtonState.Pressed) 13 { 14   DragMove(); 15 }

 

该如何任意改变窗体大小? 在主窗体的四个角分别添加一个Shape(比如Rectangle)然后为它们都订阅PreviewMouseDown事件处理: 01 Rectangle clickedRectangle = (Rectangle)sender; 02      03 switch (clickedRectangle.Name) 04 { 05   case "top": 06       Cursor = Cursors.SizeNS; 07       ResizeWindow(ResizeDirection.Top); 08       break; 09   case "bottom": 10       Cursor = Cursors.SizeNS; 11       ResizeWindow(ResizeDirection.Bottom); 12       break; 13   // ... 14 }   下面就是用鼠标重新调整窗体大小的代码 01 /// <summary> /// Resizes the window. 02 /// </summary> /// <param name="direction">The direction. 03 private void ResizeWindow(ResizeDirection direction) 04 { 05   NativeMethods.SendMessage(m_hwndSource.Handle, WM_SYSCOMMAND, 06       (IntPtr)(61440 + direction), IntPtr.Zero); 07 } 08   09 [DllImport("user32.dll", CharSet = CharSet.Auto)] 10 internal static extern IntPtr SendMessage( 11   IntPtr hWnd, 12   UInt32 msg, 13   IntPtr wParam, 14   IntPtr lParam);

 

如何为窗体添加阴影效果。 实际上有两种做法: 第一种就是试用DWM API。这个方法需要订阅SourceInitialized事件。 01 /// <summary> /// Raises the <see cref="FrameworkElement.Initialized"> event. 02 /// This method is invoked whenever 03 /// <see cref="P:FrameworkElement.IsInitialized"> /// is set to true internally. 04 /// </see></see></summary> /// <param name="e">The <see cref="T:RoutedEventArgs"> /// that contains the event data. 05 protected override void OnInitialized(EventArgs e) 06 { 07   AllowsTransparency    = false; 08   ResizeMode            = ResizeMode.NoResize; 09   Height                = 480; 10   Width                 = 852; 11   WindowStartupLocation = WindowStartupLocation.CenterScreen; 12   WindowStyle           = WindowStyle.None; 13   14   SourceInitialized    += HandleSourceInitialized; 15   16   base.OnInitialized(e); 17 } 18      19 /// <summary> /// Handles the source initialized. 20 /// </summary> /// <param name="sender">The sender. 21 /// <param name="e">The <see cref="System.EventArgs"> /// instance containing the event data. 22 private void HandleSourceInitialized(Object sender, EventArgs e) 23 { 24   m_hwndSource = (HwndSource)PresentationSource.FromVisual(this); 25   26   // Returns the HwndSource object for the window 27   // which presents WPF content in a Win32 window. 28   HwndSource.FromHwnd(m_hwndSource.Handle).AddHook( 29       new HwndSourceHook(NativeMethods.WindowProc)); 30   31   // http://msdn.microsoft.com/en-us/library/aa969524(VS.85).aspx 32   Int32 DWMWA_NCRENDERING_POLICY = 2; 33   NativeMethods.DwmSetWindowAttribute( 34       m_hwndSource.Handle, 35       DWMWA_NCRENDERING_POLICY, 36       ref DWMWA_NCRENDERING_POLICY, 37       4); 38   39   // http://msdn.microsoft.com/en-us/library/aa969512(VS.85).aspx 40   NativeMethods.ShowShadowUnderWindow(m_hwndSource.Handle); 41 }</see></see>

 

无阴影的窗体 使用WPF来创建 Metro UI
有阴影的窗体 使用WPF来创建 Metro UI      第二种方法就是使用四个外部的透明窗体来制造了阴影的假象,如下图所示 使用WPF来创建 Metro UI
  1,用代码的方式创建一个透明的窗体 2,找到Main Window 在屏幕上的坐标,尤其是左上角 3,计算4个透明窗口的坐标 4,当我们移动Main Window时,4个边框透明窗口也需要跟着移动 5,当我们重新设定 Main Window大小时,4个边框透明窗口也要跟着变化大小。   说这么多看上去好像很难,来让我们看看实现的代码吧。   创建透明窗体的代码 01 /// <summary> /// Initializes the surrounding windows. 02 /// </summary> private void InitializeSurrounds() 03 { 04   // Top. 05   m_wndT = CreateTransparentWindow(); 06   07   // Left. 08   m_wndL = CreateTransparentWindow(); 09   10   // Bottom. 11   m_wndB = CreateTransparentWindow(); 12   13   // Right. 14   m_wndR = CreateTransparentWindow(); 15   16   SetSurroundShadows(); 17 } 18      19 /// <summary> /// Creates an empty window. 20 /// </summary> /// <returns></returns> private static Window CreateTransparentWindow() 21 { 22   Window wnd             = new Window(); 23   wnd.AllowsTransparency = true; 24   wnd.ShowInTaskbar      = false; 25   wnd.WindowStyle        = WindowStyle.None; 26   wnd.Background         = null; 27   28   return wnd; 29 } 30   31 /// <summary> /// Sets the artificial drop shadow. 32 /// </summary> /// <param name="active">if set to <c>true</c> [active]. 33 private void SetSurroundShadows(Boolean active = true) 34 { 35   if (active) 36   { 37       Double cornerRadius = 1.75; 38   39       m_wndT.Content = GetDecorator( 40           "Images/ACTIVESHADOWTOP.PNG"); 41       m_wndL.Content = GetDecorator( 42           "Images/ACTIVESHADOWLEFT.PNG", cornerRadius); 43       m_wndB.Content = GetDecorator( 44           "Images/ACTIVESHADOWBOTTOM.PNG"); 45       m_wndR.Content = GetDecorator( 46           "Images/ACTIVESHADOWRIGHT.PNG", cornerRadius); 47   } 48   else 49   { 50       m_wndT.Content = GetDecorator( 51           "Images/INACTIVESHADOWTOP.PNG"); 52       m_wndL.Content = GetDecorator( 53           "Images/INACTIVESHADOWLEFT.PNG"); 54       m_wndB.Content = GetDecorator( 55           "Images/INACTIVESHADOWBOTTOM.PNG"); 56       m_wndR.Content = GetDecorator( 57           "Images/INACTIVESHADOWRIGHT.PNG"); 58   } 59 } 60   61 [DebuggerStepThrough] 62 private Decorator GetDecorator(String imageUri, Double radius = 0) 63 { 64   Border border       = new Border(); 65   border.CornerRadius = new CornerRadius(radius); 66   border.Background   = new ImageBrush( 67       new BitmapImage( 68           new Uri(BaseUriHelper.GetBaseUri(this), 69               imageUri))); 70   71   return border; 72 }   计算位置高度的代码  
查看源码   打印? 01 /// <summary> /// Raises the <see cref="FrameworkElement.Initialized"> event. 02 /// This method is invoked whenever 03 /// <see cref="FrameworkElement.IsInitialized"> /// is set to true internally. 04 /// </see></see></summary> /// <param name="e">The <see cref="T:RoutedEventArgs"> /// that contains the event data. 05 protected override void OnInitialized(EventArgs e) 06 { 07   // ... 08   09   LocationChanged += HandleLocationChanged; 10   SizeChanged     += HandleLocationChanged; 11   StateChanged    += HandleWndStateChanged; 12   13   InitializeSurrounds(); 14   ShowSurrounds(); 15   16   base.OnInitialized(e); 17 } 18      19 /// <summary> /// Handles the location changed. 20 /// </summary> /// <param name="sender">The sender. 21 /// <param name="e">The <see cref="System.EventArgs"> /// instance containing the event data. 22 private void HandleLocationChanged(Object sender, EventArgs e) 23 { 24   m_wndT.Left   = Left  - c_edgeWndSize; 25   m_wndT.Top    = Top   - m_wndT.Height; 26   m_wndT.Width  = Width + c_edgeWndSize * 2; 27   m_wndT.Height = c_edgeWndSize; 28   29   m_wndL.Left   = Left - m_wndL.Width; 30   m_wndL.Top    = Top; 31   m_wndL.Width  = c_edgeWndSize; 32   m_wndL.Height = Height; 33   34   m_wndB.Left   = Left  - c_edgeWndSize; 35   m_wndB.Top    = Top   + Height; 36   m_wndB.Width  = Width + c_edgeWndSize * 2; 37   m_wndB.Height = c_edgeWndSize; 38   39   m_wndR.Left   = Left + Width; 40   m_wndR.Top    = Top; 41   m_wndR.Width  = c_edgeWndSize; 42   m_wndR.Height = Height; 43 } 44      45 /// <summary> /// Handles the windows state changed. 46 /// </summary> /// <param name="sender">The sender. 47 /// <param name="e">The <see cref="System.EventArgs"> /// instance containing the event data. 48 private void HandleWndStateChanged(Object sender, EventArgs e) 49 { 50   if (WindowState == WindowState.Normal) 51   { 52       ShowSurrounds(); 53   } 54   else 55   { 56       HideSurrounds(); 57   } 58 }</see></see></see>

 


原文链接 OSChina.NET原创翻译
发表评论
用户名: 匿名