Win10开发:玩转应用窗体和应用标题栏TitleBar

来源:互联网 发布:优酷 mac 缓存 编辑:程序博客网 时间:2024/04/29 02:41

Windows10 API允许开发者对应用窗体和应用标题栏做修改。


应用标题栏

先说应用标题栏吧,什么是应用标题栏?比如Groove音乐的应用标题栏就是下面这样:

   

什么,你说看不清楚。因为它是白色的,是微软设计的,这锅我不背。

你不喜欢怎么办?改呗!

Windows10 API提供解决方案,可以更改应用标题栏、右上方三个按钮、鼠标经过时按钮、鼠标按下时按钮、标题栏Inactive时、三个按钮Inactive时的前景色和背景色共12种属性颜色。(这里解释下Inactive,不知道怎么翻译合适,当应用置于你的眼前,在任务栏的应用图标上按住鼠标左键不放时就是Inactive状态,貌似是不可用的状态)

关于标题栏的MSDN看这:链接

什么,你说Edge浏览器的标题栏好像不太一样。没错,因为Edge把应用界面扩展至 Titlebar 的区域,所以看起来不一样。




下面简单的代码实现更改12种属性的颜色值:

  var titleBar = ApplicationView.GetForCurrentView().TitleBar;            if (titleBar != null)            {                titleBar.BackgroundColor = Colors.Black;                titleBar.ForegroundColor = Colors.White;                titleBar.ButtonBackgroundColor = Colors.Brown;                titleBar.ButtonForegroundColor = Colors.RoyalBlue;                titleBar.ButtonPressedBackgroundColor = Colors.Green;                titleBar.ButtonPressedForegroundColor = Colors.Orange;                titleBar.ButtonHoverForegroundColor = Colors.Salmon;                titleBar.ButtonHoverBackgroundColor = Colors.Blue;                titleBar.InactiveForegroundColor = Colors.SpringGreen;                titleBar.InactiveBackgroundColor = Colors.Red;                titleBar.ButtonInactiveBackgroundColor = Colors.Tan;                titleBar.ButtonInactiveForegroundColor = Colors.Violet;            }
效果图

正常时:


鼠标滑过最大化按钮时:

鼠标按下最大化按钮时:


Inactive状态时:



如果要实现Edge浏览器的效果将应用界面扩展至 Titlebar 区域:

CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;

如果以上的修改你还不满意怎么办?不好意思你自己设计吧...

Windows 10允许开发者自定义标题栏控件,可以将界面中任意控件指定为标题栏,使用下面的函数

Window.Current.SetTitleBar(UIElement value);
其中value是一个自定义控件

官方的Demo(修改):自定义应用标题栏

首先需要自定义一个用户控件,也就是自定义的TtitleBar控件

XAML:

<Grid x:Name="RootGrid">        <Grid.RowDefinitions>            <RowDefinition Height="Auto" />            <RowDefinition Height="*" />        </Grid.RowDefinitions>        <Grid x:Name="TitleBar" VerticalAlignment="Top" Height="{x:Bind CoreTitleBarHeight, Mode=OneWay}" Canvas.ZIndex="3">            <Rectangle x:Name="BackgroundElement" Fill="Green" />            <Grid Padding="{x:Bind CoreTitleBarPadding, Mode=OneWay}">                <Grid.ColumnDefinitions>                    <ColumnDefinition Width="*"/>                    <ColumnDefinition Width="Auto"/>                </Grid.ColumnDefinitions>                <TextBlock Grid.Column="0" Text="TextBlock in Custom TitleBar"/>                <CheckBox Grid.Column="1" Content="CheckBox in Custom TitleBar"/>            </Grid>        </Grid>    </Grid>

最外层Grid分为两行是为了布局需要,Demo给了注释说明其作用:



