Creating a Color Cursor from a Bitmap

Figure 1: Transition of a color bitmap to a cursor

Environment: Win32

This article focuses on creating a color cursor from a HBITMAP. First, it explains the steps that Windows performs to display a cursor on the screen and how can we create the necessary information that Windows needs to create our cursor. Then, it explains the steps needed to convert a color HBITMAP to an HCURSOR. Finally, it shows a utility class that converts HBITMAP to HCURSOR.

How Does Windows Display a Cursor?

In Windows, transparency of the cursor is achieved by the use of two masks. One is called the AND mask and the other is called the XOR mask. To display a cursor in the screen, the system first performs a logical AND operation on the screen with the AND mask. In this process, the pixels in the screen corresponding to the 1 bits in the AND mask remain unchanged and the pixels corresponding to the 0 bits in the AND mask become modified. Then, the system will perform a logical XOR operation on the screen with the XOR mask. In this process, the pixels on the screen corresponding to the 0 bits in the XOR mask remain unchanged and the pixels corresponding to the non-0 bits get modified.

Figure 2: A sample color bitmap to be converted as a cursor

Now, let's try to realize the above cursor to its AND/XOR masks so that the system can display the cursor using these masks. First, let us create the AND mask. The above cursor contains a red colored rectangle in the center. So, all the other pixels should be transparent. Assuming that the size of the cursor is 8*8 and the size of the rectangle is 4*4, we shall define the AND mask as shown below.

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

Figure 3: AND mask for the sample color bitmap in Figure 2

In the above AND mask, the bits corresponding to the red rectangle are 0 and the rest of the bits are 1. This is because we need only the red rectangle to be displayed as the cursor and the rest of the area should be transparent. When the system performs a logical AND operation of this mask to the screen, the pixels in the screen corresponding to the red rectangle become modified and the rest remain unchanged.

Now, let us create the XOR mask for our cursor. Because we need to display the red rectangle as a cursor on the screen and the rest as transparent, we need to make the bits in the XOR mask correspond to the red rectangle as Red (RGB (255,0,0)) and the rest as 0.

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 R R R R 0 0
0 0 R R R R 0 0
0 0 R R R R 0 0
0 0 R R R R 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Figure 4: XOR mask for the sample color bitmap in Figure 2

The R in the above XOR mask represents RGB (255,0,0). In other words, it's the red color. When the system performs a logical XOR of this XOR mask to the screen, the R pixels are updated on the screen and the pixels corresponding to the 0 bits remain unchanged.

So, finally, after performing the logical AND of the AND mask, followed by the logical XOR of the XOR mask to the screen, the screen under our cursor region looks like what is shown below.

S S S S S S S S
S S S S S S S S
S S R R R R S S
S S R R R R S S
S S R R R R S S
S S R R R R S S
S S S S S S S S
S S S S S S S S

Figure 5: State of the screen area under the cursor after applying AND and XOR masks

The S represents the original screen pixels and the R represents the red color pixels.

Converting HBITMAP to HCURSOR

Now, let us try to create these AND/XOR masks from a HBITMAP. The following code fragment will do it for you.

void CColorCursor::GetMaskBitmaps(HBITMAP hSourceBitmap,
                                  COLORREF clrTransparent,
                                  HBITMAP &hAndMaskBitmap,
                                  HBITMAP &hXorMaskBitmap)
{
  HDC hDC        = ::GetDC(NULL);
  HDC hMainDC    = ::CreateCompatibleDC(hDC);
  HDC hAndMaskDC = ::CreateCompatibleDC(hDC);
  HDC hXorMaskDC = ::CreateCompatibleDC(hDC);

  //Get the dimensions of the source bitmap
  BITMAP bm;
  ::GetObject(hSourceBitmap,sizeof(BITMAP),&bm);


  hAndMaskBitmap = ::CreateCompatibleBitmap(hDC,bm.bmWidth,
                                            bm.bmHeight);
  hXorMaskBitmap = ::CreateCompatibleBitmap(hDC,bm.bmWidth,
                                            bm.bmHeight);

  //Select the bitmaps to DC
  HBITMAP hOldMainBitmap    = (HBITMAP)::
                              SelectObject(hMainDC,hSourceBitmap);
  HBITMAP hOldAndMaskBitmap = (HBITMAP)::
                              SelectObject(hAndMaskDC,
                                           hAndMaskBitmap);
  HBITMAP hOldXorMaskBitmap = (HBITMAP)::
                              SelectObject(hXorMaskDC,
                                           hXorMaskBitmap);

  //Scan each pixel of the souce bitmap and create the masks
  COLORREF MainBitPixel;
  for(int x=0;x&ltbm.bmWidth;++x)
  {
    for(int y=0;y&ltbm.bmHeight;++y)
    {
      MainBitPixel = ::GetPixel(hMainDC,x,y);
      if(MainBitPixel == clrTransparent)
      {
        ::SetPixel(hAndMaskDC,x,y,RGB(255,255,255));
        ::SetPixel(hXorMaskDC,x,y,RGB(0,0,0));
      }
      else
      {
        ::SetPixel(hAndMaskDC,x,y,RGB(0,0,0));
        ::SetPixel(hXorMaskDC,x,y,MainBitPixel);
      }
    }
  }

  ::SelectObject(hMainDC,hOldMainBitmap);
  ::SelectObject(hAndMaskDC,hOldAndMaskBitmap);
  ::SelectObject(hXorMaskDC,hOldXorMaskBitmap);

  ::DeleteDC(hXorMaskDC);
  ::DeleteDC(hAndMaskDC);
  ::DeleteDC(hMainDC);

  ::ReleaseDC(NULL,hDC);
}

The above code creates two memory DC and two memory bitmaps for the AND/XOR masks. Then, it examines the source bitmap pixels and creates the masks as we have explained in the theory part.

