How to execute code when Universal Windows Store App is closing? - c#

I am developing an app for Windows 10 Store app, but I can't seem to find/learn on how to check if the user pressed the red close button (at the top right) or by pressing Alt + F4. Basically what I want is something like this:
private void app_Close(object sender, CloseEventArgs e)
{
//saves some data in the app :D
}

.: EDIT :.
If you have a Universal app that doesn't have a MainWindow object you'll probably want to tap into the "Suspending" event:
appObject.Suspending += (s, a) =>
{
SaveTheData(); // I really like my data and want it for later too
};
or
public App()
{
/*
stuff
*/
Suspending += (s, a) =>
{
SaveTheData(); // I really like my data and want it for later too
};
}
.: Original :.
Add a handler to your MainWindow "Closing" event to save your data. Once "Closing" has finished, "Close" should fire normally.
theMainWindowObject.Closing += (s,a) =>
{
SaveTheData(); // It's precious!
};
I have something similar to this in one of my smaller applications where in the constructor for MainWindow I put the above snippet substituting "theMainWindowObject" for "this" so that it references itself
So I have:
public MainWindow()
{
// Note: "this." isn't necessary here but it helps me with mental accounting
this.Closing += (s, a) =>
{
Save();
};
}
If you're just saving one or two properties and don't have any crazy logic going on you can just drop it right in the handler:
public MainWindow()
{
Closing += (s, a) =>
{
Properties.Settings.Default.SettingsPopupX = mySettingsPopupObject.GetX();
Properties.Settings.Default.SettingsPopupY = mySettingsPopupObject.GetY();
Properties.Settings.Default.Save();
};
}

If you want to manage your Application Lifecycle have a look at this MSDN article: https://msdn.microsoft.com/en-us/library/windows/apps/mt243287.aspx
In general you don't have a "close" event in Windows Apps. Your App will be suspended when Windows or your user wants to close it. Using the ApplicationExecutionState (see more) enum you can find out who (windows or your user) closed the app.
Hope it helps!

Related

Handling multiple clicks on uwp button

I would like to have a different method called depending on the number of time I click on a button, from 1 to 5, on an UWP application.
Is it possible ? How ?
I've used something like this in my windows forms application, maybe it will help. This switch operation was inside button click event.
int clickCounter = 0;
switch (clickCounter)
{
case 1:
{
}
break;
case 2:
{
}
break;
}
Well, one or two clicks is built-in:
var b = new Button();
b.Tapped += (s, e) => { /* TODO */ };
b.DoubleTapped += (s, e) => { /* TODO */ };
But if you want three clicks, say, you need john.kernel's solution (above). Of course, you would use only Tapped to track, then some kind of timing threshold, too. Otherwise they could tap twice in 5 minutes and John's code would fire.
I don't mind interjecting that a triple-click is lame. Not discoverable. But, hey, I don't know your app or your user base, do I? So, you do what you think is right. You are the developer.
Best of luck!

Destructor vs App.Current.Exit vs All other exit handlers

Im having an issue where i need to get my Classes to run a piece of code on exit.
Basically the code writes the Property's and Parameters to an XML file so they can be sent to the programmer to replicate the same settings as the client.
so i have created code like this on each of my classes.
~WorkspaceViewModel()
{
this.Save("Workspace");
}
my problem is that i cannot find a handler that will run before this destructor.
i have tried the following
//App.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
//AppDomain.CurrentDomain.ProcessExit += new EventHandler(ProgramExit);
//App.Current.MainWindow.Closed += new EventHandler(ProgramExit);
//App.Current.Windows[0].Closed += new EventHandler(ProgramExit);
//AppDomain.CurrentDomain.DomainUnload += new EventHandler(ProgramExit);
//App.Current.MainWindow.Unloaded += new System.Windows.RoutedEventHandler(ProgramExit);
//System.Windows.Forms.Application.ApplicationExit += new EventHandler(ProgramExit);
//System.Windows.Application.Current.Exit += new System.Windows.ExitEventHandler(ProgramExit);
And saw something online about modifying the App class so i did this.
public partial class App : System.Windows.Application
{
public void OnExit()
{
this.OnExit();
}
public void App_Exit(Object sender, System.Windows.ExitEventArgs Args)
{
//Somelogic here
}
public App()
{
this.Exit += new System.Windows.ExitEventHandler(App_Exit);
}
}
could someone please help.
Are you using Windows Forms? If so, you can use the Closing event of the form. More reading: Form.Closing Event
Definition:
Occurs when the form is closing.
Example:
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if(MessageBox.Show("Do you want to exit?", "Your app title", MessageBoxButtons.YesNo) == DialogResult.No)
{
e.Cancel = true;
// cancel the closing
}
//otherwise the application will exit
}
You don't really need the if-statement, you can just call the Save method in this event and let the application exit afterwards.
You could do it this way (pseudocode)
Init();
window.Show();
Deinit();
You explicitly run initializers on application start and deinitiliazer on exit.
And in WPF it's done by using Application events, overrides or by a trick (setting Page build action for App.xml). In your implementation, you can't have constructor declared, because it's already generated (file App.g.i.cs). You can use application startup event though or simply set events in xaml.
As it turns out. all i needed to do was create a destructor on the App Class like this
public partial class App : Application
{
~App()
{
Administration.Model.DataBaseModel.GlobalCatalogue.ToFile();
}
}
Not really sure this is the best approach tho
Im still open to better ideas however.. thank you all.

Maximize C# Application from System Tray using Keyboard Shortcut

