Home > Articles > Programming > User Interface (UI)

Introduce Animated Cursors to Java GUIs, Part 2

Jeff Friesen
  • PrintPrint
  • Share ThisShare This
  • DiscussDiscuss
Close WindowJeff Friesen

Jeff Friesen

Learn more…

Using Transitions to Simplify JavaFX Animations
Sep 9, 2009
Styling Swing Components with Java CSS
Aug 28, 2009
Show Me the Movie with DirectShow
Apr 28, 2009
Playing Media with Java Media Components
Feb 27, 2009
Creating Java User Interfaces with Project Scene Graph
Feb 10, 2009
Blending Images in Java
Sep 12, 2008
Introduce Animated Cursors to Java GUIs, Part 3
Apr 30, 2008
Introduce Animated Cursors to Java GUIs, Part 2
Apr 18, 2008
Introduce Animated Cursors to Java GUIs, Part 1
Apr 11, 2008
Enhance Java GUIs with Windows Icons
Apr 4, 2008
Taming Mustang, Part 2: Scripting API Tour
Nov 2, 2007
Visit Java's Relatives: Jython and Groovy
May 4, 2007
Generics 101: Mastering the Fundamentals
Mar 23, 2007
Taming Mustang, Part 3: A New Script Engine
Mar 2, 2007
Taming Mustang, Part 1: Collections API
Feb 16, 2007
PCX Meets Image I/O: Creating an Image-Reading Java Plug-in
Dec 29, 2006
Mustang (Java SE 6) Gallops into Town
Oct 20, 2006
GridBagLayout Versus FormLayout
Oct 6, 2006
Laying Out Realistic GUIs the GridBagLayout Way
Sep 29, 2006
Harness the Power of Java's GridBagLayout
Sep 22, 2006
Tools of the Trade: SwingX Meets Swing with New and Extended Components
Aug 4, 2006
Have Fun with the Custom Screensavers Library
Mar 10, 2006
Build Screensavers with a Custom Screensavers Library in Borland C++
Feb 24, 2006
Tools of the Trade: Flash meets Java with Transform SWF and JFlashPlayer
Feb 17, 2006
Tools of the Trade, Part 3: Using the JGoodies Animation Library
Dec 22, 2005
Tools of the Trade, Part 2: Building Graphs with JGraph
Dec 9, 2005
Tools of the Trade, Part 1: Creating PDF documents with iText
Nov 4, 2005
From Literals to Expressions in Java
Aug 16, 2002
Build Your Own Java-Based Email Programs
May 10, 2002
Exploring Java's Network API: URIs and URLs
May 1, 2002
Exploring Java's Network API: Sockets
Apr 19, 2002
Basic Thread Operations in Java
Mar 22, 2002
Working with Streams in Java
Mar 22, 2002
Advanced Tips for More Powerful Tables
Nov 20, 2001
Exploring Swing's Table Component
Nov 20, 2001
Simple Tips for More Powerful Tables
Nov 20, 2001
A Handful of Tips for Swing Programs
Apr 13, 2001
A Trio of Tips for AWT Programs
Apr 13, 2001
Automating Programs with Robots
Apr 13, 2001
Build Your Own Media Player
Apr 13, 2001
Drawing Cubic Curves
Apr 13, 2001
Scaling Images
Apr 13, 2001
Using the Swing API Timers
Apr 13, 2001

Sorry, this author hasn't posted any blogs.

Jeff Friesen continues his three-part series on a Java-based animated cursor library that extracts cursor images and other data from Windows-based .ani files. His second implementation of the library overcomes various problems with the implementation in part 1 of this series, including that version’s inability to work with certain kinds of .ani files. Prior to presenting this implementation, Jeff tours the Resource Interchange File Format and the RIFF-based ANI format.

Most of Microsoft’s various Windows operating systems support animated cursors via internal infrastructure and .ani files—each .ani file stores an animated cursor’s images and animation data. These .ani-based animated cursors can be introduced easily into Java GUIs by using my animated cursor library. This library’s three implementations are the subject of this three-part series.

Part 1 introduced a Swing application for demonstrating all three implementations. This application’s source code revealed how easy it is to use the library. Part 1 also explored the basic implementation in terms of its AniCursor and BadAniException classes, which are located in the library’s ca.mb.javajeff.anicursor package.

This article, part 2 of the series, explores an improved implementation that also consists of a ca.mb.javajeff.anicursor package containing AniCursor and BadAniException classes. This second implementation fixes most of the problems with the basic implementation—I’ll point out these problems as we progress through this article.

Before revealing the second implementation, I’ll introduce you to the Resource Interchange File Format (RIFF), explore the ca.mb.javajeff.riff package, and describe the RIFF-based ANI format that defines the structure of .ani files. Collectively, this material will help you make sense of this latest library implementation.

The Resource Interchange File Format (RIFF)

