Tải bản đầy đủ (.pdf) (18 trang)

Visual Basic 2005 Design and Development - Chapter 19 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (448.43 KB, 18 trang )

Part IV
Specific Techniques
In this Part:
Chapter 19 Splash Screens
Chapter 20 Printing
Chapter 21 Threading
Chapter 22 Reflection
Chapter 23 Memory Management
25_053416 pt04.qxd 1/2/07 6:35 PM Page 493
25_053416 pt04.qxd 1/2/07 6:35 PM Page 494
Splash Screens
The first thing a user sees of an application is its splash screen. As the adage says, “You only get
one chance to make a first impression,” so it’s important that your splash screen represent your
application appropriately. Though the user only gets one first impression of your application, the
splash screen appears every time the application starts, so it’s important that it has a positive
impact each time the user sees it.
A typical splash screen displays some basic information about the application such as its name,
version number, and copyright information. Splash screens often provide contact information so
that users can get technical support if necessary.
In addition to giving the user a little information, a splash screen gives the user something to look
at while the application loads. At this point, the application might look for all sorts of resources
such as databases, files, special devices, network connections, remotely mounted drives, Web
Services, and so forth. It can connect to databases and open files, parse XML data, and otherwise
get ready for business. If a program takes several seconds to do all this, then a splash screen shows
the user that something is happening. If it includes a progress bar or status animation, it can let the
user know that the program is working and has not become stuck.
The application can also perform security checks while the splash screen is visible. It can try to
open password-protected databases, check the user’s credentials, and see if it can connect to the
network through the user’s firewall.
In some applications, I have included user name and password text boxes on the splash screen so
that the user can use it to log in. The splash screen’s code then checked a password database to


verify that the user name and password were correct, and to see what kind of user this is (clerk,
supervisor, manager, and so forth). The rest of the application used that information to configure
itself, displaying or hiding menus and buttons as appropriate.
A well-crafted splash screen shows the users that you pay attention to details and makes an appli-
cation look more professional. I usually build a splash screen for a new application as soon as
development starts so that customers viewing prototypes can see it. In one application for the
26_053416 ch19.qxd 1/2/07 6:36 PM Page 495
State of Minnesota, I made a splash screen in the shape of the state’s map. After the initial demonstra-
tion, the first question they asked was, “How did you make that cool splash screen?”
(The second question they asked was, “How long did it take?” They liked the splash screen but didn’t
want to waste money on frills. As you’ll see in this chapter, making a shaped splash screen only takes a
few minutes.)
This chapter explains how to build and use splash screens in Visual Basic. It tells how to add interesting
and unusual features to a splash screen, such as a shaped form, rotated text, and text filled with a color
gradient or pattern. Adding all of these features to every form in a project would probably make the
application appear cluttered and distracting, but in a splash screen, they can make an otherwise utilitar-
ian form more interesting.
Determining Splash Screen Contents
Figure 19-1 shows the splash screen displayed by the ShapedSplashScreen example application. (You
can download this example at
www.vb-helper.com/one_on_one.htm.) The form is shaped to fit an
image on the left and has rounded corners. It displays the application’s title
eJack in outlined text that
is filled with a color gradient shading from red to yellow to green (it looks much better on the screen
than in this book). It displays the program’s version, serial number, and copyright information. It also
displays a progress bar to show the user how far the application has proceeded in loading its data.
Figure 19-1: The
ShapedSplashScreen program displays this splash screen when it
starts.
The image on the left in Figure 19-1 was even generated by Visual Basic, specifically Visual Basic 6

code from my book, Visual Basic Graphics Programming: Hands-On Applications and Advanced Color
Development, Second Edition (Indianapolis: Wiley, 1999).
A program’s About dialog should also display the same information. It should display the program’s
name, version, serial number, and copyright statement. Because the About dialog contains the same
information as the splash screen, it makes sense to use the same form for both.
Figure 19-2 shows the
ShapedSplashScreen program displaying its About dialog. It is similar to the
splash screen except that it doesn’t display a progress bar. It also displays a rotated link to the support
Web site
www.vb-helper.com and an OK button so the user can close it. .
496
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 496
Figure 19-2: The About dialog displays much of the same information as the splash
screen.
A splash screen should not display system information such as memory usage or disk space. To manage
system resources, the user should use the operating system tools, not your application.
When a user needs help with an application, the technical support people usually need to know the pro-
gram’s serial number. These numbers are often quite long (my Visual Basic serial number has 20 digits
plus embedded dashes), so, to make entering the serial number in an email easier, the About dialog dis-
plays it in a read-only text box. That allows the user to select the serial number, press Ctrl+C to copy it to
the clipboard, and then press Ctrl+V to paste it into the email.
Many splash screens and About dialogs also contain hidden surprises, often called Easter Eggs. If you
hover the mouse over a small area on the dot in the title’s exclamation point, the mouse cursor changes
to a crosshair. If you click that spot, the hidden screen shown in Figure 19-3 appears. Often, this kind of
hidden screen displays extra non-critical information such as the names of the developers who worked
on the application.
Figure 19-3: This surprise screen displays animations of an atom and
caffeine molecule.
Some hidden screens are extremely elaborate. Some play music or make the developers’ names appear in

an amusing animation. I’ve even seen some that included complicated games that the user can play.
Whereas splash screens provide important information and feedback while the application is loading,
hidden screens are definitely optional. They’re usually fun and easy to build, however, so developers
can add them in a spare moment without much wasted effort (complicated games notwithstanding).
497
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 497
Displaying Splash Screens
Visual Basic provides a way to automatically display a splash screen, although it’s a little awkward and
not very well-documented.
First, build the form you want to use as a splash screen. Then open Solution Explorer and double-click
the My Project item. On the Application tab, scroll to the bottom and select the form in the “Splash
screen” drop-down, as shown in Figure 19-4.
Figure 19-4: Select the splash screen’s form from the drop-down list.
At this point, Visual Basic will automatically display the splash screen when the application starts. It dis-
plays the form until the program’s main form has finished its startup sequence, or until a certain mini-
mum amount of time has passed, whichever comes second. Unfortunately, changing the minimum
amount of time or adding data loading code requires some extra work on your part.
To do either of these tasks, open Solution Explorer and double-click the My Project entry. On the
Application tab, click the View Application Events button at the bottom, as shown in Figure 19-4.
To change the minimum amount of time the splash screen is displayed, add the following code to the
MyApplication class to override the class’s OnInitialize method. This code sets the application’s
MinimumSplashScreenDisplayTime property to 5 seconds (5,000 milliseconds) rather than its default
value of 3 seconds. It then calls the base class’s
OnInitialize method so that the application can
resume its startup procedure as normal.
‘ Override OnInitialize to set the splash screen’s minimum display time.
Protected Overrides Function OnInitialize(ByVal commandLineArgs As _
498
Part IV: Specific Techniques

26_053416 ch19.qxd 1/2/07 6:36 PM Page 498
System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean
‘ Display the splash screen for at least 3 seconds.
Me.MinimumSplashScreenDisplayTime = 3000
‘ Continue initialization as usual.
Return MyBase.OnInitialize(commandLineArgs)
End Function
The minimum amount of time that a splash screen should be visible is a matter of preference, but 2 or 3
seconds seems to work best. If the form vanishes after less than 2 seconds, the user doesn’t really have a
chance to see it. If the form sticks around for more than 5 seconds, it violates the “5-second rule” that
says an interactive application should respond within 5 seconds whenever possible.
Visual Basic displays the splash screen for a minimum amount of time, or until the main form finishes its
startup sequence. To get the most benefit from the splash screen, you should make the application load
data, connect to databases, use Web Services to check for updates, and perform other lengthy startup
actions during this time.
To perform actions while the form is starting up, open the application events module as you would to
set the
MinimumSplashScreenDisplayTime property. Open the code editor’s left drop-down and
select “(MyApplication Events)”. Then, in the right drop-down, select the
Startup event. Enter your ini-
tialization code in the
MyApplication_Startup event handler.
The following code shows a dummy
Startup event handler. It gets a reference to the application’s
splash screen form so that it can send status information to the form’s progress bar (this is described fur-
ther later in this chapter). It then uses some loops to waste some time before exiting. In a real applica-
tion, you would load data, connect to databases, and perform other time-consuming setup chores
instead of just waiting for a few seconds.
‘ Prepare the application to run:
‘ Connect to databases, load data, etc.

Private Sub MyApplication_Startup(ByVal sender As Object, _
ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) _
Handles Me.Startup
Dim splash_screen As frmSplash
splash_screen = DirectCast(My.Application.SplashScreen, frmSplash)
‘ Wait one second three times.
For progress As Integer = 0 To 100 Step 10
‘ Update the progress display.
splash_screen.Progress = progress
‘ Wait a little while.
Dim stop_time As Date = Now.AddSeconds(0.25)
Do While Now < stop_time
Application.DoEvents()
Loop
Next progress
End Sub
499
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 499
Displaying About Dialogs
Using a splash screen as an About dialog is easy. An About dialog displays most of the same information
as a splash screen. In this example, the differences are that the About dialog does the following:
❑ Displays an OK button
❑ Displays a link to a support Web site
❑ Provides the hidden link to the surprise screen
❑ Does not display a progress bar
To make displaying the splash screen’s form as an About dialog easy, the form provides the
ShowAbout
method shown in the following code. This code makes the OK button, surprise label, and Web site label
visible. It hides the progress bar, and calls the form’s

ShowDialog method to display the form modally.
‘ Display as an About dialog.
Public Sub ShowAbout(ByVal owner As IWin32Window)
btnOk.Visible = True
lblSurprise.Visible = True
pbarLoad.Visible = False
lblUrl.Visible = True
Me.ShowDialog(owner)
End Sub
The main program uses the following code to display the About dialog when the user selects the Help
menu’s About command:
‘ Display the About dialog.
Private Sub mnuHelpAbout_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuHelpAbout.Click
Dim frm As New frmSplash
frm.ShowAbout(Me)
End Sub
Providing Feedback
As the main form works through its startup chores, it provides feedback so that the splash screen can
update its progress bar. Unfortunately, the main form’s startup code and the splash screen’s user inter-
face run in separate threads. Code can only set a control’s property if it is running in the thread that cre-
ated the control, so the main startup code cannot simply set the
Value property for the splash screen’s
ProgressBar control. Instead, the startup code sets the splash screen’s Progress property as shown in
the section “Displaying Splash Screens” earlier in this chapter. The splash screen then updates its own
ProgressBar control.
The following code shows how the splash screen handles its
Progress property:
‘ Set the progress.
Public Delegate Sub ShowProgressDelegate(ByVal progress As Integer)

Public Sub ShowProgress(ByVal progress As Integer)
500
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 500
pbarLoad.Value = progress
End Sub
‘ Get or set the progress indicator.
Public Property Progress() As Integer
Get
Return pbarLoad.Value
End Get
Set(ByVal value As Integer)
If Me.InvokeRequired Then
Dim show_progress_delegate As ShowProgressDelegate
show_progress_delegate = AddressOf ShowProgress
Me.Invoke(show_progress_delegate, New Object() {value})
Else
ShowProgress(value)
End If
End Set
End Property
The code starts by defining a delegate named ShowProgressDelegate to represent a subroutine that
takes an integer parameter. It also defines a simple
ShowProgress subroutine that sets the pbarLoad
progress bar’s Value property to the routine’s integer parameter.
The form then defines the
Progress property that the startup code sets to provide feedback. The Get
procedure simply returns the ProgressBar’s Value property. The Set procedure calls Me.Invoke
Required
to see if the current code is running on a different thread than the form’s user interface thread.

Me.InvokeRequired returns True if the code is running in a different thread than the form’s controls
and, therefore, cannot set the control’s
Value property directly.
If
Me.InvokeRequired returns True, the code makes a ShowProgressDelegate, sets it equal to the
form’s
ShowProgress method, and uses the Invoke method to run that method, passing it the new
value that the
Progress property should have. This starts a call to ShowProgress on the form’s user
interface thread, and that routine can set the
ProgressBar control’s Value property directly.
If
Me.InvokeRequired returns False, code setting the form’s Progress property is running in the user
interface thread, so the code can manipulate the
ProgressBar control directly. In that case, the code
simply calls the
ShowProgress method itself.
Calling across to the form’s user interface thread is a bit awkward, but at least the details are encapsu-
lated in the form, so the main program’s call is straightforward. That code simply sets the form’s
Progress property and the splash screen form handles the rest.
Controlling Item Placement
The splash screen form used by this program draws several items in code. It uses code to shape the
form, draw the application’s title (
eJack!), and display rotated text.
To make working with these items easier, this example uses objects created at design time to determine the
size and placement of the items. For example, the
Panel control panTextArea determines the location of
the rounded rectangle on the right in Figures 19-1 and 19-2. Similarly the
lblTitle and lblUrl Label
controls determine where the program’s title and Web link go.

501
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 501
Not only do these controls determine the items’ placement, but they also give the items’ colors and fonts.
To change the items’ positions, size, color, or font, you can change the corresponding properties of the
controls at design time.
The
lblTitle and lblUrl controls sit on top of the panTextArea control. When you work with the
controls in the form designer, the designer tends to place the
Labels inside the Panel control. That
makes their X and Y position properties relative to the
Panel control’s origin. However, the routines that
draw these items on the form work relative to the form’s origin, not the
Panel’s origin.
To make working with these controls easier, the program uses the following code to move the controls
outside of the
Panel control. The code first makes an array containing the controls that are inside the
Panel control, and then loops through those controls. It changes each control’s parent to the form, and
moves the control to account for the offset provided by the
Panel. That puts the controls in their original
positions, but contained inside the form and not the
Panel.
‘ Move controls out of panTextArea.
Dim ctls(panTextArea.Controls.Count - 1) As Control
panTextArea.Controls.CopyTo(ctls, 0)
For Each ctl As Control In ctls
ctl.Parent = Me
ctl.Left += panTextArea.Left
ctl.Top += panTextArea.Top
Next ctl

Now the program can use these controls to position screen elements.
Shaping Forms
Making a shaped form in Visual Basic doesn’t take many steps, but it is rather confusing.
Forms have a property
TransparencyKey that tells Visual Basic what color to use to make parts of the
form transparent. In theory, if a pixel’s background color has this value, then Visual Basic does not draw
that part of the form and lets whatever lies below the form show through. In practice, things are more
confusing.
To make any of the form transparent, first set the form’s
TransparencyKey and BackColor properties
to the same color. If you run the program now, Visual Basic will not draw the form’s client area.
To make parts of the form visible again, make a
Bitmap that contains the picture you want to display.
Call the
Bitmap’s MakeTransparent method to make pixels of a certain color transparent.
Now set the form’s
BackgroundImage property to the Bitmap. The form will be transparent in the
places where the
Bitmap’s pixels are transparent.
The following code shows the pieces of the splash screen’s
Load event handler that shape the form:
‘ Prepare the splash screen.
Private Sub frmSplash_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
‘ Shape the form.
502
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 502
‘ Make a bitmap for our form image.
Dim bm As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)

