Im trying to add a custom splashscreen on my windows 8 store app
I managed to get it to work, but the default SplashScreen still appears before my Custom one.
This is my SplashScreen XAML:
<Page
x:Class="CartuxaTablet.ExtendedSplash"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CartuxaTablet"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#FF0000">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="180"/>
</Grid.RowDefinitions>
<Canvas Grid.Row="0">
<Image x:Name="extendedSplashImage" Source="ms-appx:///Assets/splash.png" Canvas.Left="158" Canvas.Top="48" />
</Canvas>
<StackPanel Grid.Row="1" HorizontalAlignment="Center">
<ProgressRing IsActive="True"></ProgressRing>
</StackPanel>
</Grid>
and the code behind:
namespace CartuxaTablet
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
partial class ExtendedSplash
{
internal Rect splashImageRect; // Rect to store splash screen image coordinates.
internal bool dismissed = false; // Variable to track splash screen dismissal status.
internal Frame rootFrame;
private SplashScreen splash; // Variable to hold the splash screen object.
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent();
// Listen for window resize events to reposition the extended splash screen image accordingly.
// This is important to ensure that the extended splash screen is formatted properly in response to snapping, unsnapping, rotation, etc...
Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
splash = splashscreen;
if (splash != null)
{
// Register an event handler to be executed when the splash screen has been dismissed.
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Retrieve the window coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
PositionImage();
}
// Create a Frame to act as the navigation context
rootFrame = new Frame();
// Restore the saved session state if necessary
RestoreStateAsync(loadState);
}
async void RestoreStateAsync(bool loadState)
{
if (loadState)
await SuspensionManager.RestoreAsync();
// Normally you should start the time consuming task asynchronously here and
// dismiss the extended splash screen in the completed handler of that task
// This sample dismisses extended splash screen in the handler for "Learn More" button for demonstration
}
// Position the extended splash screen image in the same location as the system splash screen image.
void PositionImage()
{
extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
extendedSplashImage.Height = splashImageRect.Height;
extendedSplashImage.Width = splashImageRect.Width;
}
void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
{
// Safely update the extended splash screen image coordinates. This function will be fired in response to snapping, unsnapping, rotation, etc...
if (splash != null)
{
// Update the coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
PositionImage();
}
}
// Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// Navigate away from the app's extended splash screen after completing setup operations here...
// This sample navigates away from the extended splash screen when the "Learn More" button is clicked.
}
}
}
and on my App.Xaml.cs i added this.
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
Window.Current.Content = extendedSplash;
}
Window.Current.Activate();
Do i need to do something extra to disable the default Splash Screen?
You can't disable the default splash screen, but you can work with it to customize it. You can see the Guidelines for splash screens (Windows Store apps).
Related
I need to remove this white borders (marked orange pen). I want that my App fit 880px and be full width. In My XAML Document I did next
<Page
x:Class="FirstScreen.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FirstScreen"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="880" Height="600">
<Grid Width="880" Height="600" Background="Black">
</Grid>
</Page>
But I still have white borders! what I need that my App will compile with out this borders?
You can stop window resize, by using TryResizeView(Size) function, but its not recommended to do resize by code behind, when user is engaged in UI.
I will share the solution here , but again ITS NOT RECOMENDED.
in App.xaml.cs , OnLaunched event , once all your UI related code completed, at the end , place this line of code
ApplicationView.GetForCurrentView().TryResizeView(size);
ApplicationView.GetForCurrentView().VisibleBoundsChanged += App_VisibleBoundsChanged;
and create event for "App_VisibleBoundsChanged"
private void App_VisibleBoundsChanged(ApplicationView sender, object args)
{
ApplicationView.GetForCurrentView().TryResizeView(size);
}
declare a global variable for Size
Size size = new Size(800, 600);
This will make your app, always work in specified size. But the user feels like a glitch in app, when they try to resize .
Here is the entire App.xaml.cs code
sealed partial class App : Application
{
Size size = new Size(800, 600);
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
ApplicationView.GetForCurrentView().TryResizeView(size);
ApplicationView.GetForCurrentView().VisibleBoundsChanged += App_VisibleBoundsChanged;
}
private void App_VisibleBoundsChanged(ApplicationView sender, object args)
{
ApplicationView.GetForCurrentView().TryResizeView(size);
}
}
You are giving the Grid a width as 880, so the Grid is not fill in all the window. Just remove the width and height that you've added.
I'm trying to navigate from Extended.xaml screen to another screen Main.xaml.
But issue is that the page is stuck there not navigating to another page. How to achieve that? Any help would be appreciated.
Xaml code:
<Grid x:Name="lcol">
<Grid.Background>
<ImageBrush Stretch="Fill"
ImageSource="ms-appx:///Assets/Home/home_android.jpg" />
</Grid.Background>
<RelativePanel Grid.Row="0">
<Image x:Name="extendedSplashImage" Source="/Assets/Home/home_android.jpg"
Stretch="Uniform" Height="385" Width="690"
RelativePanel.AlignHorizontalCenterWithPanel="True"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"/>
</RelativePanel>
</Grid>
Cs code:
public sealed partial class ExtendedSplash : Page
{
internal Rect splashImageRect; // Rect to store splash screen image coordinates.
private SplashScreen splash; // Variable to hold the splash screen object.
internal bool dismissed = false; // Variable to track splash screen dismissal status.
internal Frame rootFrame;
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent()
try
{
var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
}
catch (Exception ex)
{
Log.print(ex.StackTrace);
}
// Listen for window resize events to reposition the extended splash screen image accordingly.
// This is important to ensure that the extended splash screen is formatted properly in response to snapping, unsnapping, rotation, etc...
// Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
splash = splashscreen;
if (splash != null)
{
// Register an event handler to be executed when the splash screen has been dismissed.
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Create a Frame to act as the navigation context
rootFrame = new Frame();
DismissExtendedSplash();
}
}
void PositionImage()
{
extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
extendedSplashImage.Height = splashImageRect.Height;
extendedSplashImage.Width = splashImageRect.Width;
}
void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
{
// Safely update the extended splash screen image coordinates. This function will be fired in response to snapping, unsnapping, rotation, etc...
if (splash != null)
{
// Update the coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
PositionImage();
}
}
// Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// Complete app setup operations here...
}
private void DismissExtendedSplash()
{
rootFrame.Navigate(typeof(MainPage));
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
}
You can show more detail of App.xaml.cs. I suppose your code is written as the official simple like this
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
Window.Current.Content = extendedSplash;
}
Window.Current.Activate();
}
Your ExtendedSplash code :
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent()
try
{
var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
}
catch (Exception ex)
{
Log.print(ex.StackTrace);
}
splash = splashscreen;
if (splash != null)
{
// Register an event handler to be executed when the splash screen has been dismissed.
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Create a Frame to act as the navigation context
rootFrame = new Frame();
DismissExtendedSplash();
}
}
You executed method DismissExtendedSplash() before finished initialization extendedSplash. SoWindow.Current.Conten is MainPage, and then you excuted Window.Current.Content = extendedSplash,The MainPage is replaced with extendedSplash.
I want to display a splash screen in my app since I have to read some data on disk and customize the interface accordingly. If I didn't the effect would be that the interface is loaded and then customized, and the effect is clearly visible. So my idea is define a globla splash screen window and:
In the constructor.
WindowState = WindowState.Minimized; // <---- for the mainWindow
splashScreen.Show();
in the WindowViewBase_Loaded event
SetInterfaceElements(); // <-------interface customization (1)
splashScreen.Close();
WindowState = WindowState.Maximized; // (2)
Activate(); // <------------------------to put focus on
In the end the effect is always the same so a gap between (1) and (2).
So I thought about a refresh problem. I tried to force it with UpdateLayout but no luck. So from here another solution but always the same. Am I missing something??
What you need to do is to create a splash screen class and encapsulate all of its functions. Furthermore, you need to activate the splash screen through a thread, like this:
public static class SplashScreenView
{
public static Show()
{
Thread thread = new Thread(() =>
{
splashScreenView = new SplashScreenView();
....
}
// you code
thread.Start();
}
public static Close()
{
// close splash screen code
}
}
After that your code suppose to be like that:
SplashScreenView.Show();
// all your code
SplashScreenView.Close();
This way you don't need to maximize and minimize your window.
In the mainView constructor
public MainView()
{
SplashScreen splashScreen = new SplashScreen();
splashScreen.Show();
...
}
Then
Action emptyDelegate = delegate { };
bool IsContentRendered = false;
private void WindowViewBase_Loaded(object sender, RoutedEventArgs e)
{
SetInterfaceElements();
Dispatcher.Invoke(emptyDelegate, DispatcherPriority.Render);<---to refresh
IsContentRendered = true;
}
finally
private void WindowViewBase_ContentRendered(object sender, EventArgs e)
{
if (IsContentRendered)
{
if (splashScreen != null)
splashScreen.Close();
WindowState = WindowState.Maximized;
Activate();
}
}
Personally i would go with setting the Splash as the MainWindow on application initialization, doing the required loading in the loaded callback of the splash window and then opening + changing the actual MainWindow. That way you don't have to bother with threads/ui freezes.
My WinForms app's main window is slow to load (up to 20 seconds, depending on arguments), so it needs a splash screen.
The main window constructor is slow because it exercises thousands of lines of code (some of it beyond my influence). Sometimes this code pops up message boxes.
I've tried two splash screen designs, they each have problems. Any better ideas?
Splash screen with BackgroundWorker
static void Main(string[] args)
{
var splash = !args.Contains("--no-splash");
if (splash)
{
var bw = new BackgroundWorker();
bw.DoWork += (sender, eventArgs) => ShowSplash();
bw.RunWorkerAsync();
}
var app = new FormMain(args); // slow. sometimes opens blocking message boxes.
Application.Run(app);
}
private static void ShowSplash()
{
using (var splash = new FormSplash())
{
splash.Show();
splash.Refresh();
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
Problems:
Splash screen sometimes expires before main window open (user thinks app has crashed)
Main window sometimes minimises when splash closes.
Splash screen with WindowsFormsApplicationBase
sealed class App : WindowsFormsApplicationBase
{
protected override void OnCreateSplashScreen()
{
this.SplashScreen = new FormSplash();
}
protected override void OnCreateMainForm()
{
// slow. sometimes opens blocking message boxes.
this.MainForm = new FormMain(this.CommandLineArgs);
}
}
Problems:
Any MessageBoxes opened appear behind splash screen, silently. User won't notice it and thinks app is stuck.
If splash screen is 'always on top', the message box is inaccessible and unclickable.
I agree with Hans Passant in that the code needs to be re-evaluated as the design seems incorrect.
As for the problem at hand, you should be able to resolve this by creating your own instance of a messageBox.
I tested using this code;
public DialogResult TopMostMessageBox(string message, string title, MessageBoxButtons button, MessageBoxIcon icon)
{
return DisplayMessageBox(message, title, button, icon);
}
public DialogResult DisplayMessageBox(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
{
DialogResult result;
using (var topmostForm = new Form {Size = new System.Drawing.Size(1, 1), StartPosition = FormStartPosition.Manual})
{
var rect = SystemInformation.VirtualScreen;
topmostForm.Location = new System.Drawing.Point(rect.Bottom + 10, rect.Right + 10);
topmostForm.Show();
topmostForm.Focus();
topmostForm.BringToFront();
topmostForm.TopMost = true;
result = MessageBox.Show(topmostForm, message, title, buttons, icon);
topmostForm.Dispose();
}
//You might not need all these properties...
return result;
}
//Usage
TopMostMessageBox("Message","Title" MessageBoxButtons.YesNo, MessageBoxIcon.Question)
Again, I need to stress that I agree that the original code needs to be re-factored and am only providing a possible solution to the question.
Hope this helps?
You can implement our own message box and use TopMost property, with TopMost you will get message in-front of splash screen loader.
More about topmost: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.topmost.aspx
In the end, moved the slow code from the constructor to a handler for the OnShown event.
Used WindowsFormsApplicationBase for splash screen as Hans Passant suggested, carefully checked the remaining constructor code to make sure it'll never open an message boxes.
I am developing a project and I want to add to it a splash screen. I have checked questions here on Stackoverflow and other blogs and MSDN etc. but could not find the solution I am looking for.
I want my SplashScreen,
1- appear and stay on the screen 3-4 seconds but at the same time I want my Main Window NOT TO appear. When my splash screen fades out completely then Main Window should appear. Many of the examples I have checked out do not implement this. Even though I set SplashScreen.Close.(TimeSpan.FromMiliseconds(4000)) MainWindow still apeear immediately front or back of SplashScreen. They say "add an image to your project, make it's Build Action SplashScreen or Resource, if you want to handle fade out time go App.xaml.cs file and implement your own Main() method and put your logic." I know that already. It does not work.
2- If possible I want my splashscreen NOT TO fade out slowly. I want it to disappear suddenly.(if this is not possible or really hard for a intermediate developer to do it, it is ok. you may disregard.)
And please I want C# code not Xaml. My project is based on WPF adn .NET 4.0 client profile.
Thank you.
Why don't you make your splash screen a fully qualified XAML <window> and in your App.xaml set it up as your StartupUri:
<Application x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="SplashWindow.xaml">
Then in your splash window's Load Event you initialize the main window (preferably somewhere else so the instance sticks around when you close the splash). From here you can also specify a timer for x-seconds to go off and show the main window / hide the splash window.
using System.Threading;
/// -------------------------------
private Timer t;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
App.MainWindow = new MainWindow(); // Creates but wont show
t = new Timer(new TimerCallback(CloseSplash), null, new TimeSpan(0,0,10), new TimeSpan(0,0,0,0,-1));
// Do Other load stuff here?
}
private void CloseSplash(object info)
{
// Dispatch to UI Thread
Dispatcher.Invoke(DispatcherPriority.Normal, x => CloseSplashMain());
}
private void CloseSplashMain()
{
App.MainWindow.Show()
this.Close();
}
You'll have to change your app's main window behaviour though, otherwise closing the splash window will cause the app to close.
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
App.Current.ShutdownMode = ShutdownMode.OnLastWindowClose;
}
}
Also don't forget to dispose your timer when you're done. It's an IDisposable and will keep firing that method unless it's stopped.
There are answers but I find a an easier one. Just use the Thread.Sleep(int miliSeconds) method in the main window's constructor. This will delay your app in order to open specified miliseconds later.
In the constructor of App.xaml.cs open your splash screen, wait for a few seconds, then close before proceeding with rest of the app. I am using Unity, so I close the splash screen somewhere after the Boostrapper has initialized some services.
public partial class App : Application
{
private static SplashScreen _splashScreen;
public App()
{
OpenSplashScreen();
new Bootstrapper().Run();
}
private void OpenSplashScreen()
{
_splashScreen = new SplashScreen("SplashScreen/splash.jpg");
_splashScreen.Show(false);
}
internal static void CloseSplashScreen(double time)
{
_splashScreen.Close(TimeSpan.FromSeconds(0));
_splashScreen = null;
}
}
where Bootstrapper.cs is listed below:
public class Bootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
base.ConfigureContainer();
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(Container);
// initialize some services before
App.CloseSplashScreen(0);
}
protected override IModuleEnumerator GetModuleEnumerator()
{
return new ExtendedConfigurationModuleEnumerator();
}
protected override DependencyObject CreateShell()
{
MainWindow shell = new MainWindow(Container);
shell.Show();
return shell;
}
}
The best way and using the API is
SplashScreen splash = new SplashScreen("splashscreen.jpg");
splash.Show(false);
splash.Close(TimeSpan.FromMilliseconds(2));
InitializeComponent();