C#代码部分稍微有点多,但都是逻辑很清晰的:

  public sealed partial class CustomTitleBar : UserControl, INotifyPropertyChanged    {        private CoreApplicationViewTitleBar coreTitleBar = CoreApplication.GetCurrentView().TitleBar;        public CustomTitleBar()        {            this.InitializeComponent();            Loaded += CustomTitleBar_Loaded;            Unloaded += CustomTitleBar_Unloaded;        }        void CustomTitleBar_Loaded(object sender, RoutedEventArgs e)        {            coreTitleBar.LayoutMetricsChanged += OnLayoutMetricsChanged;            coreTitleBar.IsVisibleChanged += OnIsVisibleChanged;            // The SizeChanged event is raised when the view enters or exits full screen mode.            Window.Current.SizeChanged += OnWindowSizeChanged;            UpdateLayoutMetrics();            UpdatePositionAndVisibility();        }        void CustomTitleBar_Unloaded(object sender, RoutedEventArgs e)        {            coreTitleBar.LayoutMetricsChanged -= OnLayoutMetricsChanged;            coreTitleBar.IsVisibleChanged -= OnIsVisibleChanged;            Window.Current.SizeChanged -= OnWindowSizeChanged;        }        void OnLayoutMetricsChanged(CoreApplicationViewTitleBar sender, object e)        {            UpdateLayoutMetrics();        }        void UpdateLayoutMetrics()        {            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs("CoreTitleBarHeight"));                PropertyChanged(this, new PropertyChangedEventArgs("CoreTitleBarPadding"));            }        }        void OnIsVisibleChanged(CoreApplicationViewTitleBar sender, object e)        {            UpdatePositionAndVisibility();        }        void OnWindowSizeChanged(object sender, WindowSizeChangedEventArgs e)        {            UpdatePositionAndVisibility();        }        void UpdatePositionAndVisibility()        {            if (ApplicationView.GetForCurrentView().IsFullScreenMode)            {                // In full screen mode, the title bar overlays the content. and might or might not be visible.                TitleBar.Visibility = coreTitleBar.IsVisible ? Visibility.Visible : Visibility.Collapsed;                Grid.SetRow(TitleBar, 1);            }            else            {                // When not in full screen mode, the title bar is visible and does not overlay content.                TitleBar.Visibility = Visibility.Visible;                Grid.SetRow(TitleBar, 0);            }        }        UIElement pageContent = null;        public UIElement SetPageContent(UIElement newContent)        {            UIElement oldContent = pageContent;            if (oldContent != null)            {                pageContent = null;                RootGrid.Children.Remove(oldContent);            }            pageContent = newContent;            if (newContent != null)            {                RootGrid.Children.Add(newContent);                // The page content is row 1 in our grid. (See diagram above.)                Grid.SetRow((FrameworkElement)pageContent, 1);            }            return oldContent;        }        #region Data binding        public event PropertyChangedEventHandler PropertyChanged;        public Thickness CoreTitleBarPadding        {            get            {                // The SystemOverlayLeftInset and SystemOverlayRightInset values are                // in terms of physical left and right. Therefore, we need to flip                // then when our flow direction is RTL.                if (FlowDirection == FlowDirection.LeftToRight)                {                    return new Thickness() { Left = coreTitleBar.SystemOverlayLeftInset, Right = coreTitleBar.SystemOverlayRightInset };                }                else                {                    return new Thickness() { Left = coreTitleBar.SystemOverlayRightInset, Right = coreTitleBar.SystemOverlayLeftInset };                }            }        }        public double CoreTitleBarHeight        {            get            {                return coreTitleBar.Height;            }        }        #endregion        public void EnableControlsInTitleBar(bool enable)        {            if (enable)            {                Window.Current.SetTitleBar(BackgroundElement);            }            else            {                Window.Current.SetTitleBar(null);            }        }    }
自定义的TitleBar准备好了后,就可以在需要的时候添加或移除这个CustomTitleBar就可以了,使用前需要修改CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;  

首先需要声明:

CustomTitleBar customTitleBar = null;
需要的时候Add:

public void AddCustomTitleBar()        {            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;            if (customTitleBar == null)            {                customTitleBar = new CustomTitleBar();               // customTitleBar.EnableControlsInTitleBar(true);                // Make the main page's content a child of the title bar,                // and make the title bar the new page content.                UIElement mainContent = this.Content;                this.Content = null;                customTitleBar.SetPageContent(mainContent);                this.Content = customTitleBar;            }        }
不需要的时候Remove:

  public void RemoveCustomTitleBar()        {            CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = false;            if (customTitleBar != null)            {                // Take the title bar's page content and make it                // the window content.                this.Content = customTitleBar.SetPageContent(null);                customTitleBar = null;            }        }
大功告成!

官方示例在此:https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/TitleBar/cs

注意:在Mobie上,应用是没有TitleBar的说法的,同时也是全屏的,因此不存在以上操作

说明一下,上述代码出自官方Demo,注释给的挺清楚,真的可以学到很多

关于自定义TitleBar,stackoverflow上有人提问如何在窗口右上方的三个键旁放一个全屏键(链接:stackoverflow),微博上的@JustinAndDesign 在回答中给出了解决方案,在这里暂不做讲解


应用窗体

到此,TitleBar的基本知识讲解差不多了。

接着说说应用窗体,其实所涉及到的东西前面已经出现过了,主要通过下面的方法获取到当前应用窗体:

var view = ApplicationView.GetForCurrentView();

view有几个主要的属性和方法:

Title:窗体的标题,区别于应用标题栏的标题

TitleBar:当前窗体对应的应用标题栏

Orientation:获取当前窗体的方向,值为Landscape或Portrait

IsFullScreen:布尔值,获取当前窗体是否是最大化

IsFullScreenMode:布尔值,获取当前窗体是否是满屏

IsOnLockScreen:布尔值,获取当前窗体是否位于Windows锁定屏幕上

IsScreenCaptureEnabled:获取或设置窗体是否启用窗体捕获

ExitFullScreenMode():方法,无返回值。退出全屏模式

TryEnterFullScreenMode():方法,返回值布尔值,进入全屏模式是否成功


Demo:切换窗体满屏显示

  private void ToggleFullScreenMode(object sender, RoutedEventArgs e)        {            var view = ApplicationView.GetForCurrentView();            view.Title = "我是窗体标题";            if (view.IsFullScreenMode)              {                //退出满屏模式                view.ExitFullScreenMode();            }            else            {                if (view.TryEnterFullScreenMode())                {                    //进入满屏模式成功                }                else                {                    //进入全屏模式失败                }            }        }

0 0
原创粉丝点击