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
Re: Getting windows mousepointer icon = black square
Re: Getting windows mousepointer icon = black square
Re: Getting windows mousepointer icon = black square
As shown in my code from my previous post, hbmColor is not used for monochrome cursors, so...
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?
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.
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.
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.
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.
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);
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)
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) )