Created by Microsoft and IBM, and debuting as part of the Microsoft Windows 3.0 multimedia extensions, the Resource Interchange File Format (RIFF) specifies a structured format for storing multimedia data in files. For example, digitized sounds are stored in .wav files, movies are stored in .avi files, and animated cursors are stored in .ani files.

RIFF Internals

The foundation of a RIFF file is the chunk data structure. A chunk contains a header consisting of identifier and size fields. The chunk also contains a data area field. The layout of these fields is conveniently expressed via the following C language code fragment:

typedef unsigned long DWORD;

typedef unsigned char BYTE;

typedef DWORD FOURCC;  // four-character code

typedef struct
{
  // The ckID and ckSize fields constitute the chunk’s header.

  FOURCC ckID;     // chunk ID
  DWORD ckSize;     // chunk size
  BYTE ckData [ckSize]; // chunk data area (not legal C code, but illustrative)
}
CHUNK;

The ckID field contains four ASCII characters that identify the kind of data contained in the chunk’s data area. For example, the characters RIFF identify the chunk containing RIFF data. If a chunk ID is smaller than four characters, it’s padded on the right with space characters.

The ckSize field contains the length of the data stored in the ckData field, not including any padding byte added to the data. Furthermore, the sizes of the ckID and ckSize fields are not included in ckSize’s value.

The ckData field contains data that’s word-aligned within the RIFF file. If the data length is odd, an extra zero byte is appended to the data. The ckSize value doesn’t include this byte in its tally.

A RIFF file begins with a top-level chunk whose chunk ID is RIFF or RIFX. RIFF is specified if the file’s data is stored in the more common little-endian (low byte first) order; RIFX is specified if the file’s data is stored in big-endian (high byte first) order.

The top-level chunk’s data area begins with a form type field, which identifies the type of data in the file and its format. Examples of form type content include AVI and WAVE. Figure 1 illustrates the RIFF chunk’s organization.

Figure 1

Figure 1 The RIFF chunk’s data area is divided into a form type field and subchunks.

Figure 1 shows that the RIFF (and also RIFX) chunk’s data area (following the form type field) is divided into a sequence of subchunks that specify the actual data. One of these subchunks, which is commonly found in different kinds of RIFF files, is LIST.

Unlike other kinds of subchunks, a LIST subchunk contains a sequence of subchunks in its data area. This area begins with a list type field instead of a form type field. The list type field identifies the kind of data that LIST’s subchunks provide. Figure 2 shows a LIST subchunk.

Figure 2

Figure 2 The RIFF chunk reveals a single LIST subchunk in its data area.

To reinforce our understanding of RIFF internals, let’s explore the structure of richo.wav, a 2,436-byte RIFF-based WAVE file that stores a digitized richochet sound and is included with this article’s code. This file’s structure is shown in Listing 1.

Listing 1 The structure of richo.wav.

Chunk: RIFF
Chunk size: 2428
{
 Form type: WAVE

 Chunk: fmt
 Chunk size: 16
 {
 }

 Chunk: data
 Chunk size: 2317
 {
 }

 Chunk: LIST
 Chunk size: 66
 {
  List type: INFO

  Chunk: ISFT
  Chunk size: 53
  {
  }
 }
}

The structure begins with a parent RIFF chunk. This chunk’s header reveals the size of the data area (2,428 bytes). If you add this value to the sizes of the header fields, the result equals the file size—this is generally (but not always) true of RIFF files.

This chunk’s data area (between the { and } characters) consists of a form type field followed by a sequence of fmt , data, and LIST subchunks. These subchunks respectively store the digitized sound’s format, the sound’s data values, and metadata describing this WAVE file.

Although a LIST subchunk can contain various subchunks that store different kinds of metadata (a copyright string and a creation date are examples), the structure above reveals a single ISFT subchunk. This subchunk names the software package used to create this file.

  • Share ThisShare This
  • Your Account

Discussions

Make a New Comment

You must log in in order to post a comment.

Related Resources

Danny KalevMinutes from the October 2009 Meeting
By Danny Kalev on November 19, 2009 No Comments

The minutes from the Santa Cruz (October 2009) meeting are available here. Even if you're not a language layer at heart, I encourage you to read them.

Danny KalevA Reader's Opinion on Attributes
By Danny Kalev on October 20, 2009 No Comments

In August I dedicated a series to the debate about C++0x attributes. I believe that it covered the subject in a balanced and detailed way, but I keep getting complaints from C++ users who don't like attributes for various reasons. Here's a recent email I received from a Polish C++ programmer. While it  doesn't represent my opinion about attributes -- I'm rather neutral about this feature and consider it a "solution waiting for a problem" -- but it suggests that attributes are still a highly controversial issue that will haunt C++ for a long time. The email is quoted here with minor edits that and as usual, with all private details removed.

Danny KalevFollowup: The Web 2.0 Guy I Ain't
By Danny Kalev on October 16, 2009 1 Comment

Almost a year ago, I posted here The Web 2.0 Guy I Ain't. People wonder whether I still resist all those Web 2.0 features and technologies at the end of 2009.

See All Related Blogs

Informit Network