how to wxGridCellRenderer wxBitmap for a wxGridColumn

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
wxotichna
Earned a small fee
Earned a small fee
Posts: 19
Joined: Fri Sep 16, 2022 8:37 am

how to wxGridCellRenderer wxBitmap for a wxGridColumn

Post by wxotichna »

I had to show an "icon" into a wxGrid column and this is how it can be done.

It may not be the "best"solution but ... it works

define a class that does the rendering

Code: Select all

#define wxGRID_VALUE_ICON   wxT("icon_png")
#define ICON_HEIGHT			24
#define ICON_WIDTH			24

class IconCellRenderer : public wxGridCellRenderer
	{
public:
	IconCellRenderer()
		{
		}

	wxSize GetBestSize(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, int row, int col)
    		{
	    	return wxSize(ICON_WIDTH,ICON_HEIGHT);
    		}

	void Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool isSelected)
		{
	    	wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);

		wxGridTableBase *dbP = grid.GetTable();

		void *avalP = dbP->GetValueAsCustom(row, col, wxGRID_VALUE_ICON);

		if ( ! avalP ) return;

		wxBitmap *bmP = (wxBitmap *)avalP;

		dc.SetClippingRegion(rect);
		dc.DrawBitmap(*bmP,rect.x,rect.y);
		dc.DestroyClippingRegion();
		}

	IconCellRenderer * Clone () const
		{
		return new IconCellRenderer();
		}
	};
you need to report the new "type" for the given column, this is in the class that extends the TableBase

Code: Select all


	wxString GetTypeName( int row, int col )
		{
		switch (col)
			{
			case COL_ESTATUS:  return wxGRID_VALUE_ICON;

			default: return wxGRID_VALUE_STRING;
			}
		}

and also the method to return the custom type

Code: Select all


    virtual void* GetValueAsCustom( int row, int col, const wxString& typeName )
    	{
    	if ( col != COL_ESTATUS ) return NULL;

    	// note that what is returned is a pointer
    	PvExtension *extP = e_filtered.at(row);

    	if ( extP->isPhoneBusy() )
    		return &busyIcon;

    	if ( extP->isPhoneRing() )
    		return &ringIcon;

    	return NULL;
    	}


One way to create the "icon" is using the windows resource (if you are on windows)

Code: Select all


ringIcon("telephone-ring-128x128.png", wxBITMAP_TYPE_PNG_RESOURCE),
busyIcon("telephone-busy-128x128.png", wxBITMAP_TYPE_PNG_RESOURCE)

wxBitmapHelpers::Rescale(ringIcon, wxSize(ICON_WIDTH,ICON_HEIGHT));
wxBitmapHelpers::Rescale(busyIcon, wxSize(ICON_WIDTH,ICON_HEIGHT));

the .rc file has the following lines

Code: Select all

telephone-ring-128x128.png RCDATA "../resources/telephone-ring-128x128.png"
telephone-busy-128x128.png RCDATA "../resources/telephone-busy-128x128.png"
and is used like this

Code: Select all

windres -v -I${MINGW_HOME}\include\wx-3.2 ../resources/resources.rc ../resources/resources.o 

then you need to actually tell to the wxGrid to use the new renderer

Code: Select all

// you need to have iconRendererP as long lived as the wxGrid instance
iconRenderP = new IconCellRenderer();
jtableP->RegisterDataType (	wxGRID_VALUE_ICON, iconRenderP, jtableP->GetDefaultEditor() );
Post Reply