Dim gr As Graphics = Graphics.FromImage(bm)
‘ Draw smooth curves.
gr.SmoothingMode = SmoothingMode.AntiAlias
‘ Make a rounded rectangle for the text area.
Using rect_path As GraphicsPath = _
RoundedRectanglePath(panTextArea.Bounds(), 30, 30)
‘ Draw the text area.
Using br As New SolidBrush(panTextArea.BackColor)
gr.FillPath(br, rect_path)
End Using
Using thick_pen As New Pen(Color.DarkBlue, 3)
gr.DrawPath(thick_pen, rect_path)
End Using
End Using
‘ Make a Bitmap containing the Jack image.
Dim jack_bm As New Bitmap(My.Resources.Jack)
jack_bm.MakeTransparent(bm.GetPixel(0, 0))
‘ Draw the Jack image onto the form’s Bitmap.
gr.DrawImage(jack_bm, jack_bm.GetBounds(GraphicsUnit.Pixel))

‘ Make black areas transparent.
Me.BackColor = Color.Black
Me.TransparencyKey = Me.BackColor
‘ Use the result for the form’s background image.
Me.BackgroundImage = bm

End Sub
The code starts by creating a Bitmap to fit the splash screen form. It then makes a Graphics object to
draw on the
Bitmap, and sets the object’s SmoothingMode property to AntiAlias to give drawn shapes

