Augmenting standard cursor

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
neilc
Earned a small fee
Earned a small fee
Posts: 11
Joined: Thu Aug 18, 2011 2:00 pm

Augmenting standard cursor

Post by neilc »

Does anyone know if it's possible to augment a wxCursor with an icon? or, get the standard cursor as an image/icon at run-time?

I'd like to use the standard cursor and just add a small icon to it, depending on the mode the user inteface is in. Since a cursor can be created from a wxImage, it looks like it should be possible if I can get the stock cursor at run-time and combine it with my small icon. Does this sound possible?

Thanks
---
Neil
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Augmenting standard cursor

Post by doublemax »

To my best knowledge, there is no wxWidgets-way to get a bitmap of the default cursor.
Use the source, Luke!
neilc
Earned a small fee
Earned a small fee
Posts: 11
Joined: Thu Aug 18, 2011 2:00 pm

Re: Augmenting standard cursor

Post by neilc »

Having searched about this a bit more, I can draw a MSW cursor to a wxMemoryDC using the platform-specific handle, i.e.:

Code: Select all

WXHDC hDC = dc.GetHDC();
WXHCURSOR hCursor = wxSTANDARD_CURSOR->GetHCURSOR();
::DrawIcon(hDC, 0, 0, (HICON)hCursor);
Does anyone know what the equivalent platform-specific method for GTK would be? I see there is

Code: Select all

GdkCursor *GetCursor() const;
in wxCursor - can this be used to draw on a wxDC? Possibly using:

Code: Select all

dc.GetImpl()->GetCairoContext()
I don't really know where to start with the GTK stuff though so any pointers would be very useful!

Cheers
---
Neil
neilc
Earned a small fee
Earned a small fee
Posts: 11
Joined: Thu Aug 18, 2011 2:00 pm

Re: Augmenting standard cursor

Post by neilc »

It seems like on GTK, the following code can be used to draw the cursor:

Code: Select all

GdkCursor * gCursor = wxSTANDARD_CURSOR->GetCursor();
GdkPixbuf * gPixbuf = gdk_cursor_get_image(gCursor);
wxBitmap bmp(gPixbuf);
dc.DrawBitmap(bmp, 0, 0);
(should also be checking for NULL for the pointers)

I'm not too sure about whether the wxBitmap now owns the GdkPixbuf (I think it does) or whether gdk_cursor_get_image is creating new GdkPixbuf data or just returning existing data. This could be important if wxBitmap is releasing the memory. Any thoughts anyone?
neilc
Earned a small fee
Earned a small fee
Posts: 11
Joined: Thu Aug 18, 2011 2:00 pm

Re: Augmenting standard cursor

Post by neilc »

OK, I think I'm close.

Code: Select all

#ifdef __WXGTK__
#include <gtk/gtk.h>
#endif

static wxCursor init_augmented_cursor(void)
{
#if defined(__WXMSW__)

  wxBitmap curBmp;
  WXHCURSOR hCursor = wxSTANDARD_CURSOR->GetHCURSOR();
  wxIcon curIcon;
  curIcon.SetHICON((WXHICON)hCursor);
  curBmp.CopyFromIcon(curIcon);

#elif defined(__WXGTK__)

  GdkCursor * gCursor = wxSTANDARD_CURSOR->GetCursor();
  GdkPixbuf * gPixbuf = gdk_cursor_get_image(gCursor);
  wxBitmap curBmp(gPixbuf);

#else
# error Not defined for this OS
#endif

  // use a wxGraphicsContext to avoid alpha mangling of wxMemoryDC
  wxImage curImg = curBmp.ConvertToImage();
  wxGraphicsContext * gc = wxGraphicsContext::Create(curImg);
  gc->SetBrush(*wxBLUE_BRUSH);
  gc->DrawRectangle(16,16,8,8);
  delete gc; // created wxGraphicsContext must have lifetime less than wxImage
  wxCursor newCursor(curImg);

  return newCursor;
}
The only thing that I'm a bit stuck on is how to get the cursor hot spot from wxSTANDARD_CURSOR and set that on the new cursor. Any suggestions?

My other concerns are with ownership of the hCursor (MSW) and gPixbuf (GTK) and whether the resources would be deleted when they shouldn't or if I haven't handled freeing the resources properly.

Other minor issues:
  • On MSW, some translucent pixels seem to be made fully opaque/transparent giving the cursor a 'hard' outline.
  • On GTK, I found the new cursor to sometimes appear slightly corrupted until I only created the cursor once. Not sure why this was.
Would be great if someone could comment on this.

Cheers
---
Neil
Post Reply