Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Generate Cursor from Icon Collapse All
Subject Author Date
Suhai Gyorgy Oct 18, 2006 - 6:10 AM

Dear Support,

In your FormEditor sample, you have a method called GenCursorFromToolboxIcon. From that code I was trying to figure out how you make the resulted cursor, but I didn’t much succeed. Actually I’m trying to make a cursor from those icons as well, but rather the kind that VS 7.1 uses in its dialog editor. That cursor seems to be 24x24 and has a 10x10 cross over its hotspot and the specified icon in bottom right corner and nothing else. I’d like to achive this somehow. Could you please point me to the right direction or provide a code for that?

Thank you,
Chris

Technical Support Oct 20, 2006 - 1:24 PM

We recommend you use 32x32 cursors as it is done in the CFormEditorView::GenCursorFromToolboxIcon() method. This will let you avoid unwanted problems on old Windows OSes. The hotspot position and cross size are controlled by the following local variables in the method mentioned above:

const POINT ptHotspot = { 12, 14 };
static const int nCrossMetric = 8;
These local variables can be moved into method parameters. The generated 32x32 icon can be split into 4 areas (16x16 pixels each). The top-left, top-right and bottom left areas contain the cross and hot spot. The bottom-right area is completely dedicated to the 16x16 icon passed in the method’s parameter.

As you can see the _iiDst.hbmColor and _iiDst.hbmMask bitmaps are created having the size 32x32. But the ::BitBlt() Win32 API is invoked twice in this method and puts the source icon into the bottom-left area only:
    ::BitBlt(
        hIconDC_Dst, 16, 16, 16, 16,
        hIconDC_Src, 0, 0, SRCCOPY
        );
    ::BitBlt(
        hMaskDC_Dst, 16, 16, 16, 16,
        hMaskDC_Src, 0, 0, SRCCOPY
        );
If the icon handle specified in method’s parameter contains a 24x24 icon, then you may need to change the ptHotspot and nCrossMetric values and you should adjust the parameters of ::BitBlt() Win32 API invocations:
    ::BitBlt(
        hIconDC_Dst, 8, 8, 24, 24,
        hIconDC_Src, 0, 0, SRCCOPY
        );
    ::BitBlt(
        hMaskDC_Dst, 8, 8, 24, 24,
        hMaskDC_Src, 0, 0, SRCCOPY
        );

Suhai Gyorgy Oct 20, 2006 - 3:09 PM

Thank you very much, but this much I did understand from the code. My biggest problems with the code are:

- Why changing hotspot position changes width of bottom horizontal and right vertical black lines drawn "behind" icon? When checking CExtCmdIcon::AssignFromHICON code I could see that it calculates size of icon’s "working area" from hotspot position (assuming that hotspot is in the very middle of icon, thus icon size is assumed to be (ptHotspot.x * 2, ptHotspot.y * 2) ) But this time this is not the case (calculated size is 24x28, original size is 16x16).

- Why I can’t see the cross? It is painted with white pen but there’s neither white, nor any kind of cross in the cursor. When I change position of cross, I can see that those pixels where the cross should be are invisible (deleting overlapping pixels of icon). Even if I use black pen to draw the line, black line is only drawn over icon pixels and still invisible any other places.

This might not make any sense if you don’t test the sample with the mentioned changes. In my case I would use 16x16 icon to make 32x32 cursor as you suggested. I guess your intention’s with the sample code were just the kind of cursor I’d like to achieve, but it’s somehow not working right. Could you please check?

Technical Support Oct 22, 2006 - 10:52 AM

We coded a sample project for you. Here is its source and binary code zipped into two files:

test_create_cursor_BIN.zip
test_create_cursor_SRC.zip

The CTestDlg::stat_CreateTestCursor() method seems to be what you are looking for. We have not encountered any problems described in your message when coding this function.

Suhai Gyorgy Oct 24, 2006 - 4:24 AM

The above sample project works great, thank you! And from that I found out what causes those problems I described: In FormEditor sample you use a global CExtCmdIcon object for this cursor. When the cursor is generated, it is assigned with AssignFromHICON method at the end of GenCursorFromToolboxIcon method. And when we want to use the cursor with SetCursor, the cursor is extracted from that global CExtCmdIcon object with ExtractHICON. Either AssignFromHICON, or ExtractHICON makes some changes to the icon which mess things up. Please, confirm.

I made my application work by eliminating CExtCmdIcon and using HCURSOR global variable instead. Thank you!

Technical Support Oct 25, 2006 - 11:09 AM

We confirm that there may be a potential problem with icons extracted from CExtBitmap objects inside a CExtCmdIcon object. The CExtBitmap class can replace the icon functionality only if it has the 32-bit pixel format (with alpha channel). In the sample, we used an icon based on a color bitmap and a mask bitmap. So the sample may be the solution only if you have color/mask-based icons. We can modify the method that creates icons to provide support for alpha channel based icons and cursors but it will work only correctly only on Windows XP or later. Although the alpha blending supported by Prof-UIS on any Windows OS and Windows 2000 also has alpha blending capabilities, 32-bit bitmaps with alpha channels can be used for creating icons only on Windows XP or later.

Suhai Gyorgy Oct 26, 2006 - 6:26 AM

Actually all I’d like to ask from you is to fix the FormEditor sample to have the correct cursor in it. Thank you.

Technical Support Oct 27, 2006 - 6:48 AM

Although it is completely possible to change the type of cursor in the FormEditor sample, we would prefer to leave it intact so that this can work on OS version older than Windows XP. We could do the same in a sample application for you or improve the CExtBitmap class by adding a method that generates cursors from bitmaps of any pixel format. What do you think about this?

Suhai Gyorgy Oct 27, 2006 - 7:13 AM

Sorry, I wasn’t clear. I understand that FormEditor has to work on any OS. I wasn’t even thinking of asking for fix like that. I was thinking more of a kind of correction that I did: eliminating use of CExtCmdIcon and using HICON instead. Right now FormEditor cursor doesn’t look like as you intended it to look like. If you could just check the code for your GenCursorFromToolboxIcon method, you see would see that you are not using CExtBitmap at all, still, if you run the application, you e.g. can’t see any cross in the cursor. It’s because of use of CExtCmdIcon and its AssignFromHICON method. Could you please check that?

Technical Support Oct 30, 2006 - 10:34 AM

We modified the test project. Now it creates the cursor handle using a CExtBitmap object as an optional right bottom part of the cursor. The following method does what you need:

    static HCURSOR stat_CreateTestCursor(
        INT nHotSpotX,
        INT nHotSpotY,
        INT nCursorWidth,
        INT nCursorHeight,
        CExtBitmap * pBmpToDrawAtRightBottom = NULL,
        COLORREF clrTransparent = COLORREF(-1L),
        INT nCrossMetric = 4,
        INT nBoundsMetric = 0
        );
Please note that the pBmpToDrawAtRightBottom bitmap should have a format with 15 bits per pixel or greater. The clrTransparent parameter set to COLORREF(-1L) means then there are no transparent pixels. If the pBmpToDrawAtRightBottom bitmap has a format with 32 bits per pixel, then the pixels with alpha values less or equal to 127 are regarded as transparent.