Watch out for "Power Toys", sometimes you get more than you bargained for.

Okay, so I was checking out the VB PowerToys, and I have to say they are kind of nice. I can always appreciate a free download especially if it saves me some time. However, you don't reinvent the wheel when creating a new component and then append the word Power to it. The VB Power Toys are relying on a partial combination of Windows Forms, Windows Forms hacks, and P/Invoke calls, but even with a license to use such features they only use them in a half-arsed manner.

Currently, for the animation, the developer uses ShowWindow in order to get around the activation issues with Windows Forms, but then turns around and uses custom animation routines. Custom animation routines when working with Forms really suck because they involve a LOT of screen popping as you continuously redraw the form contents. This is not bad if you animate an empty window, called a representative, and then show the actual form with controls at the end. This reduces repainting, so at the very least I would recommend the Power Toys use this method.

Otherwise, take advantage of the system darnit. AnimateWindow, a well documented Win32 API, is capable of doing all of the animation available in the NotificationWindow with a minimum of code. I applaud some of the cool designer features for blends and what not, but not taking advantage of a built-in, and very fast API for animating the window (much faster than custom animation) is just not cool. Anyway, if you want your own “Toast” windows without all of the extra garbage all you really need to do is make a call to AnimateWindow over top of your normal forms. A sample Form that hides then shows using a fade, as well as taking advantage of a Region while doing it, can be found in the following snip:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class AnimateWindowShow : Form {
    [DllImport("user32.dll")]
    static extern bool AnimateWindow(IntPtr hwnd, uint dwTime, uint dwFlags);
   
    public AnimateWindowShow() {
        ShowInTaskbar = false;
        Click += new EventHandler(Form_Click);
    }
   
    private void Form_Click(object sender, EventArgs e) {
        GraphicsPath gp = new GraphicsPath(); gp.AddEllipse(ClientRectangle);
        this.Region = new Region(gp);
   
        AnimateWindow(this.Handle, (uint) 1000, (uint) 0x90000);
       
        DateTime end = DateTime.Now.AddSeconds(3);
        while(end > DateTime.Now) { System.Threading.Thread.Sleep(0); }

        AnimateWindow(this.Handle, (uint) 1000, (uint) 0x80000);
    }
   
    [STAThread]
    private static void Main(string[] args) {
        Application.Run(new AnimateWindowShow());
    }
}

The above isn't complete at all, and isn't meant to be. The point is you don't need a PowerToy for most of this stuff because the functionality is one API call away and not 50+ lines of animation code. In addition to the Show methods in the PowerToy, AnimateWindow actually has many additional settings. Not to mention it handles the whole activation logic with a simple flag that gets Or'ed in with the rest of the flags. Slide, Blend, Roll, swipes from center, horiztonally or vertically. It is a cool API and won't put a large hurting on your system.

Even better is the SystemParametersInfo where you can get information on whether users even have animations enabled by default. By doing some checks with this method you can get loads of information on tuning your UI to make sure it works best with the user's system.

Don't get me wrong, some of the PowerToys are excellent and cool. Just be aware of what you are getting and the alternatives. Maybe the developer didn't know about the AnimateWindow API, or possibly there were some issues I'm overlooking. I'll be interested in hearing about it. There are some notes on the API about when certain flags are supported, but it returns a bool true/false and lets you know if it succeeds, so you can check that and return appropriate error information.

Published Wednesday, July 21, 2004 2:45 AM by Justin Rogers
Filed under: , ,

Comments

Wednesday, July 28, 2004 11:02 AM by Rudi

# re: Watch out for "Power Toys", sometimes you get more than you bargained for.

I guess the reason why they have put in the long hours to get the animations to work is because if you try your sample, it works.

If you add a button, it still works, if you add a Label, I get this exception:
Unhandled Exception: System.ArgumentException: hdc
at System.Windows.Forms.DibGraphicsBufferManager.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits)
at System.Windows.Forms.DibGraphicsBufferManager.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height)
at System.Windows.Forms.DibGraphicsBufferManager.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetBounds)
at System.Windows.Forms.DibGraphicsBufferManager.AllocBuffer(IntPtr target, Rectangle targetBounds)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Label.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.Label.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Label.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Form.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at AnimateWindow.Toast.AnimateWindow(IntPtr hwnd, UInt32 dwTime, UInt32 dwFlags)
at AnimateWindow.Toast.Show() in d:\my documents\visual studio projects\animatewindow\animatewindow\toast.cs:line 72
at AnimateWindow.Form1.button1_Click(Object sender, EventArgs e) in d:\my documents\visual studio projects\animatewindow\animatewindow\form1.cs:line 87
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
at System.Windows.Forms.Control.WmCommand(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
The program '[2284] AnimateWindow.exe' has exited with code 0 (0x0).
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.ComponentManager.System.Windows.Forms.UnsafeNativeMethods+IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)

And I guess they did not have the option of fixing that...

Leave a Comment

(required) 
(required) 
(optional)
(required)