You cans use them but for monochrome cursors, you need to do what wxWidgets attempts to do, i.e., properly blend the two parts of the mask...
Getting windows mousepointer icon = black square Topic is solved
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
-
- I live to help wx-kind
- Posts: 193
- Joined: Fri Jan 30, 2015 1:48 pm
- Location: Bologna, Italy
Re: Getting windows mousepointer icon = black square
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
As shown in my code from my previous post, hbmColor is not used for monochrome cursors, so...
-
- I live to help wx-kind
- Posts: 193
- Joined: Fri Jan 30, 2015 1:48 pm
- Location: Bologna, Italy
Re: Getting windows mousepointer icon = black square
Ok, but:
This is a try to get the color one (i modified your sample):
WHY it does'nt work?
Code: Select all
BITMAP bmMask,bmCurs;
if ( !ii.hbmMask ) {
wxLogMessage("NO Cursor Mask???");
return false;
}else{
if( GetObject(ii.hbmMask, sizeof(bmMask), &bmMask) != sizeof(bmMask) ) {
wxLogError("Could not get BITMAP from the mask.");
return false;
}
wxLogMessage("Cursor Mask: size = %dx%d pixels, depth = %d.",
bmMask.bmWidth, bmMask.bmHeight, bmMask.bmBitsPixel);
}
if ( !ii.hbmColor ) {
wxLogMessage("The cursor is monochrome.");
} else {
wxLogMessage("The cursor is in color.");
if( GetObject(ii.hbmColor, sizeof(bmCurs), &bmCurs) != sizeof(bmCurs) ) {
wxLogError("Could not get BITMAP from the mask.");
return false;
}
wxLogMessage("Cursor Mask: size = %dx%d pixels, depth = %d.",
bmCurs.bmWidth, bmCurs.bmHeight, bmCurs.bmBitsPixel);
if (!bitmap.InitFromHBITMAP(ii.hbmColor, bmCurs.bmWidth, bmCurs.bmHeight, bmCurs.bmBitsPixel) ) {
wxLogError("Could not initialize Bitmap from HBITMAP.");
return false;
}
wxMask bmMask(ii.hbmMask);
bitmap.SetMask(&bmMask);
}
WHY it does'nt work?
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
I think there is a bug, you are always missing "!" when checking the result of ::GetObject(), this function returns zero on failure, non-zero otherwise. I did not read the rest of the code.
-
- I live to help wx-kind
- Posts: 193
- Joined: Fri Jan 30, 2015 1:48 pm
- Location: Bologna, Italy
Re: Getting windows mousepointer icon = black square
I check his return value against sizeof(BITMAP): whatever result (0 or not) not equal to the size of that BITMAP means a failure.
Seems to me more strict than just checking for 0.
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
Sorry for having missing that check, I did not look past the end of the function closing parentheses.
Anyway, the docs say
IIf the function succeeds, and lpvObject is a valid pointer, the return value is the number of bytes stored into the buffer.
I am not sure if this always means sizeof(BITMAP) and would do what the docs say, e.g., check if the result is non-zero. I have no suggestion otherwise and I am going AFK for a bit now.
BTW, IIRC from looking at the wxWidgets code I linked before, wxMask bits are different (inverted?) from Windows mask bits, so you may not be able to use HBITMAP as wxMask directly. But I a may be wrong again.
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
Attempting to fix wxWidgets code, I have realized that perhaps monochrome icons cannot be properly stored in a wxBitmap/wxImage.
wxBitmap stores pixels to be drawn and optionally a transparent mask to indicate which pixels to not draw. Similarly with alpha for wxBitmap/wxImage.
However, a monochrome cursor is supposed to be drawn inverted against the background, so it is always visible, e.g. black on white, white on black etc. Perhaps it could be done drawing such wxBitmap with wxDC::Blit(), using wxXOR as the ROP? But that would be a hassle, to remember which bitmap is monochrome...
So a monochrome icon has to be stored in a wxIcon and drawn with (now buggy) wxDC::DrawIcon(). I know it sounds horrible, but if it comes to worst, and if possible, you could just store the HCURSOR and draw it when needed with something like
What do you think about this, Parduz?
BTW, we also did not speak about animated cursors but let's pretend that is a non-issue.
wxBitmap stores pixels to be drawn and optionally a transparent mask to indicate which pixels to not draw. Similarly with alpha for wxBitmap/wxImage.
However, a monochrome cursor is supposed to be drawn inverted against the background, so it is always visible, e.g. black on white, white on black etc. Perhaps it could be done drawing such wxBitmap with wxDC::Blit(), using wxXOR as the ROP? But that would be a hassle, to remember which bitmap is monochrome...
So a monochrome icon has to be stored in a wxIcon and drawn with (now buggy) wxDC::DrawIcon(). I know it sounds horrible, but if it comes to worst, and if possible, you could just store the HCURSOR and draw it when needed with something like
Code: Select all
::DrawIconEx(dc.GetHDC(), x, y, hCursor0, 0, 0, nullptr, DI_NORMAL);
BTW, we also did not speak about animated cursors but let's pretend that is a non-issue.
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
The issue just has been fixed in wxWidgets master: https://github.com/wxWidgets/wxWidgets/ ... 6347fef477
I would still recommend using wxIcon instead of wxBitmap, for reasons stated in my previous post.
Code: Select all
#include <wx/wx.h>
#include <wx/msw/wrapwin.h>
bool GetFromCurrentCursor(wxIcon& icon, wxBitmap& bitmap)
{
CURSORINFO ci{0};
wxIcon tmpIcon;
wxBitmap tmpBitmap;
ci.cbSize = sizeof(ci);
if ( !::GetCursorInfo(&ci) || (ci.flags & CURSOR_SHOWING) == 0 )
{
wxLogDebug("Could not get cursor info.");
return false;
}
if ( !tmpIcon.CreateFromHICON(WXHICON(ci.hCursor)) )
{
wxLogDebug("Could not create wxIcon from HCURSOR.");
return false;
}
if ( !tmpBitmap.CopyFromIcon(tmpIcon) )
{
wxLogDebug("Could not create wxBitmap from wxIcon.");
return false;
}
icon = tmpIcon;
bitmap = tmpBitmap;
return true;
}
class MyFrame: public wxFrame
{
public:
MyFrame() : wxFrame (nullptr, wxID_ANY, "Test")
{
SetBackgroundColour(*wxRED);
SetClientSize(200, 100);
m_timer.Bind(wxEVT_TIMER,
[this](wxTimerEvent&) { GetFromCurrentCursor(m_icon, m_bitmap); Refresh(); Update(); });
m_timer.Start(100);
Bind(wxEVT_PAINT, &MyFrame::OnPaint, this);
}
private:
wxTimer m_timer;
wxIcon m_icon;
wxBitmap m_bitmap;
void OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
if ( !m_icon.IsOk() || !m_bitmap.IsOk() )
return;
dc.DrawIcon(m_icon, 20, 20);
dc.DrawBitmap(m_bitmap, 100, 20, true);
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
(new MyFrame())->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
You do not have the required permissions to view the files attached to this post.
-
- I live to help wx-kind
- Posts: 193
- Joined: Fri Jan 30, 2015 1:48 pm
- Location: Bologna, Italy
Re: Getting windows mousepointer icon = black square
Great!.PB wrote: ↑Sat Apr 17, 2021 8:13 am The issue just has been fixed in wxWidgets master: https://github.com/wxWidgets/wxWidgets/ ... 6347fef477
But....
should'nt the new code be inside the "if ( hbmp )" branch, instead of outside of it?
(just 'cause i'm gonna recompile my widgets so i want to be sure)
-
- Part Of The Furniture
- Posts: 4204
- Joined: Sun Jan 03, 2010 5:45 pm
Re: Getting windows mousepointer icon = black square
Actually, looking at the code, I think it should be inside the block guarded by statement
Code: Select all
if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )