Defining the Mouse Cursor

The default mouse cursor is a small white arrow, but you can change the mouse cursor to any 16x16 or 32x32 shape with fg_mouseptr(). You define the mouse cursor in terms of a screen mask and cursor mask that resemble the monochrome bitmap format used by fg_drawmap(). Windows displays the mouse cursor by first logically ANDing the screen contents with the screen mask, and then XORing that result with the cursor mask.

Let's begin by looking at the masks for the default mouse cursor. The size of each mask (and hence the mouse cursor) is 16 pixels wide and 16 pixels high. As mentioned earlier, the default cursor is a small white arrow with a black outline around it. Here are its screen and cursor masks expressed as binary values:

screen mask

cursor mask

cursor appearance

1001111111111111

0000000000000000

.**.............

1000111111111111

0010000000000000

.*x*............

1000011111111111

0011000000000000

.*xx*...........

1000001111111111

0011100000000000

.*xxx*..........

1000000111111111

0011110000000000

.*xxxx*.........

1000000011111111

0011111000000000

.*xxxxx*........

1000000001111111

0011111100000000

.*xxxxxx*.......

1000000000111111

0011111110000000

.*xxxxxxx*......

1000000000011111

0011111111000000

.*xxxxxxxx*.....

1000000000001111

0011111000000000

.*xxxxx*****....

1000000011111111

0011011000000000

.*xx*xx*........

1000100001111111

0010001100000000

.*x*.*xx*.......

1001100001111111

0000001100000000

.**..*xx*.......

1111110000111111

0000000110000000

......*xx*......

1111110000111111

0000000110000000

......*xx*......

1111111000111111

0000000000000000

.......***......

Windows first ANDs the screen mask with the screen contents at the mouse cursor position. This means the screen mask 1 bits leave the corresponding screen pixels intact, while the 0 bits change the pixels to black. Next, Windows XORs the result with the cursor mask. This time the cursor mask 0 bits leave the corresponding pixels unchanged, while the 1 bits change them to white. This produces a mouse cursor as shown above on the right, where a dot (.) represents an unchanged pixel, an asterisk (*) a black pixel, and an x a white pixel. The following table summarizes the cursor appearance for all possible combinations of mask bits.

Screen Mask Bit

Cursor Mask Bit

Resulting Cursor Pixel

0

0

black

0

1

white

1

0

unchanged

1

1

inverted

With an understanding of the way the default mouse cursor works, we're now ready to define our own 16x16 mouse cursors. Shown here are the screen mask, cursor mask, and resulting appearance for a solid plus-shaped cursor. The hexadecimal equivalents of the binary mask values are also given.

-----screen mask----- binary hex

-----cursor mask----- binary hex

cursor appearance

1110000000111111 E03F

0000000000000000 0000

...*******......

1110000000111111 E03F

0000111110000000 0F80

...*xxxxx*......

1110000000111111 E03F

0000111110000000 0F80

...*xxxxx*......

0000000000000111 0007

0000111110000000 0F80

****xxxxx****...

0000000000000111 0007

0111111111110000 7FF0

*xxxxxxxxxxx*...

0000000000000111 0007

0111111111110000 7FF0

*xxxxxxxxxxx*...

0000000000000111 0007

0111111111110000 7FF0

*xxxxxxxxxxx*...

0000000000000111 0007

0111111111110000 7FF0

*xxxxxxxxxxx*...

0000000000000111 0007

0111111111110000 7FF0

*xxxxxxxxxxx*...

0000000000000111 0007

0000111110000000 0F80

****xxxxx****...

1110000000111111 E03F

0000111110000000 0F80

...*xxxxx*......

1110000000111111 E03F

0000111110000000 0F80

...*xxxxx*......

1110000000111111 E03F

0000000000000000 0000

...*******......

1111111111111111 FFFF

0000000000000000 0000

................

1111111111111111 FFFF

0000000000000000 0000

................

1111111111111111 FFFF

0000000000000000 0000

................

If we wanted to make the mouse cursor hollow rather than solid, the masks and resulting cursor appearance would look like this:

-----screen mask-----

binary hex

-----cursor mask-----

binary hex

cursor

appearance

1110000000111111 E03F

0000000000000000 0000

...*******......

1110111110111111 EFBF

0000000000000000 0000

...*.....*......

1110111110111111 EFBF

0000000000000000 0000

...*.....*......

0000111110000111 0F87

0000000000000000 0000

****.....****...

0111111111110111 7FF7

0000000000000000 0000

*...........*...

0111111111110111 7FF7

0000000000000000 0000

*...........*...

0111111111110111 7FF7

0000001000000000 0200

*.....x.....*...

0111111111110111 7FF7

0000000000000000 0000

*...........*...

0111111111110111 7FF7

0000000000000000 0000

*...........*...

0000111110000111 0F87

0000000000000000 0000

****.....****...

1110111110111111 EFBF

0000000000000000 0000

...*.....*......

1110111110111111 EFBF

0000000000000000 0000

...*.....*......

1110000000111111 E03F

0000000000000000 0000

...*******......

1111111111111111 FFFF

0000000000000000 0000

................

1111111111111111 FFFF

0000000000000000 0000

................

1111111111111111 FFFF

0000000000000000 0000

................

Note that the center bit defined in the cursor mask causes the corresponding screen pixel to be inverted.

There is one more item needed to define a mouse cursor completely. That item is the hot spot, or the actual screen position used or reported in response to mouse position requests. For the plus-shaped cursors just constructed, it would make sense to define the hot spot in the center of the plus. The hot spot is specified relative to the upper left corner of the cursor, so its position within the cursor would be (6,6) -- that is, six pixels to the right and six pixels below the upper left corner. You can specify the hot spot offsets using negative values or values above 15 to position it outside the mouse cursor matrix if desired.

The fg_mouseptr() function defines a mouse cursor shape. The first of its three parameters is a 32-element array, passed by reference. The array's first 16 elements contain the screen mask, and its second 16 elements contain the cursor mask. The remaining two parameters respectively specify the horizontal and vertical offsets for the hot spot. For 16x16 mouse cursors, we recommend using the C/C++ or Delphi word data type for the mask array. The fg_mouseptr() function returns a handle to the resulting mouse cursor. Note that fg_mouseptr() does not immediately activate the new cursor shape, but merely defines it. In C/C++ programs, any mouse cursor handles created with fg_mouseptr() should be released with the Windows API function DestroyCursor() in the program's WM_DESTROY message handler.

The fg_mousecur() function activates a mouse cursor shape previously defined with fg_mouseptr(), or with the Windows API function LoadCursor(). Its only parameter is a handle to the mouse cursor shape (which is what fg_mouseptr() and LoadCursor() return). C/C++ programs typically call fg_mousecur() from the WM_SETCURSOR message handler when the mouse cursor enters the client area. C++Builder and Delphi programs should use the form's Cursor property instead of fg_mousecur() to activate a new cursor shape.

<< Prev

Next >>

Contents
Fastgraph Home Page

 

copyright 2001 Ted Gruber Software, Inc.