Now, what we need is to use these masks and create a cursor using the well-known CreateIconIndirect() SDK call as shown below.

ICONINFO iconinfo       = {0};
iconinfo.fIcon          = FALSE;
iconinfo.xHotspot       = 0;
iconinfo.yHotspot       = 0;
iconinfo.hbmMask        = hAndMask;
iconinfo.hbmColor       = hXorMask;

HCURSOR hCursor         = ::CreateIconIndirect(&iconinfo);

That's it. We have successfully created a color cursor from a bitmap.

Using the Code

It is always better to create a utility class for doing these things for us. So, I created one called CColorCursor. It has the following interfaces.

static void GetMaskBitmaps(HBITMAP hSourceBitmap,
                           COLORREF clrTransparent,
                           HBITMAP &hAndMaskBitmap,
                           HBITMAP &hXorMaskBitmap);
static HCURSOR CreateCursorFromBitmap(HBITMAP hSourceBitmap,
                                      COLORREF clrTransparent,
                                      DWORD xHotspot,
                                      DWORD yHotspot);

The first interface is called from the second one to create the masks. The first one is also made public because we can use it to get an idea of what is happening inside. I used the first interface in my test application to display the AND/XOR mask as shown in the first figure and the second one to create a cursor directly.

Now, we are approaching towards the end of this article. I will finish it by showing the usage of this utility class.

#include "ColorCursor.h"

....

HBITMAP hSourceBitmap  = c.
HCURSOR hCursor = CColorCursor::
                  CreateCursorFromBitmap(hSourceBitmap,RGB(0,0,0),
                                         0,0);

A Word of Caution

The utility class explained above will try to create the cursor in the same size of the input source bitmap. But in Windows, there are some limitations for the size of the cursor. So, it is always safer to pass bitmaps having a standard size. Otherwise, the result may be unpredictable.

Downloads

Download demo project - 37 Kb
Download source - 2 Kb


Comments

  • Replica Oakley Romeo wholesale online

    Posted by nmbvrwtln on 06/26/2013 06:34pm

    Oakleys Sale ,No-one believes you, no person prepared pay attention to you? But I think that everything may become more perfect, it requires imagination. The exclusive edition of Oakley sunglasses, painter, charity, sports and athletes together to play some favorite Oakley sunglasses sale, would be the world's best light. Oakley Outlet ,If you need to know, not in the slightest while using white ray ban sunglasses, and no compensation due to this task - this really is completely outside attack, and the inclusion of gay and absolute achievement, see more flattering! Oakley could be the mysterious properties of amazing miracle. Another style using this brilliant brand, together with brilliant, fabulous specimens - Oakley's eye-catching, stylish colors. fake Oakley Gascan ,Good design and manufacture of the framework is also good, regardless of under what circumstances, may make people comfortable. After a while, sunglasses, and gradually become present with way of life necessities, and fashion jewelry. You don't have the very best of the most beneficial to find the best. You actually may give the elements of the show too although if you wish to change the look of your respective face, it is easy. Oakley sunglasses, cheap is an excellent brand, it represents a number of art and fashion. You need which you have their own fashion style. Oakley sunglasses, a human eye cannot begin to see the use within order to lose the photovoltaic ultraviolet rays, is higher than the adverse ultraviolet, ultraviolet, so it's very attractive. You need to use in biochemistry Labrador, and also wood processing. They may be doing work in the snow track and field, along with swimming. To put it briefly, you can wear Oakley sunglasses through the mid-summer day, four seasons inside thin air on the beach or boating or skiing. Hardly believe you'll succeed, regardless of if the majority of people feel that your move is tantamount to breaks against it, but who does be aware that your creation will become a mainstay of certain areas. "Wearable electronics" to recover weapons Bluetooth solution, there's no cell cell phone MP3 player collective access and listen to music, within the framework of sunglasses produced extremely plans. Simply because these include adequately designed wonderful gallons addition, another critical point, why Oakley sunglasses are the rights of ladies, in truth, not. As a way to fulfill the different needs of shoppers, either now or even in the near future, Oakley won't stop the pace of progress.

    Reply
  • console pixel size

    Posted by tav on 05/11/2005 05:53pm

    How du i programically, with c++, change the pixel size in my console window(DOS-window)? I want the text to be smaller. If you know how to do this please send me an Email: 020485@stud.hials.no

    Reply
  • Create Bitmap Cursor from Win98

    Posted by Legacy on 02/04/2004 12:00am

    Originally posted by: Phong

    It is incorrect in Win98. Do you know about it? Why?

    • god

      Posted by gangzi on 03/18/2004 09:36pm

      really?

      Reply
    Reply
  • nice and clean

    Posted by Legacy on 10/25/2003 12:00am

    Originally posted by: ME

    .

    Reply
  • nice and clean

    Posted by Legacy on 10/25/2003 12:00am

    Originally posted by: ME

    .

    Reply
  • Nice one

    Posted by Legacy on 10/21/2003 12:00am

    Originally posted by: Sudheer

    This is a very informative and helpful article.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • The operational costs of managing an x86 base are taxing IT budgets, making it difficult to fund and staff new initiatives. Today's IT organization must seek efficiencies in its operations and shift to a more agile infrastructure that's flexible enough to adapt to future changes in the business. Read this Q & A session with Jed Scaramella, research manager for IDC's Enterprise Platforms and Data Center Trends, to learn how the integrated nature of the blade platform delivers critically needed efficiencies …

  • The latest release of SugarCRM's flagship product gives users new tools to build extraordinary customer relationships. Read an in-depth analysis of SugarCRM's enhanced ability to help companies execute their customer-facing initiatives from Ovum, a leading technology research firm.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds