This chapter has a few topics that are slightly more frivolous than in the others. In it, you will learn some things that may be useful, but are more likely to lead to fun and games in some cases.
Solution: Use a background image as a template and set a transparency key. When you do this, you are taking over all responsibility for painting and mouse interaction—the OS’s windowing system can no longer help you with standard tasks, such as moving, maximizing, resizing, and more.
First, you need to create the background image. In this case, it’s a simple black figure with a white background to represent transparency (see Figure 27.1).
To allow the form to be moved, you need to handle the mouse messages yourself. In this case, to keep it simple, a mouse click anywhere on the form is translated into a simulated non-client mouse click to fool the OS into thinking the title bar has been clicked. The interop code is simple:
The form code intercepts the MouseDown event and sends a message to Windows telling it that we’ve clicked on the caption.
Figure 27.2 shows our custom window shape in action, complete with transparency.
The procedure is even simpler in WPF (see Listings 27.1 and 27.2). This code assumes the existence of an image in the project called WindowTemplate.png.
Solution: Use the NotifyIcon
class and attach a menu to it (see Figure 27.3).
This example shows a simple menu attached to an icon (called DemoIcon.ico, which you will need to add to your project’s resources):
Do you really need an icon down there? Many users resent them, so take care. Consider well if you really need it. Perhaps you can create one temporarily to notify the user of events, but then remove it once they’re acknowledged—much like the printer icon. At the very least, provide a way for the user to disable the icon.
You could also consider popping up a temporary window in a corner of the screen, like Outlook does with new mail notifications, or Windows Live Messenger does with various events. After a few seconds, these windows fade away.
Solution: There is nothing special about a screen saver, other than the following conventions:
• A single window that takes over the full screen.
• A configuration dialog box (optional).
• Responds to specific command-line arguments.
• File extension renamed from .exe to .scr.
The following sections detail the parts of a simple WPF screen saver that displays images from your pictures folder.
When the /c
option is passed, you should show an options form. Where you save your options is up to you (the registry, XML file, and so on).
In the case of this demo screen saver, it just shows a placeholder dialog box that says there are no options (see Listings 27.3 and 27.4).
The main screen saver window sizes itself to fit the entire screen, and it cycles through the gathered images (see Listings 27.5 and 27.6).
The application XAML is mostly unremarkable, except for the fact that it does not specify a Window
for the StartupURI
property (see Listing 27.7).
The code-behind file handles the various options and starts up the screen saver in the right mode (see Listing 27.8).
This screen saver handles three parameters:
If anything else is passed (or nothing at all), the screen saver should exit.
The preceding code relies on a little bit of interop to get the bounds of a native window:
Solution: Show a splash screen to display progress as you load the application.
If you want the splash screen to refresh itself correctly, you must run the initialization code on a separate thread so that the UI thread can refresh. Figure 27.4 shows the results with a simple splash screen with a progress bar and status label.
The splash screen can be any form. In this case, it’s a dialog box with no border, an image control that fills the entire form, and a progress and label control.
The application shows the splash form before starting the main form.
WPF actually has splash screen functionality built in, and if all you need is the image to show up while the main window loads, this will do it. To use it, set the build action for an image in your project to “SplashScreen” and the application will automatically show it during startup.
To get more functionality, like shown with the Windows Forms example, it’s a fairly simple translation, as shown in Listing 27.9.
The usage is similar to that in Windows Forms:
Figure 27.5 shows how we can take advantage of WPF’s visual richness to create a neater splash screen than with Windows Forms.
Solution: Use the PlaySound API via P/Invoke.
The first argument to PlaySound
can be a filename, alias, or resource, depending on the flags you pass. The aliases are defined in the registry and the Sounds control panel applet.
The SND_ASYNC
flag tells the system to start playing the sound, but to return immediately, before it’s done playing. This is usually what you want, to avoid hanging the UI while a sound plays.
Solution: Although simple, this solution is a very easy thing to get wrong, algorithmically. For more information, look at Wikipedia’s entries on card-shuffling algorithms.
The accompanying source code wraps this algorithm into a test program that runs it millions of times and tracks the outcomes to see if the results are skewed in any way.