smooth edges.
The code then uses a
GraphicsPath object that it gets from the RoundedRectanglePath method described
shortly. It uses the
panTextArea Panel control to determine the size and position of the rounded rectangle.
In Figures 19-1 and 19-2, the rounded rectangle is the area on the right containing the text.
The program fills the rounded rectangle with the
Panel’s background color, and then outlines it in dark
blue.
Next, the code loads the
jack bitmap from the program’s resources and calls its MakeTransparent
method to make pixels with the same color as the one in its upper-left corner transparent. It then uses
the
Graphics object’s DrawImage method to copy the jack image onto the Bitmap.
The code sets the form’s
BackColor and TransparencyKey properties to black and sets the form’s
background image to the
Bitmap. The result is a form shaped to include the rounded rectangle and the
jack image on the left.
503
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 503
The RoundedRectanglePath function shown in the following code makes a GraphicsPath represent-
ing a rounded rectangle. This code makes a
GraphicsPath, and adds arcs and line segments to make
the rounded rectangle:
‘ Return a GraphicsPath object representing a rounded rectangle.
Public Function RoundedRectanglePath(ByVal x As Integer, ByVal y As Integer, _
ByVal wid As Integer, ByVal hgt As Integer, _
ByVal x_radius As Integer, ByVal y_radius As Integer) As GraphicsPath

Dim graphics_path As New GraphicsPath
graphics_path.AddArc(x, y, x_radius * 2, y_radius * 2, 180, 90)
graphics_path.AddLine(x + x_radius, y, x + wid - x_radius, y)
graphics_path.AddArc(x + wid - x_radius * 2, y, x_radius * 2, _
y_radius * 2, -90, 90)
graphics_path.AddLine(x + wid, y + y_radius, x + wid, y + hgt - y_radius)
graphics_path.AddArc(x + wid - x_radius * 2, y + hgt - y_radius * 2, _
x_radius * 2, y_radius * 2, 0, 90)
graphics_path.AddLine(x + wid - x_radius, y + hgt, x + x_radius, y + hgt)
graphics_path.AddArc(x, y + hgt - y_radius * 2, x_radius * 2, y_radius * 2, _
90, 90)
graphics_path.AddLine(x, y + hgt - y_radius, x, y + y_radius)
Return graphics_path
End Function
Public Function RoundedRectanglePath(ByVal rect As Rectangle, _
ByVal x_radius As Integer, ByVal y_radius As Integer) As GraphicsPath
Return RoundedRectanglePath(rect.X, rect.Y, rect.Width, rect.Height, _
x_radius, y_radius)
End Function
The second overloaded version (the one used by the form’s shaping code) takes a Rectangle and the
radii that it should use for the corner curves as parameters. It translates these values into the parameters
needed by the first version of
RoundedRectanglePath and calls that version.
Filling Text
The following code shows how the splash screen draws filled text. It begins by creating a new
GraphicsPath object.
‘ Draw “Jack!”
Using jack_path As New GraphicsPath()
‘ Make a path for the text.
Using string_format As New StringFormat

jack_path.AddString( _
lblTitle.Text, _
lblTitle.Font.FontFamily, _
lblTitle.Font.Style, _
lblTitle.Font.Size, _
lblTitle.Bounds(), _
string_format)
End Using
‘ Fill the text with a gradient.
504
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 504
Using jack_br As New LinearGradientBrush( _
jack_path.GetBounds(), Color.Red, Color.Lime, LinearGradientMode.Horizontal)
Dim color_blend As New ColorBlend()
color_blend.Colors = New Color() {Color.Red, Color.Yellow, Color.Lime}
color_blend.Positions = New Single() {0.0, 0.5, 1.0}
jack_br.InterpolationColors = color_blend
gr.FillPath(jack_br, jack_path)
End Using
Using jack_pen As New Pen(Color.DarkBlue, 2)
gr.DrawPath(jack_pen, jack_path)
End Using
End Using
The code uses the GraphicsPath object’s AddString to add a string to the path. It passes information
taken from the
lblTitle label control to the AddString method. This lets you easily move, resize, and
change the font for the text without modifying the code.
Next, the program makes a
LinearGradientBrush that shades horizontally from red to lime across the

width of the text. The code defines a color blend for the brush that shades from red to yellow to lime,
and then uses the
Graphics object’s FillPath method to fill the text with this brush.
You could use any other brush to fill the text. For example, you could fill the text with a background
color to make it hollow, or you could use a
TextureBrush to fill the text with an image.
After it fills the text, the code uses the
Graphics object’s DrawPath method to outline the text in dark
blue.
Rotating Text
When the form displays as an About dialog, it draws the program’s support Web site www.vb-
helper.com
on the right in a rotated font. The following code shows how the program draws this text:
‘ Draw the URL rotated over lblUrl.
If lblUrl.Visible Then
Const URL_TEXT As String = “www.vb-helper.com”
gr.RotateTransform(90, MatrixOrder.Append)
Dim url_size As SizeF = gr.MeasureString(URL_TEXT, lblUrl.Font, 1000)
gr.TranslateTransform(lblUrl.Left + url_size.Height, lblUrl.Top, _
MatrixOrder.Append)
gr.DrawString(URL_TEXT, lblUrl.Font, Brushes.Blue, 0, 0)
‘ Move lblUrl under the text so we can catch its Click event.
lblUrl.Width = CInt(url_size.Height)
lblUrl.Height = CInt(url_size.Width)
lblUrl.Text = “”
End If
The Graphics object provides several methods for translating, scaling, and rotating its output. The code
starts by adding a rotation transformation to make the
Graphics object rotate its output 90 degrees.
505

Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 505
Next, the code measures the string it will display. It adds a translation to make the Graphics object
move text drawn at the origin onto the
lblUrl Label control. Notice that the code adds the text’s height
to the horizontal translation. After the text is rotated, its drawing origin is in the upper-right corner of
where the text is drawn. To make the text lie above the
lblUrl control, the code must move it this extra
distance to the right, as shown in Figure 19-5.
Figure 19-5: Text rotated 90 degrees must be translated an extra distance to make it line
up over the
lblUrl control.
You can use similar techniques to display text rotated at other angles, although exactly positioning the
text can be even trickier than it is for text rotated 90 degrees.
The program clears the
lblUrl control’s text, so it is not seen. But the control is still present, so it can
display a “hand” cursor and the user can click it. The following code shows how the program displays
the VB Helper Web site when the user clicks the control. When the code uses
System.Diagnostics
.Process
to “Start” the URL, the system opens the Web site in its default browser.
‘ Open the VB Helper Web site.
Private Sub lblUrl_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles lblUrl.Click
System.Diagnostics.Process.Start(“”)
End Sub
Displaying Hidden Screens
The splash screen contains a tiny Label control named lblSurprise. The control’s Text property is set
to an empty string, so the user cannot see it. The control’s
Cursor property is set to Cross, so it displays

a crosshair cursor when the user positions the mouse over it.
When the user clicks the
lblSurprise control, the following event handler displays the surprise screen
modally:
‘ Display a surprise form.
Private Sub lblSurprise_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles lblSurprise.Click
Text origin
Some Text
Label origin
Label
Transformed text origin
506
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 506
Dim frm As New frmSurprise
frm.ShowDialog(Me)
End Sub
The surprise form is mostly straightforward. It displays some text and an OK button that unloads the
form. A
PictureBox control in the lower right displays an animated GIF file showing a rotating caffeine
molecule. The
PictureBox animates the GIF automatically, so you don’t need to do anything except set
the control’s
Image property to the GIF file.
The only interesting code in the surprise form draws the animated atom in the lower left. The form con-
tains a
Timer control that fires its Timer event every one-tenth of a second. The following code shows
how the event handler works. When the
Timer event occurs, the code invalidates the picAtom

PictureBox
to force the control to repaint itself.
Private Sub tmrAtom_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles tmrAtom.Tick
picAtom.Invalidate()
End Sub
Private Sub picAtom_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles picAtom.Paint
Const DTHETA As Double = Math.PI / 5
Static theta As Double = 0
e.Graphics.Clear(picAtom.BackColor)
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
theta += DTHETA
Const E_RADIUS As Integer = 3
Dim cx As Integer = picAtom.ClientSize.Width \ 2
Dim cy As Integer = picAtom.ClientSize.Height \ 2
Dim rx As Integer = CInt(picAtom.ClientSize.Width * 0.45)
Dim ry As Integer = CInt(picAtom.ClientSize.Height * 0.15)
Dim rect As New Rectangle(-rx, -ry, 2 * rx, 2 * ry)
Dim x, y As Double
e.Graphics.RotateTransform(60, Drawing2D.MatrixOrder.Append)
e.Graphics.TranslateTransform(cx, cy, Drawing2D.MatrixOrder.Append)
e.Graphics.DrawEllipse(Pens.Red, rect)
x = rx * Cos(theta)
y = ry * Sin(theta)
e.Graphics.FillEllipse(Brushes.Red, _
CInt(x - E_RADIUS), CInt(y - E_RADIUS), _
2 * E_RADIUS, 2 * E_RADIUS)
e.Graphics.ResetTransform()
e.Graphics.RotateTransform(-60, Drawing2D.MatrixOrder.Append)

e.Graphics.TranslateTransform(cx, cy, Drawing2D.MatrixOrder.Append)
e.Graphics.DrawEllipse(Pens.Red, rect)
x = rx * Cos(-theta * 0.9)
y = ry * Sin(-theta * 0.9)
e.Graphics.FillEllipse(Brushes.Green, _
CInt(x - E_RADIUS), CInt(y - E_RADIUS), _
2 * E_RADIUS, 2 * E_RADIUS)
e.Graphics.ResetTransform()
507
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 507
e.Graphics.TranslateTransform(cx, cy, Drawing2D.MatrixOrder.Append)
e.Graphics.DrawEllipse(Pens.Red, rect)
x = rx * Cos(theta * 0.8)
y = ry * Sin(theta * 0.8)
e.Graphics.FillEllipse(Brushes.Blue, _
CInt(x - E_RADIUS), CInt(y - E_RADIUS), _
2 * E_RADIUS, 2 * E_RADIUS)
e.Graphics.ResetTransform()
Const N_RADIUS As Integer = 4
e.Graphics.FillEllipse(Brushes.Black, _
cx - N_RADIUS, cy - N_RADIUS, _
2 * N_RADIUS, 2 * N_RADIUS)
End Sub
The control’s Paint event handler clears the PictureBox and sets the Graphics object’s
SmoothingMode property to draw a smooth picture.
The code then calculates parameters to draw an ellipse centered at the origin. It uses the
Graphics
object’s RotateTransform and TranslateTransform methods to draw the ellipse rotated 60 degrees
and centered in the

PictureBox. It then uses some trigonometry to figure out where to draw an electron
on the ellipse. The program uses a static variable to keep track of the electron’s angle around the ellipse
so that it can move the electron to a new position next time the control repaints.
Next, the program resets the
Graphics object’s transformation and repeats the same steps to draw a
new ellipse and electron rotated –60 degrees. It multiplies the angle it used to draw the previous electron
by 0.9, so this electron rotates around its ellipse at a slower speed.
The program again resets the
Graphics object’s transformation and repeats the same steps to draw an
ellipse and electron that is not rotated. This time, it multiplies the electron’s angle by 0.8, so this electron
moves even slower than the others.
Finally, the
Paint event handler draws a nucleus in the center of the PictureBox.
Summary
This chapter describes some techniques you can use to make interesting and informative splash screens.
Though they would be overly flashy in the body of most applications, they can add an extra dimension
of interest to splash screens and About dialogs. These forms are displayed seldom enough that adding
some extra sparkle won’t hurt, and it gives you a chance to show some creativity in even the most staid
application.
One of the purposes of a splash screen is to let the user know that the application is working while it
performs initial setup. The version described in this chapter basically gives the user something interest-
ing to look at while the program gets ready to run. While the splash screen is visible, the program can
connect to databases, verify network connections, check user credentials, and otherwise prepare to work.
508
Part IV: Specific Techniques
26_053416 ch19.qxd 1/2/07 6:36 PM Page 508
Another style of splash screen also lets the user know the program is running while displaying impor-
tant information at the same time. This type of screen displays a message of the day, production note, or
some other piece of information that the user can read while the program initializes. The screen acts
more like an About dialog, and the user closes it after reading the latest message. You can still use the

techniques described in this chapter to give the screen an interesting shape, shaded or rotated text, and a
link to a support Web page, but because the user will spend more time on this type of screen, it should
be a bit more conservative than the splash screen described here.
Visual Studio .NET changed the way you display splash screens. In Visual Basic 6, you needed to dis-
play the splash screen yourself and use a timer to remove it after a certain period of time, or after the
application had finished loading, whichever came second.
Visual Basic .NET also greatly changed the way you send output to the printer. Visual Basic 6 included a
Printer object that had methods that let you draw, print text, start a new page, and perform other
printing operations in a straightforward, procedural way. Visual Basic .NET uses an event-driven
approach where your code must respond to requests to generate output. Chapter 20, “Printing,”
describes Visual Basic .NET’s event-driven printing model, and shows how you can build your own
more procedural printing system.
509
Chapter 19: Splash Screens
26_053416 ch19.qxd 1/2/07 6:36 PM Page 509
26_053416 ch19.qxd 1/2/07 6:36 PM Page 510

×