wxwidgets

How can I make a wxColorPickerCtrl narrower?


wxColourPickerCtrl (WXMSW): Can it be narrower without looking awful?

I'm trying to save some horizontal space in a wxWidgets/DialogBlocks project. One place that I think I could save is in the width of a wxColorPickerCtrl, which seems to like to be 95 pixels wide.

colorpicker default appearance

That seems unnecessarily wide. However, when I set its width to something nicer, like 25px, I get something appallingly ugly.

colorpicker 25px wide--bad!

Is there a (supported) way to get the control to narrow nicely? It seems as though it might be possible, because I'm creating this in DialogBlocks, and when I insert the control in the GUI builder, the app shows me something very nice. However, it never renders it that way when I build.

colorpicker 25px wide in DialogBlocks builder--nice!

I know the GUI builder is showing me a control and not a static image (au3info says it's a button, the same as what it says when I inspect the window created by the compiled, running app), so it seems like this ought to be possible. I just don't know how.

I have tried a few sensible (IMHO) style changes, but to no avail. The picker control just doesn't resize/clip the image that is on the rendered button.

Is there a way to make the control something very minimal, like a square? I have been unable to find any examples of this (outside of the DialogBlocks GUI builder)

ADDENDUM

I debugged my simple project and followed execution of the wxColourPickerCtrl constructor into generic\clrpickerg.cpp wxGenericColourButton::Create()

m_bitmap = wxBitmap( 60, 13 );

If I change the hardcoded width to, say, 13, the button looks like I want. Is there a way to alter the underlying bitmap of this member object that's not exactly accessible?

HACKED SOLUTION

Taking the advice of the answer, I had to subclass both wxGenericColourButton (to change the bitmap) and wxColourPickerCtrl (to use the new button class). This will be sensitive to changes in the wxWidgets innards, but I couldn't find any better option.

    class _wxGenericColourButton : public wxGenericColourButton {
    public:
        _wxGenericColourButton() {}
        _wxGenericColourButton( wxWindow *parent,
                                wxWindowID id,
                                const wxColour& col = *wxBLACK,
                                const wxPoint& pos = wxDefaultPosition,
                                const wxSize& size = wxDefaultSize,
                                long style = wxCLRBTN_DEFAULT_STYLE,
                                const wxValidator& validator = wxDefaultValidator,
                                const wxString& name = wxColourPickerWidgetNameStr )
        {
            Create(parent,id,col,pos,size,style,validator,name);
        }
        bool Create( wxWindow *parent,
                     wxWindowID id,
                     const wxColour& col = *wxBLACK,
                     const wxPoint& pos = wxDefaultPosition,
                     const wxSize& size = wxDefaultSize,
                     long style = wxCLRBTN_DEFAULT_STYLE,
                     const wxValidator& validator = wxDefaultValidator,
                     const wxString& name = wxColourPickerWidgetNameStr )
        {
            // Generally taken from wxGenericColourButton::Create() [clrpickerg.cpp:44]
    
            // Make the bitmap smaller by default. Enlarging the button should work fine.
            m_bitmap = wxBitmap(13, 13);
    
            // create this button
            if (!wxBitmapButton::Create( parent, id, m_bitmap, pos,
                                         size, style | wxBU_AUTODRAW, validator, name ))
            {
                wxFAIL_MSG( wxT("wxGenericColourButton creation failed") );
                return false;
            }
    
            // and handle user clicks on it
            Connect(GetId(), wxEVT_BUTTON,
                    wxCommandEventHandler(wxGenericColourButton::OnButtonClick),
                    NULL, this);
    
            m_colour = col;
            UpdateColour();
            InitColourData();
    
            return true;
        }
    };
    
    class _wxColourPickerCtrl : public wxColourPickerCtrl {
    public:
        _wxColourPickerCtrl() {}
    
        _wxColourPickerCtrl( wxWindow *parent, wxWindowID id,
                             const wxColour& col = *wxBLACK, const wxPoint& pos = wxDefaultPosition,
                             const wxSize& size = wxDefaultSize, long style = wxCLRP_DEFAULT_STYLE,
                             const wxValidator& validator = wxDefaultValidator,
                             const wxString& name = wxColourPickerCtrlNameStr)
        {
            Create(parent, id, col, pos, size, style, validator, name);
        }
        
        bool Create( wxWindow *parent, wxWindowID id,
                     const wxColour& col = *wxBLACK,
                     const wxPoint& pos = wxDefaultPosition,
                     const wxSize& size = wxDefaultSize,
                     long style = wxCLRP_DEFAULT_STYLE,
                     const wxValidator& validator = wxDefaultValidator,
                     const wxString& name = wxColourPickerCtrlNameStr)
        {
            // This code is generally taken from: wxColourPickerCtrl::Create() [clrpickercmn.cpp:51]
            
            if (!wxPickerBase::CreateBase(parent, id, col.GetAsString(), pos, size,
                                          style, validator, name))
                return false;
     
            // Use our "enhanced" _wxGenericColourButton instead of the one with hardcoded,
            //   undesirable behavior.
            m_picker = new _wxGenericColourButton(this, wxID_ANY, col,
                                                  wxDefaultPosition, wxDefaultSize,
                                                  GetPickerStyle(style));           
            // Copied from clrpickercmn.cpp
            wxPickerBase::PostCreation();
            m_picker->Connect(wxEVT_COLOURPICKER_CHANGED,
                              wxColourPickerEventHandler(wxColourPickerCtrl::OnColourChange),
                              NULL, this);
            
            return true;
        }
    };

Solution

  • Unfortunately there is no clean way to work around this bug. You could derive from wxGenericColourButton and change its m_bitmap and then call UpdateColour() but this would be using undocumented and subject to change API and is just generally ugly.

    This really should be fixed in wxGenericColourButton itself, the bitmap should be computed from the provided size (and also updated when the size changes!) and it shouldn't be difficult to do. If you decide to try to do this, please don't hesitate to submit your patches to wxWidgets.