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给了注释说明其作用:
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 { //进入全屏模式失败 } } }