I have updated the code to include some more information
Code: Select all
#include <wx/wx.h>
#include <wx/msw/wrapwin.h>
bool CreatewxBitmapFromCurrentCursor(wxBitmap& bitmap)
{
CURSORINFO ci{0};
ICONINFO ii{0};
ci.cbSize = sizeof(ci);
if ( !::GetCursorInfo(&ci) || (ci.flags & CURSOR_SHOWING) == 0 )
{
wxLogError("Could not get the cursor info.");
return false;
}
// class AutoIconInfo from include\msw\private.h can be used instead
if ( !::GetIconInfo(ci.hCursor, &ii) )
{
wxLogError("Could not get icon info about the cursor.");
return false;
}
if ( !ii.hbmColor )
wxLogMessage("The cursor is monochrome.");
else
wxLogMessage("The cursor is in color.");
::DeleteObject(ii.hbmColor);
::DeleteObject(ii.hbmMask);
wxIcon icon;
wxBitmap bmp;
if ( !icon.CreateFromHICON(WXHICON(ci.hCursor)) )
{
wxLogError("Could not create wxIcon from HCURSOR.");
return false;
}
if ( !bmp.CopyFromIcon(icon) )
{
wxLogError("Could not create wxBitmap from wxIcon.");
return false;
}
wxLogMessage("wxBitmap created from the cursor: size = %dx%d pixels, depth = %d, mask = %s.",
bmp.GetWidth(), bmp.GetHeight(), bmp.GetDepth(), bmp.GetMask() ? "Yes" : "No");
bitmap = bmp;
return true;
}
class MyDialog : public wxDialog
{
public:
MyDialog() : wxDialog(nullptr, wxID_ANY, "Test")
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
m_button = new wxButton(this, wxID_ANY, "Update Cursor Bitmap (<F5>)");
Bind(wxEVT_BUTTON, [this](wxCommandEvent&){ UpdateCursorBitmap(); } );
mainSizer->Add(m_button, wxSizerFlags().Expand().Border());
wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
mainSizer->Add(logCtrl, wxSizerFlags().Proportion(1).Expand().Border());
SetSizer(mainSizer);
SetClientSize(FromDIP(wxSize(800, 800)));
wxAcceleratorEntry entries[1];
entries[0].Set(wxACCEL_NORMAL, WXK_F5, m_button->GetId());
wxAcceleratorTable accel(1, entries);
SetAcceleratorTable(accel);
UpdateCursorBitmap();
}
private:
wxButton* m_button;
void UpdateCursorBitmap()
{
wxBitmap bitmap;
if ( !CreatewxBitmapFromCurrentCursor(bitmap) )
return;
m_button->SetBitmap(wxNullBitmap, wxTOP); // work around a bitmap not being updated properly
m_button->SetBitmap(bitmap, wxTOP);
bitmap.SaveFile("captured_cursor.png", wxBITMAP_TYPE_PNG);
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
wxInitAllImageHandlers();
MyDialog().ShowModal();
return false;
}
}; wxIMPLEMENT_APP(MyApp);
Parduz wrote: ↑Wed Apr 14, 2021 2:13 pm
I think that this should be considered a bug... i don't know what CreateFromHICON do but it should take care of this default and well documented
behaviour of b/w icons in Windows. Don't you?
The mask is recognized but the depth and size are wrong, this is output from text cursor first and arrow cursor second:
Code: Select all
17:43:33: The cursor is monochrome.
17:43:33: wxBitmap created from cursor: size = 32x64 pixels, depth = 32, mask = Yes.
17:43:37: The cursor is in color.
17:43:37: wxBitmap created from cursor: size = 32x32 pixels, depth = 32, mask = No.
Parduz wrote: ↑Wed Apr 14, 2021 2:13 pm
Now i need to find a way to manage this case myself... which i fear will lead to the same problems i had before. I'll see.
I would ask in the wx-users mailing first, to see what can be done and if it is indeed a bug. I think it could be worked around in the user code, but I did not have time to try yet.
IIRC, there were some recentish changes regarding handling monochrome bitmaps on Windows, I have tested this on the master but also with 3.05 to see if there was any regression but the result was same for both. But perhaps my whole idea is incorrect and one is not supposed to create a wxIcon from HCURSOR even when HCURSOR is typedef for HICON. OTOH, creating a wxCursor from HCURSOR and then trying to create a wxBitmap from it led to a crash...
Parduz wrote: ↑Wed Apr 14, 2021 2:13 pm
Do the HICON will be destroyed also with a new CreateFromHICON call?
I would hope so but I would also rather ask about this to make sure.