Prevent animation on form.Show() when activated from a NotifyIcon - c#

I have a very typical hackish solution for minimizing to system tray in C#:
private void MainFormResize(object sender, EventArgs e) {
if (FormWindowState.Minimized == this.WindowState) {
this.Hide();
systemTrayIcon.Visible = true;
}
}
private void systemTrayIconMouseDoubleClick(object sender, MouseEventArgs e) {
systemTrayIcon.Visible = false;
this.Show();
this.WindowState = FormWindowState.Normal;
}
Ideally, I want my application to disappear/reappear when minimizing to or reopening from the system tray. Minimizing to the system tray works as expected -- the window disappears with no delay and there appears a new tray icon.
Double-clicking on the icon, however, has some very strange effects. The window undergoes a resize animation to its position -- the window appears to fly in from a completely random corner of the screen.
I don't want that. I just want Minimize > -Poof- Disappear and Double-click > -Poof- Appear with no animations or delays or anything of that sort.
Why does this code have an animation? If I call Form.Show() in any other context, the window automatically appears like I want, but when called from a NotifyIcon, it acts strangely. I thought it might be the WindowState = FormWindowState.Normal line, but if I remove that, the window isn't brought to the foreground.
Edit: This problem seems to be OS and theme dependent. The problem doesn't appear to exist in Windows XP, but it's hard to tell because my virtual machine is a little laggy. In Windows 7 Aero, the abitrary-offscreen position problem occurs. In Windows 7 Basic/Classic, it minimizes to the task bar, and reappears from its old position in the taskbar (as if it was actually minimized to the task bar, not the system tray). I haven't tested on Vista. Any tips?

Did you try reordering to put WindowState = FormWindowState.Normal before Show()? I believe the animation you are seeing is the standard window restore animation. Since you are calling Show() before restoring your window, it gets an off-screen position.
Edit: I see your issue now - I looked at it for a second or so, and even tried an IMessageFilter, but for some reason couldn't trap WM_SYSCOMMAND when minimizing (although it fires on restoring).
The one easy thing you could do is live with the minimize animation, though - in your resize handler, just before the Hide() call, set WindowState to Normal. You'll see the minimize animation, but not the maximize (which on most platforms is much less noticeable).

If you need to hide the window when the program runs, your best bet is to create a class that derives from ApplicationContext and shows the NotifyIcon. You then use this class instead of form in the Application.Run.
class TaskTray : ApplicationContext
{
private NotifyIcon _Icon;
public TaskTray()
{
_Icon = new NotifyIcon();
//...
)
}
static void Main()
{
Application.Run(new TaskTray());
}

At least it is possible to have the animation originate from where it should - you have to move the minimized window near the tray notification area: see my hack here

Well, this is an old question, but it's the first result I hit when googling, so I'll share my findings, maybe someone could find this useful.
My application starts with no window showing on the desktop, only a tray icon. The main window can be shown by double-clicking on the tray icon, and closing the window will hide it to the tray icon again.
When my application is hidden, the taskbar icon is hidden as well. However, when it's shown, I have the taskbar icon shown as well, so it can be switched between other windows.
It works as intended. However, I can't help but noticing the animation when showing the window feels very strange and jerky, and it's bugging me a lot. After some digging around, I found the animation behavior is affected by ShowInTaskbar property of the form.
private void ShowMainWindow(object sender, EventArgs e)
{
//ShowInTaskbar = true; // smooth animation
Show();
//ShowInTaskbar = true; // jerky animation
}
Without the ShowInTaskbar = true; line, the window would appear instantly without any animation. Putting the line below Show(); results in the "jerky" animation. Putting the line above Show() gives a smooth fading-in animation and that's the one I choose in the end.

Related

Some questions about Windows Presentation Foundation (C#)

I am working on a program that contains (among other things) a WPF window for which I am using the next code to maximize it at a MouseDoubleClick Event:
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
this.Topmost = true;
Now, what I want to do is that when the window is maximized and the mouse exits the screen (goes to the bottom of the screen until it exits the screen) a new window to appear at the bottom of the screen(WPF or WindowsForm) that will contains several things (buttons, a scrollBars, etc) and that will be active only as long as the mouse is over it (just like in BSplayer). My question is how to do that ? I'm really a starter with WPF, I don't know XAML and I would prefer to do as much as I can using C# code.
So: how do I know when the mouse leaves the screen and how do I make that window to appear on bottom of the screen (without minimizing or doing anything else with the original window) ?
I tried using this.MouseLeave but it doesn't work when the window is maximized.
And if I am asking this question here, I will use my chance to also ask two other things:
When the WPF window is maximized and if the mouse hasn't been moved for more than 5 seconds, than I want the mouse to be hidden and to become visible again only when the mouse moves. How do I do this ?
When the WPF window is not maximized, I want that the border of the screen to be very small, almost invisible (no minimize, close or other button). I am using this.WindowStyle = System.Windows.WindowStyle.ToolWindow but it still leaves the exit/close button there; If I use this.WindowStyle = System.Windows.WindowStyle.None it looks perfect, but then I can't move the window. I there anyway to make the window movable with WindowStyle.None ? Preferably, when I keep the mouse pressed on the interior of the screen, I want to be able to drag the WPF window around on my screen.
Really need help to these problems. It's a pretty important project that I am working on.
Answer to this question
When the WPF window is maximized and if the mouse hasn't been moved for more than 5 seconds, than I want the mouse to be hidden and to become visible again only when the mouse moves. How do I do this ?
This can be achieved by using the timer with an interval of 5 seconds. When timer elapse set mouse cursor to None to hide it and when mouse moves, reset the mouse cursor to original one.
Put below code in the constructor:
this.MouseMove += new MouseEventHandler(MainWindow_MouseMove);
tm = new System.Timers.Timer();
tm.Interval = 5000;
tm.Elapsed += new System.Timers.ElapsedEventHandler(tm_Elapsed);
tm.Start();
Below are event defination:
void MainWindow_MouseMove(object sender, MouseEventArgs e)
{
tm.Stop();
tm.Start();
// Reseting the time back to original. Here I have assumed that original one is Arrow.
this.Dispatcher.Invoke(new Action(() =>
{
Mouse.OverrideCursor = Cursors.Arrow;
}));
}
void tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.Dispatcher.Invoke(new Action(() =>
{
if (Mouse.OverrideCursor != Cursors.None)
{
Mouse.OverrideCursor = Cursors.None;
currentCursor = Mouse.OverrideCursor;
}
}));
}
Hope this helps !!

Preventing Winform from being maximized?

I want to prevent my desktop application from being maximized. It should not become maximized by any means - by double clicking on title bar, or by clicking Windows + Up arrow on the keyboard, etc.
-> I disable both the MaximizeBox and MinimizeBox.
-> I also set the MaximumSize and MinimumSize for my WinForm
Still when I press Windows + Up arrow, my win form Shifts to top left of the screen, I mean it gets maximized.
So please tell me any way to prevent this thing happening...
There are actually two completely separate issues at work here. Granted, they look basically the same from a functional perspective, but from an implementation-model perspective (as Windows itself would naturally use) they are unrelated.
As others have answered, you can prevent your form from being maximized by setting its MaximizeBox property to false. This removes the WS_MAXIMIZEBOX style on the form's underlying window, which prevents the window manager from allowing the window to be maximized. It disables the maximize box on the window's caption bar (the one between the minimize box and the close box), disables the "Maximize" option on the window/system menu, and any other methods of maximizing a window that I may have forgotten.
However, this has nothing to do with the Win+↑ keyboard shortcut, which invokes Aero Snap the same as would dragging the window to the the magic position sat the edges of the screen. The window manager, whether as a result of a bug or a feature of Aero Snap, still allows you to effectively "maximize" windows that should not otherwise be maximized. Setting the MaximizeBox property doesn't affect this, so if you truly want to prevent the user from changing the window's size this way, you will need to disable Aero Snap's effect on your window.
Unfortunately, there's no method (at least, not to my knowledge) of programmatically disabling Aero Snap on a per-window or per-process basis (also see this related question). If the user has Aero Snap enabled, you can assume that they want that behavior and applications aren't supposed to tamper with it. The only thing you can do is completely disable resizing your window. In WinForms, you do that by setting the FormBorderStyle property to one of the following: FormBorderStyle.FixedSingle, FormBorderStyle.Fixed3D, or FormBorderStyle.FixedDialog. If you still want your window to be resizable in other ways, you will need to write the code to handle that manually, which is not a particularly easy task.
Thus, I encourage you to very carefully consider whether this is really necessary. All other non-maximizable windows accomplish this simply by setting the MaximizeBox property (or doing the equivalent in their UI framework), which means that they can still be effectively maximized via Aero Snap. If this works for everyone else's windows, including those that are part of Windows itself, it should probably work for you.
The form has a property called MaximizeBox - set this to false.
In regard to your second question, check out this question and it's answers for the best ways to implement keyboard shortcuts in WinForms.
this.FormBorderStyle = FormBorderStyle.FixedSingle;
That line of code will prevent the user from re-sizing the Window.
In addition to that you hide/disable the maximize box and that should do what you asked.
To disable the maximize box use this
this.MaximizeBox = false;
To hide the maximize box use this as well
this.MinimizeBox = false;
If Maximize and Minimize are set to false the buttons disappear.
Setting the MaximumSize equal to the Size (or some size) at least stops the windows from going full-screen. It still snaps to the top left corner but it's still a window at least and looks right - like it's Windows being stupid instead of your program.
You can prevent the windows snapping to the upper left corner by setting:
private void toolbox_Move(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Normal;
}
in the move event of the form.
There is a property of the Form class named "MaximumBox" you have to set False in the properties window of your form... This actually will disable the form from being maximized by any way... Also if you want to control your form sizes you can work with such properties as "MinimumSize, MaximumSize" setting their values at your discretion or creating an event handler for the MaximumSizeChanged and MinimumSizeChanged events...
You can try to RegisterHotKey Win+Up if your window or application is activated and unregister this hot key if it is deactivated. You must catch the hotkey and return appropriate value to prevent further processing.
Look at WM_ACTIVATEAPP, WM_ACTIVATE and WM_NCACTIVATE. The first can be used if you want to disable the Win+UP for all your windows.
Set formborderstyle to fixedsingle
Maximizebox=false
Set the maximumsize to the size of winform's default size
Ex: if size(646,385) then set maximumsize(646,385)
One thing you can do is set the MaximumSize and MinimumSize in the same value but not 0,0.
It's easy easy! Apply the folling code to maintain window's state to normal when a resize event is triggered.
protected override void OnResize(EventArgs e) {
base.OnResize(e);
WindowState = FormWindowState.Normal;
}

After minimizing app, on restore, windows pursues mouse pointer

I have an application in WPF C# where other than the purpose of what it's done, I customized the close and minimize buttons. The problem is that when I minimize, all is good, I cycle around all other apps, but, when I want to go back to the application, I click in the window in the taskbar, and the window pops up... But when it pops up, the window pursues the mouse pointer throughout the screen...
The code i've implemented the the simplest it can be...
private void Minimize_LeftMouseDown(object sender, MouseButtonEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
Can you point me some directions?
Thanks
It's possible that you've somehow captured the mouse at that point, and the minimize state is preventing WPF's normal release from occurring. If your control is named "Minimize", try adding:
private void Minimize_LeftMouseDown(object sender, MouseButtonEventArgs e)
{
// Make sure we're not capturing the mouse anymore
Mouse.Capture(null);
this.WindowState = WindowState.Minimized;
}
Use the LeftMouseUp event instead of LeftMouseDown. You want to minimize the window when the mouse is released, not when it is pressed down.

WPF window pre-loading

When switching between windows in my full screen WPF app, if it is the first time the screen has been shown, The monitor will go black momentarily before the windows is displayed. This only happens the first time the window is shown. Is there a way to pre-load each window so this does not happen?
This is what I've tried:
myWindow.Show();
myWindow.Hide();
but there is a visible flicker.
Then I tried:
myWindow.Height = 0;
myWindow.Width = 0;
myWindow.WindowState = WindowState.Normal;
myWindow.Show();
myWindow.Hide();
myWindow.Height = Screen.PrimaryScreen.Bounds.Height;
myWindow.Width = Screen.PrimaryScreen.Bounds.Width;
myWindow.WindowState = WindowState.Maximized;
No flicker, but when I then shown the window it showed itself in a weird state for a split second then updated to display properly.
I had a similar problem. In the end I created a splash screen and loaded the controls up behind the splash screen in a seperate thread. This stopped the flashing, but made the initail app load longer.
Apparently this person asked a clearer question.
How can I avoid flicker in a WPF fullscreen app?

How to restore minimized window without flicker

I've made an expose-clone for Vista that sometimes need to restore a minimized window.
I've managed to do this with the SetWindowPlacement function.
The problem is that this also repaints the window which looks like crap after the window nicely has slided into the screen.
This is the code i use to bring a window to the top and give it focus:
private static void ActivateWindow(IntPtr windowToShow)
{
RectAPI r = new RectAPI();
Win32.GetWindowRect(windowToShow, ref r);
if (r.top == -32000) //r.top is -32000 if the window is in minimized state
{
WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
Win32.GetWindowPlacement(windowToShow, ref wp);
if (wp.flags == WindowPlacementFlags.WPF_RESTORETOMAXIMIZED)
wp.showCmd = cmdShow.SW_SHOWMAXIMIZED;
else
wp.showCmd = cmdShow.SW_RESTORE;
Win32.SetWindowPlacement(windowToShow, ref wp);
}
Win32.SetForegroundWindow(windowToShow);
}
If i use it on a window that is already restored it will only call SetForegroundWindow and the window will get to the top of the z-order and get focus without any flicker.
But if i call it on a minimized window I also have to use SetWindowPlacement to bring back the window to restored state. This is what causes the window to repaint and flicker :/
There has to be a way to restore a minimized window without the flicker because the built in window manager does this.
One way to do it is to use double-buffering technique: paint to an off-screen bitmap, then restore, then blit the bitmap to the screen. But it seems like overkill if restoring a minimized window is the only scenario where it's needed. Maybe others will have better ideas?..
Also, if you paint entire window client area, you can disable WM_ERASEBKGND (or rather, say that you processed it but don't do anything) to avoid unneeded fill-with-background-then-redraw sequence.
This link on MSDN will explain how you would want to handle the window painting in your case. Window events like window refresh or minimize/maximize will require repainting of your window or a region of the window.
Happy Coding!!
I'm OP...accidentaly ate my cookie.
Studied how windows flip3d and the taskbar manages this a bit closer and they actually repaint the window before they start the animation of the thumb.
Try to minimize a window and then restore it with flip3d, you will see a small blink on the 3d-window before it get restored.
Tried the same thing with my app and it looks alot better, not perfect but acceptable :/

Categories

Resources