Minimize Event ( C# Win 8.1 app) - c#

I'm developing an App for windows 8.1 and i need to execute a method to pause some tasks or play a sound when the app is minimized in the sidebar.
I tried:
Application.Current.Suspending += new SuspendingEventHandler(Method_Name);
private void Method_Name(object sender, object e)
{
Other_Method();
}
But this event takes a few seconds (5~10) to occur after I minimize the app.
What event occurs when the app is dragged to the sidebar? What process sends the event?
Thanks.

Check out this post for the answer. It's WindowSizeChanged and check the value of ApplicationView.Value.
[EDIT]
Apparently for 8.1 things have changed a bit. The ApplicationView stuff is deprecated (that was quick) but this still takes place in SizeChanged for the window. Check out this for more details.

After long searching I found something that is not exactly what i wanted, but it works.
This event occurs everytime that visibility of the page changes (Is started, is maximized or minimized for exemple), then you must do some conditions using the if operator.
Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(One_Method);
private void One_Method(object sender, Windows.UI.Core.VisibilityChangedEventArgs e)
{
if(Some_Condition)
{
//TODO: Code that you want execute.
}
}
I'll keep the answer in open for the case of someone knows something more efficient.

Related

Show a Window while application is closing

I've a very heavy application that takes some time to close itself (it also depends on the pc where it is running.. but this is not the matter right now)
I would like to show a custom window with a message during this closing time, but as soon as i call the "Shutdown" method every window disappears (except made for the MessageBox).
This is the code i'm trying to use to achieve my objective
void MainWindow_Closing(object sender, CancelEventArgs e)
{
Task.Factory.StartNew(() =>
{
var closingWaitTest = "application closing, please wait;
Application.Current.Dispatcher.Invoke(() =>
{
var closingSplash = new ClosingSplashWindow(closingWaitTest);
closingSplash.Show();
});
MessageBox.Show(closingWaitTest);
});
Application.Current.Shutdown();
}
I Added a messageBox just to check, and it actually works. I mean, the MessageBox stays open until the application process is alive (i check that from the windows TaskManager) while my Window is instantly closed.
Hope someone can give some advice about this,
thanks in advance (:
EDIT -
So, the main problem is that as soon as i call the Application.Current.Shutdown my splash window instantly closes, while the application process is still up and running for some time (disposing all my things before calling shutdown actually reduced this time a bit).
The point is that i would like to show a window for the entirety of time that the process is still up; given the fact that a MessageBox behaves exactly like that, my question is:
Is there a way to make my ClosingSplashWindow behave like a MessageBox and stay visible until the application process is really dead?
Since Application.Current.Shutdown(); is going to close the application immediately. Maybe you first have a flag to track that application is being closed, cancel the Closing event and initiate the Resource cleanup followed by Application.Current.Shutdown(); again.
The Application_Closing handler may get fired once again, since you've a flag which says you're about to close you can directly exit the handler and all should be good.
First of all, you want to have a flag which indicates that your application is currently shutting down:
private bool IsShuttingDown { get; set; }
Then you should cancel closing operation, perform some heavy work and shut down your application:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!IsShuttingDown)
{
e.Cancel = true;
ShowSplashWindow();
PerformHeavyOperation();
Application.Current.Shutdown();
IsShuttingDown = true;
}
}
In the end I solved the problem creating another application that shows a window while the main application process is still up and running.
I know it is not the best way to do it, but i was not able to do it in any other way..
Thank for the support! :)

Alarm without message dialog

I would like to make and App that when users set an alarm (like wake up alarm) and alarms sounds, doesnt show a message dialog to confirm and stop the alarm.
On web I have discovered some methods called Obscured and UnObscured that fired when the message's alarm shows, but the message still showed!
In Code:
public OverAlarmPage()
{
InitializeComponent();
PhoneApplicationFrame phoneAppRootFrame = (Application.Current as App).RootFrame;
phoneAppRootFrame.Obscured += OnObscured;
phoneAppRootFrame.Unobscured += Unobscured;
}
void OnObscured(Object sender, ObscuredEventArgs e)
{
txtStatus.Text = "Obscured event occurred";
}
void Unobscured(Object sender, EventArgs e)
{
txtStatus.Text = "Unobscured event occurred";
}
I just want to make stop the alarm sound with the vibrating of mobile (with gyroscope) but without the hell message!
There are any solution or is this a O.S feature that i cant touch?
The built in notification classes (Alarm and Reminder) don't support any customization of the UI that is displayed when they are triggered.
The only alternative I can think of would require the application to remain running (possibly under the lock screen) and then you just play the sound from the app at the appropriate time.
Obviously this requires that the app remain running though.
Other than that you will be prevented from trying to create the behaviour you are after.

Drag'n'drop to a Windows form issue

I have, what should be, a simple question on drag'n'drop. I have a fresh Win Form project where the form has set to allow drops using AllowDrop = true. Should also mention that I am running Windows 7 64-bit.
Just to be sure, I have subscribed to
this.DragDrop += new System.Windows.Forms.DragEventHandler(Form1_DragDrop);
as well.
But when I run the app and drag anything from my desktop or explorer, it indicates with the mouse pointer icon that I am not allowed to drop any file(s) to it after all.
I found a a similar question like this one (but Win Vista) where the issue was that Visual Studio was running with admin priveleges which windows explorer wasn't. But building the app and running the executable results in the same problem.
I have done this many times in the past and couldn't Google my way to solve this one. What am I missing?
By default the target drop effect of a drag-and-drop operation is not specified (DragDropEffects.None). Thus there is no drop event for your control in this case.
To allow Control to be a drag-and-drop operation's receiver for the specific data you should specify the concrete DardDropEffect as shown below (use the DragEnter or DragOver events):
void Form1_DragDrop(object sender, DragEventArgs e) {
object data = e.Data.GetData(DataFormats.FileDrop);
}
void Form1_DragEnter(object sender, DragEventArgs e) {
if(e.Data.GetDataPresent(DataFormats.FileDrop)) {
e.Effect = DragDropEffects.Copy;
}
}
Related MSDN article: Performing a Drag-and-Drop Operation in Windows Forms
You are using the wrong Event, use the DragEnter Event.
this.DragEnter += new System.Windows.Forms.DragEventHandler(Form1_DragDrop);

How do I "Hide()" a Modal WPF Window without it closing?

I have a WPF window that is run on a background thread as a sort of "notifier window"... when an event is raised, it displays a message... a user clicks the "Snooze" button and I call this.Visibility = Visibility.Collapsed
The very moment that I hide the window (either by calling this.Hide() or setting the Visibility as mentioned above)... the "ShowDialog()" code releases the window and closes it.
This is absolutely a bug in the WPF code (which I've identified via reflector)... but my question remains. Has anyone been able to come up with a work-around for this issue?
I've tried many things and am now reaching out to ya'll smart people :)
You can't hide a modal dialog. That's like asking, "How do I get to 100mph in reverse?" You don't, you drive the car forwards.
Use Show, not ShowDialog. Alternately you can simply re-ShowDialog when it needs to become visible again.
Timothy's Answer is good. I just needed for my scenerio to add the following
window.Closed += new EventHandler(window_Closed);
window.Show();
System.Windows.Threading.Dispatcher.Run();
and then in the event...
void window_Closed(object sender, EventArgs e)
{
System.Windows.Threading.Dispatcher.ExitAllFrames();
}
I needed to do this because it was hanging on the Run after the form was really closed.
In order to show modal window always use ShowDialog().
Use Close() instead of Hide().
Handle the FormClosing event like that:
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Visible = false;
}
OK, and as quickly as that - my boss (old C++ goofy guy that he is) figured out the answer.
Here was the code inside of my background thread (which is set to STA mode):
// Show dialog - keeps the thread open and shows the window! Yay!!!
new BeamUI.Notifier.NotifierWindow().ShowDialog();
And here is the modification, that strangely enough works perfectly :)
// Show... hmm, that shows the window... but how do I keep this thread open?
new BeamUI.Notifier.NotifierWindow().Show();
// ZOMG - a line of code that JUST keeps the thread (and msgpump) going!!!
System.Windows.Threading.Dispatcher.Run();
And that's it.
This kinda thing makes me hate C++ people though, and makes me want to just say "if you just built it right in the first place I wouldn't have to look for a work-around!" (j/k)

Why is Form.Refresh() not working?

I'm running a data import, using a Windows form to kick off the import and show progress.
I've got this whole thing so nice and user friendly, with major and minor progress bars and everything... but just one problem... the form refresh keeps going AWOL.
I have a call to Form.Refresh() every time I update my labels/progress bars, and it usually starts off working. But if ever I need to break into debug mode, just to hand-hold the import a bit, the Refresh() call stops working, and sometimes even if I'm running without Debug mode, at some unpredictable point the same thing happens: the labels and progress bars do not get updated, and if you hide the form and reopen it, the form does not repaint at all - it just shows up entirely white.
Why, oh why, does Form.Refresh() stop working, and how can I fix this?
It sounds as if the import runs on the UI thread, which means that this thread is blocked, preventing the form from repainting itself. A better approach would be to use a BackgroundWorker component, do the import in the DoWork event handler and use the ProgressChanged to update the UI.
Example:
private void StartImport()
{
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.RunWorkerAsync();
}
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// do some work simulating a lenghy process which occasionally
// reports progress with data back to the caller
for (int i = 0; i < 100; i++)
{
Thread.Sleep(200);
backgroundWorker.ReportProgress(i, "Item No " + i.ToString());
}
}
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
listBox.Items.Add(e.UserState.ToString());
}
Using this approach you will typically not need to call Refresh to force a repaint of the form.
You may want to change your code into using BeginUpdate and EndUpdate, like so:
Control.BeginUpdate();
// Do something to the control, e.g. add items or whatnot
Control.EndUpdate();
This way Refresh shouldn't be necessary.
AFAIK constantly calling Refresh is really a hack and should be avoiding, as it stresses the CPU quite a bit (it has to refresh everything instead of just the things which are changed).
Edit: If the form starts being white, it seems the drawing code is not been called at all, which indicates it's somewhat not responding.
I'd check the code for anything that can deadlock or otherwisely hang.
You could use observer pattern..in short if anything changes in model observer pattern will make sure that change is visible on form..
google it for some examples..
Depending on what .NET framework you're using, you can use the Task.Run approach:
private void btnShowProgress_Click(object sender, EventArgs e)
{
progressBar1.Value = 0;
Task.Run(() =>
{
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(100);
progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Value = i; }));
}
});
}
Task.Run info
Using invoke with controls
The solution may not be the best practice but it definitely works for small applications.
In Form1 create a bool to check to see if the form is closed.
public bool formclosed = false
Then in Form2 on the Form Closing Event Handler add
formclosed = true
also in the Form2 after
InitializeComponent();
add
formclosed = false;
In Form1 create a timer.
In the timer1.Tick event handler say
private void timer1_Tick(object sender, EventArgs e)
{
if(formclosed == true)
{
Application.Restart();
}
}
This will restart the application and refresh everything ... I also had my text saved to the Properties.Settings.Default so everytime the application started the default settings would show.
I created an initial version of a Progress control using a BackgroundWorker. The Progress control computed and displayed nice things like Estimated Duration, Estimated Time to Completion. Each statistic was displayed by custom control based on a Label control. The Progress control worked in my production code.
Then I made some changes to the Progress control. I switched from basing my custom statistics controls from Label to Panel. I successfully ran all my tests (using NUnit). Then, I created a Test Windows Forms app. The Progress control successfully worked in the Test Windows Forms app.
When I ran my production Windows app with the updated Progress control it didn't display the statistics.
I tried Thread.Sleep(N), Form.Refresh(). None of those worked to update the statistics.
I eventually called Control.Invalidate() on each Statistic control. The Invalidate caused OnPaint to be called and the control happily updated the display with its specific statistic.
For Each Stat_Obj As Control in Statistics_Controls
Stat_Obj.Invalidate()
Next
You might need to give the window time to redraw itself. I understand you're doing the import in a loop and the loop is running on the main UI thread? Try adding this line to the loop:
Application.DoEvents();

Categories

Resources