Can I know if there is anyway that I can maximise my windows form application from the system tray using say a Keyboard Shortcut rather than clicking on it?
I am currently minimizing using this piece of code
//Minimize to Tray with over-ride for short cut
private void MinimiseToTray(bool shortCutPressed)
{
notifyIcon.BalloonTipTitle = "Minimize to Tray App";
notifyIcon.BalloonTipText = "You have successfully minimized your app.";
if (FormWindowState.Minimized == this.WindowState || shortCutPressed)
{
notifyIcon.Visible = true;
notifyIcon.ShowBalloonTip(500);
this.Hide();
}
else if (FormWindowState.Normal == this.WindowState)
{
notifyIcon.Visible = false;
}
}
Hence, I need a keyboard shortcut that should maximize it. Much thanks!
EDIT: If you simply want to 'reserve a key combination' to perform something on your application, a Low-Level keyboard hook whereby you see every keypress going to any other application is not only an overkill, but bad practice and in my personal view likely to have people thinking that you're keylogging! Stick to a HOT-KEY!
Given that your icon will not have keyboard focus, you need to register a global keyboard hotkey.
Other similar questions:
How can I register a global hot key to say CTRL+SHIFT+(LETTER)
Best way to tackle global hotkey processing in c#?
Example from Global Hotkeys With .NET:
Hotkey hk = new Hotkey();
hk.KeyCode = Keys.1;
hk.Windows = true;
hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
if (!hk.GetCanRegister(myForm))
{
Console.WriteLine("Whoops, looks like attempts to register will fail " +
"or throw an exception, show error to user");
}
else
{
hk.Register(myForm);
}
// .. later, at some point
if (hk.Registered)
{
hk.Unregister();
}
To do this, you must use "Low-Level Hook".
You will find all information about it on this article : http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
Look at this too : http://www.codeproject.com/Articles/6362/Global-System-Hooks-in-NET
I second Franck's suggestion about a global keyboard hook. Personally, I had very good experiences with the CodeProject article "Processing Global Mouse and Keyboard Hooks in C#".
As they write in their article, you can do things like:
private UserActivityHook _actHook;
private void MainFormLoad(object sender, System.EventArgs e)
{
_actHook = new UserActivityHook();
_actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
}
You could then call a function in your MyKeyPress handler that opens your window.
If you follow the guide here. It will show you how to register a global shortcut key.
public partial class Form1 : Form
{
KeyboardHook hook = new KeyboardHook();
public Form1()
{
InitializeComponent();
// register the event that is fired after the key press.
hook.KeyPressed += new EventHandler<KeyPressedEventArgs>(hook_KeyPressed);
// register the CONTROL + ALT + F12 combination as hot key.
// You can change this.
hook.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Alt, Keys.F12);
}
private void hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
// Trigger your function
MinimiseToTray(true);
}
private void MinimiseToTray(bool shortCutPressed)
{
// ... Your code
}
}

Custom tray icon notification balloon

I have a C# program that sits in the system tray and pops up a notification balloon now and then. I'd like to provide 2-3 buttons on the notification balloon to allow the user to take various actions when the notification appears - rather than, for example, having to click the notification balloon to display a form containing buttons for each possible action.
I'm looking for suggestions on the best way to go about implementing this.
Edit: clarification, I want to provide buttons on the notification balloon so the user can take direct action on the notification rather than having to take action through some other part of the application (a form or menu for example).
There's no built-in method for this. I would suggest writing your own "balloon" and activating that instead of calling .ShowBalloon()
This is how I do it. It may not be the correct way of doing it. I do this way because .ShowBalloonTip(i) doesn't work as expected for me. It doesn't stay for i seconds and go off. So I do in another thread and forcefully dispose off.
private static NotifyIcon _notifyIcon;
//you can call this public function
internal static void ShowBalloonTip(Icon icon)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(icon);
}
private static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Show(e);
Thread.Sleep(2000); //meaning it displays for 2 seconds
DisposeOff();
}
private static void Show(DoWorkEventArgs e)
{
_notifyIcon = new NotifyIcon();
_notifyIcon.Icon = (Icon)e.Argument;
_notifyIcon.BalloonTipTitle = "Environment file is opened";
_notifyIcon.BalloonTipText = "Press alt+tab to switch between environment files";
_notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
_notifyIcon.Visible = true;
_notifyIcon.ShowBalloonTip(2000); //sadly doesnt work for me :(
}
private static void DisposeOff()
{
if (_notifyIcon == null)
return;
_notifyIcon.Dispose();
_notifyIcon = null;
}

Is it possible to capture any unspecific input event in C#?

I want my application to be able to display certain information when no user input has been detected for some time (like a Welcome/Instruction layer). Is there anyway to have the application register any form of user input (keyboard, mousedown/move etc) without having to write handlers for each of those events?
Is there a generic input window message that gets sent before it is interpreted as being mouse or keyboard or other device? The behaviour I want is similar to Windows waking up from screen saver / sleep on keyboard or mouse input.
I want to avoid something like:
void SomeHandler(object sender, EventArgs e) { WakeUp(); }
...
this.KeyDown += SomeHandler;
this.MouseMove += SomeHandler;
this.SomeInputInteraction += SomeHandler;
The GetLastInputInfo Function is probably what you're looking for. It retrieves the time of the last input event.
I don't know if this works in WPF but this may help:
public class DetectInput : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if ( m.Msg == (int)WindowsMessages.WM_KEYDOWN
|| m.Msg == (int)WindowsMessages.WM_MOUSEDOWN
// add more input types if you want
)
{
// Do your stuff here
}
return false;
}
}
and in Program:
Application.AddMessageFilter(new DetectInput ()); // Must come before Run
Application.Run(YourForm);
Maybe this article on CodeProject will help you. It is about automatically logging off after a period of inactivity using WPF.
Hope this helps.

Categories