Make visible baloonTipText until it is clicked - c#

I have a NotifyIcon in my program which displays a baloon tip in the taskbar. I wrote code as
notifyIcon1.Icon = new Icon(SystemIcons.Application, 40, 40);
notifyIcon1.Visible = true;
notifyIcon1.Text = "Test Notify Icon Demo";
notifyIcon1.BalloonTipText =count+ " Alerts";
notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
notifyIcon1.BalloonTipTitle = "Alert!";
notifyIcon1.ShowBalloonTip(999999999);
The baloon tip is invisible after the set time (999999999). But I want to show the baloon tip until it is clicked as I have baloontipclicked event.
How to make baloontip visible forever?

from MSDN:
Minimum and maximum timeout values are enforced by the operating
system and are typically 10 and 30 seconds, respectively, however this
can vary depending on the operating system. Timeout values that are
too large or too small are adjusted to the appropriate minimum or
maximum value. In addition, if the user does not appear to be using
the computer (no keyboard or mouse events are occurring) then the
system does not count this time towards the timeout.
it seems not be possible to override the maximum timeout (eventually adjusted by Windows and limited to 30 seconds even if you specify a longer one) so the Notification will fade away, will not wait for you to click on it after 2 minutes.
if you want to really have a different behavior you should probably use something else, other objects or simulate something similar with forms where you have the full control on the behavior and you can show, hide and close as you wish from your code.

You can show it again if it hasn't been clicked.
You have the close event (BalloonTipClosed), if user hasn't ckicked it just show it again.
private void ShowBalloonTip(int minutes) {
notifyIcon.BalloonTipIcon = ToolTipIcon.Error;
notifyIcon.BalloonTipText = "Text";
notifyIcon.BalloonTipTitle = "Title";
notifyIcon.ShowBalloonTip(minutes* 60 * 1000);
m_showUntil = DateTime.Now.AddMinutes(minutes);
}
private void notifyIcon_BalloonTipClosed(object sender, EventArgs e) {
if (m_showUntil > DateTime.Now)
notifyIcon.ShowBalloonTip(60 * 1000);
}
private void notifyIcon_BalloonTipClicked(object sender, EventArgs e) {
m_showUntil = DateTime.MinValue;
(..)
}

Related

"shutdown.exe" destroys application settings

I have a one-window WPF application (Win8.1 / .net4.7), the Window.Closing-Event is unhandled, the Window.Closed-Event is handled as follows:
private void Window_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.WinMainLocationX = this.Left; // ok
Properties.Settings.Default.WinMainLocationY = this.Top; // ok
Properties.Settings.Default.WinMain_size = new Size(this.Width, this.Height); // crucial setting
Properties.Settings.Default.WinMain_state = this.WindowState; // ok
Properties.Settings.Default.Save();
}
I'm closing the app (at this point always in idle state) once a day by a batch file containing C:\WINDOWS\system32\shutdown.exe /s /t 20 and nothing afterwards. By this the computer shuts down properly. The parameters of shutdown.exe can be seen by command line input of shutdown /?.
Problem: Every 7 or 8 days the window size gets corrupted in a way that the application (after having started in the morning) looks like this:
How can I protect my application settings from interference by shutdown.exe?
I think the problem is storing the settings while the application window is minimized. Width and Height of the window will be 0 in this case.
You can use the RestoreBounds property of your window to get its restored size independent of its current state:
Properties.Settings.Default.WinMainLocationX = this.RestoreBounds.Left;
Properties.Settings.Default.WinMainLocationY = this.RestoreBounds.Top;
Properties.Settings.Default.WinMain_size = new Size(this.RestoreBounds.Width, this.RestoreBounds.Height);
Properties.Settings.Default.WinMain_state = this.WindowState;
Some answers to this question show another approach using the WinAPI functions GetWindowPlacement / SetWindowPlacement:
.NET WPF Remember window size between sessions
Adding Environment.Exit(0)has solved the issue. I can imagine the cause of the problem was that the Window.Closed-Handler has been reached twice.
private void Window_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.WinMainLocationX = this.Left; // ok
Properties.Settings.Default.WinMainLocationY = this.Top; // ok
Properties.Settings.Default.WinMain_size = new Size(this.Width, this.Height); // crucial setting
Properties.Settings.Default.WinMain_state = this.WindowState; // ok
Properties.Settings.Default.Save();
Environment.Exit(0);
}

Link Media Element on WPF with Label and Slider

I have linked the import button with a media element so i can get the song to play.
// Create OpenFileDialog
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
// Set filter for file extension and default file extension
dlg.DefaultExt = ".txt";
dlg.Filter = "WAV Files (*.wav)|*.wav|MP3 Files (*.mp3)|*.mp3|MP4 Files (*.mp4)|*.mp4|WMA Files (*.wma)|*.wma|SWA (*.swa)|*.swa";
// Display OpenFileDialog by calling ShowDialog method
Nullable<bool> result = dlg.ShowDialog();
// Get the selected file name and display in a TextBox
if (result == true)
{
// Open document
meMedia1.Source = new Uri(dlg.FileName);
meMedia1.Play();
//txtFileLocation.Text = filename;
Now, the sound plays but what I want to do is link a slider so they can skip some of the song and also a label above the slider so that it read how long into the song it is. This is how my application looks now to give you an idea.
http://i.stack.imgur.com/sVtrd.png
Thank You.
EDIT : Got the seek to change the song position but I still cant get it manually moving to the time of the song, for example if I skip to the middle of the song, and let the song finish my slider will still be in the middle and I want it to be at the end.
One approach is to create a DispatcherTimer that ticks every 200-800ms (depending on your preference for update speed) that syncs the slider to the player's current Position. That code might look similar to this:
// In the class members area
private DispatcherTimer _timer = null;
// In your constructor/loaded method
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(500);
_timer.Tick += _timer_tick;
// Timer's tick method
void _timer_tick(object sender, EventArgs e)
{
// Convert duration to an integer percentage based on current position of
// playback and update the slider control
TimeSpan ts = meMedia1.NaturalDuration.TimeSpan;
int percent = int( meMedia1.Position / ts.Seconds * 100 );
mySliderControl.Value = percent;
}
Note that this assumes you have a Slider whose Min is 0 and Max is 100. You can bump it up to 0-1000 (and change the math accordingly) to get finer granularity. This also doesn't allow the slider to push user interaction back to the player, but gives you an idea of one way to get the opposite. You can add an event handler to the Slider such that when the user begins interacting, this _timer is stopped ( _timer.Stop() ) so updates to the media position stop updating the slider and instead start doing your slider -> media position updates instead. Then when the user lets go of the slider, turn the _timer back on ( _timer.Start() ).

Simple button animations

I am trying to learn .NET programming. As a part of my learning, I tried to make some effects on buttons. It is working... but not as smooth as I imagined! Is there any better way to do this? Thank you in advance!
My need:
There are 3 buttons.
When you hover the mouse over one of them, it expands and when you mouse out from that button, it returns to its initial size.
private void button1_MouseHover(object sender, EventArgs e)
{
button1.BackColor = Color.White;
button1.Width = 130;
button1.BringToFront();
}
private void button1_MouseLeave(object sender, EventArgs e)
{
button1.BackColor = Color.Red;
button1.Width = 75;
}
private void button2_MouseHover(object sender, EventArgs e)
{
button2.BackColor = Color.Gray;
button2.Width = 130;
button2.BringToFront();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
button2.BackColor = Color.Red;
button2.Width = 75;
}
private void button3_MouseHover(object sender, EventArgs e)
{
button3.BackColor = Color.DimGray;
button3.Width = 130;
button3.BringToFront();
}
private void button3_MouseLeave(object sender, EventArgs e)
{
button3.BackColor = Color.Red;
button3.Width = 75;
}
So first off, you don't want to do the exact same thing 3 times. Create a single method to add the appropriate handlers for a button, and then just write the code once to handle any given button.
Note that you can go into the expand/contract tick handlers and use the percentComplete value to set the height as well, to move the color along a spectrum (this would involve some mathematics of colors to do though) or to alter any other aspect of the button. If you're really motivated to generalize it you could add a parameter to the method of Action<double> that does something to the object based on the given percent progress.
public void AddAnimation(Button button)
{
var expandTimer = new System.Windows.Forms.Timer();
var contractTimer = new System.Windows.Forms.Timer();
expandTimer.Interval = 10;//can adjust to determine the refresh rate
contractTimer.Interval = 10;
DateTime animationStarted = DateTime.Now;
//TODO update as appropriate or make it a parameter
TimeSpan animationDuration = TimeSpan.FromMilliseconds(250);
int initialWidth = 75;
int endWidth = 130;
button.MouseHover += (_, args) =>
{
contractTimer.Stop();
expandTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.DimGray;
};
button.MouseLeave += (_, args) =>
{
expandTimer.Stop();
contractTimer.Start();
animationStarted = DateTime.Now;
button.BackColor = Color.Red;
};
expandTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
expandTimer.Stop();
}
else
{
button.Width = (int)(initialWidth +
(endWidth - initialWidth) * percentComplete);
}
};
contractTimer.Tick += (_, args) =>
{
double percentComplete = (DateTime.Now - animationStarted).Ticks
/ (double)animationDuration.Ticks;
if (percentComplete >= 1)
{
contractTimer.Stop();
}
else
{
button.Width = (int)(endWidth -
(endWidth - initialWidth) * percentComplete);
}
};
}
If you are using WinForms, animations are going to be rather painful and you will have to handle them yourself via Timer objects.
If you are getting into .NET and want to make cool-looking applications with animatons and styling, I highly recommend you look at WPF instead. It can do animations very easily though C# or XAML.
While it is still possible in WinForms, it will take far more development time where as those features are built into WPF already (and optimized).
When you modify a controls properties, it takes effect instantaneously. What you desire is something that is usually known as some type of fade or tweening. There might be libraries out there to do this, but if you wanted to write this yourself for fun, you can use a Timer object, and on each tick update the color.
What you would do is set a color as the TargetColor somewhere(this is a variable or property you make up), and then start a timer that ticks maybe every 10 milliseconds. In each tick, you look at the start time, and how long has passed since then. If you want the animation to take place of a full second, then that is 1000 milliseconds. So during each tick, you look at the amount of time that has passed, maybe 200 milliseconds, then divide 200/1000 to get the fraction of time that you have gone into the animation. Then you look at a difference between the Start and Target Color, multiply that difference by the fraction, and add the result to the start color. In other words, 200 milliseconds into an animation that last 1000 milliseconds, means you are 20% into the animation. Thus you want to set the color to be whatever color is 20% from the start color towards the end color.
There's alot you could do to refine this. Perhaps having a subclass Button control that encapsulates the timer and exposes functions/properties to track start/end color, animation transition time, etc. Most animated UI features like this let you specify how long the animation should last, and then it interpolates the inbetween states as it transitions. This is the origin of the term tweening, as it comes from transitioning from one state to another by inbetweening

I want to display the form before the speech output

My problem is that the program speaks before the form gets displayed.
Here's the load block:
/********************
* *
* Start Game *
* *
********************/
private void Battleship_Load(object sender, EventArgs e)
{
// Interface housekeeping
lblStatus.Font = new Font("HandelGotDLig", 18);
// fill computer board
game.buildBoards();
human = game.Human;
computer = game.Computer;
shot = game.Initialize(ref human, ref shot);
//set up displays
gbComputerHistory.Visible = false;
gbHumanHistory.Visible = false;
gbShot.Visible = false;
lblStatus.Text = "Choose who starts";
gbStart.Visible = true;
// display human board
DisplayBoard(picHuman, human, false);
// display computer ships
DisplayBoard(picComputer, computer, false);
this.Refresh();
#if SPEECH
Say("Welcome to BATTLESHIP! Prepare to Lose!");
Say("Choose who starts first.");
#endif
}
I suspect I could bury it in the paint event, but then I'd have to keep track of whether it has spoken already.
I don't want it speaking every time the form is repainted.
Try adding the speech code to the Form_Shown event. This event is raised whenever the form is shown to the user (when they can actually see it). From MSDN:
The Shown event is only raised the first time a form is displayed; subsequently minimizing, maximizing, restoring, hiding, showing, or invalidating and repainting will not raise this event.

Is there anyway to know when the screen has been updated/refreshed (OpenGL or DirectX maybe?)

I currently have an application I'm writing in c# (using .NET) that requires me to start a timer as soon as a user sees an image on screen up until they respond with a key press.
Now I realise that practically this is very difficult given the monitor input lag and response time, the time the keyboard takes to physically send the message, the OS to process it, etc.
But I'm trying my best to reduce it down to mostly a constant error (the response time results will be used to compare one user to the next so a constant error isn't really an issue). However annoying hurdle is the variable caused by the monitor refresh rate, as I gather when my onPaint message is called and done with, it doesn't mean the image has actually been processed and sent from the graphics buffer?
Unfortunately time restrictions and other commitments would realistically restrict me to continuing this task in c# for windows.
So what I was wondering was if either handling all the drawing in OpenGL or DirectX or better still for me if it is possible to just using either OpenGL or DirectX to create an event when the screen is updated?
Another suggestion given to me previously was regarding V-Sync, if I switch this off is the image sent as soon as it is drawn? as opposed to sending images at a set rate synchronised to the monitor refresh rate?
You must render your graphic in a separate thread in order to:
Use vertical synchronisation to have a precise timing of the effective display of your image.
Get the precise timing of your user input (since user interface is not on the same thread than the render loop.
Initialise Direct3D to enable the VSync during render :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Perform the render in a separate thread:
Thread renderThread = new Thread(RenderLoop);
renderThread.Start();
shouldDisplayImageEvent = new AutoResetEvent();
Then use the following render loop:
void RenderLoop()
{
while(applicationActive)
{
device.BeginScene();
// Other rendering task
if (shouldDisplayImageEvent.WaitOne(0))
{
// Render image
// ...
userResponseStopwatch = new Stopwatch();
userResponseStopwatch.Start();
}
device.EndScene();
device.Present();
}
}
Then handle the user input :
void OnUserInput(object sender, EventArgs e)
{
if (userResponseStopwatch != null)
{
userResponseStopwatch.Stop();
float userResponseDuration = userResponseStopwatch.ElapsedMillisecond - 1000 / device.DisplayMode.RefreshRate - displayDeviceDelayConstant;
userResponseStopwatch = null;
}
}
You now use the shouldDisplayImageEvent.Set() event trigger to display the image as needed and start the stop watch.
First enable the VSync on your application idle loop :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Application.Idle += new EventHandler(OnApplicationIdle);
// More on this here : http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
internal void OnApplicationIdle(object sender, EventArgs e)
{
Msg msg = new Msg();
while (true)
{
if (PeekMessage(out msg, IntPtr.Zero, 0, 0, 0))
break;
}
// Clearing render
// ...
if (displayImage)
{
// Render image
// ...
renderTime = DateTime.now();
}
device.Present();
}
With the vsync enabled, the device.Present function block until the next frame synchronisation, so if you compute the time between renderTime and the user input time and remove the display device delay + 16.67ms you should get your user response delay.

Categories

Resources