wxWidgets绘制自定义控件

时间:2014-09-14 13:20:35

标签: c++ wxwidgets

我想编写一个应用程序,它必须在任何平台上具有相同的外观。我决定使用wxWidgets

 (I never have a large amount of work with this library).

从ScrollBar开始我的自定义。这是一个糟糕的决定,

(inheritance from wxScrollBar = because all control badly flickering)

因为在操作系统Windows下,默认的ScrollBar具有很差的自定义能力explanation here。接下来我的步骤是进行与this post相同的工作,但使用wxWidgets代替MFC。

  1. 更好地在一个窗口上绘制所有控件或用自己的窗口替换每个4个部分:滚动背景,拇指滑块,2个滚动箭头?需要建议。
  2. 我先选择了:

    #include "wx/wx.h"
    #include "wx/sizer.h"
    
    #define ENABLE_ERASING 0
    #define DISABLE_BORDER 1
    #define UPDATE_ON_RESIZE 0
    
    #if DISABLE_BORDER
    long gBorder = wxBORDER_NONE;
    #else
    long gBorder = 0;
    #endif
    
    class ScrollBar : public wxControl
    {
    public:
        ScrollBar(wxWindow *parent, wxWindowID id);
    protected:
        void on_paint(wxPaintEvent& ev);
    #if ENABLE_ERASING
        void on_erace(wxEraseEvent& ev);
    #endif
        void draw(wxDC& dc);
        wxSize DoGetBestSize() const override;
    #if UPDATE_ON_RESIZE
        void on_size(wxSizeEvent& ev);
    #endif
        wxDECLARE_EVENT_TABLE();
    private:
    };
    
    wxBEGIN_EVENT_TABLE(ScrollBar, wxControl)
    EVT_PAINT(ScrollBar::on_paint)
    #if ENABLE_ERASING
    EVT_ERASE_BACKGROUND(ScrollBar::on_erace)
    #endif
    #if UPDATE_ON_RESIZE
    EVT_SIZE(ScrollBar::on_size)
    #endif
    wxEND_EVENT_TABLE()
    
    ScrollBar::ScrollBar(wxWindow* parent, wxWindowID id)
        : wxControl(parent, id, wxDefaultPosition, wxDefaultSize, gBorder)
    {}
    
    void ScrollBar::on_paint(wxPaintEvent& ev)
    {
        wxPaintDC dc(this);
        draw(dc);
        wxSize size = GetClientSize();
        wxString text = wxString::Format("%i; %i paint", size.GetWidth(),     
    size.GetHeight());
        dc.DrawText(text, wxPoint(74, 8));
    }
    
    #if ENABLE_ERASING
    void ScrollBar::on_erace(wxEraseEvent& ev)
    {
        wxClientDC* clientDC = nullptr;
        if (!ev.GetDC())
            clientDC = new wxClientDC(this);
        wxDC* dc = clientDC ? clientDC : ev.GetDC() ;
        draw(*dc);
        wxSize size = GetClientSize();
        wxString text = wxString::Format("%i; %i erase", size.GetWidth(), 
    size.GetHeight());
        dc->DrawText(text, wxPoint(74, 8));
        if (clientDC)
            delete clientDC;
    }
    #endif
    
    void ScrollBar::draw(wxDC& dc)
    {
        wxSize size = dc.GetSize();
        // draw scroll arrows
        dc.SetBrush(*wxBLUE_BRUSH);
        dc.SetPen( wxPen( wxColor(0,175,175), 2 ) );
        dc.DrawRectangle(0, 0, 20, size.GetHeight());
        dc.DrawRectangle(size.GetWidth() - 21, 0, 20, size.GetHeight());
    
        // draw background
        dc.SetBrush(*wxGREY_BRUSH);
        dc.SetPen( wxPen( wxColor(175,175, 0), 2 ) );
        dc.DrawRectangle(21, 0, size.GetWidth() - 43, size.GetHeight());
    
        // draw thumb slider
        dc.SetBrush(*wxCYAN_BRUSH);
        dc.SetPen( wxPen( wxColor(175, 0, 175), 2 ) );
        dc.DrawRectangle(70, 7, 150, 20);
    
        dc.SetPen(wxNullPen);
        dc.SetBrush(wxNullBrush);
    }
    
    wxSize ScrollBar::DoGetBestSize() const
    {
        return wxSize(-1, 35);
    }
    
    #if UPDATE_ON_RESIZE
    void ScrollBar::on_size(wxSizeEvent& ev)
    {
        Refresh();
        ev.Skip();
    }
    #endif
    // ********************************************** //
    
    class MyApp: public wxApp
    {
        wxFrame* frame_;
        ScrollBar* sc_bar_;
    public:
        bool OnInit()
        {
            if ( !wxApp::OnInit() )
                return false;
    
            frame_ = new wxFrame(nullptr, wxID_ANY, "ScBar test App");
            sc_bar_ = new ScrollBar(frame_, wxID_ANY);
    
            wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
            sizer->Add(new wxButton(frame_, -1, "Tiny Button"), 0, 0, 0);
            sizer->Add(sc_bar_, 0, wxEXPAND, 0);
    
            frame_->SetSizer(sizer);
            frame_->Show();
            return true;
        }
    };
    
    IMPLEMENT_APP(MyApp)
    
    1. 为什么静态绘制(不更改位置,大小)拇指滑块始终绘制正确并调整大小不会对该矩形产生任何影响?
    2. 然后闪烁的战争就开始了。删除背景根本没有帮助:

      #define ENABLE_ERASING 1
      

      Here我发现解决方案需要为调整大小添加正确的处理程序:

      #define ENABLE_ERASING 0
      #define UPDATE_ON_RESIZE 1
      
      1. 这是正确的解决方案吗?
      2. 我不明白为什么我必须在resize事件处理程序中执行 ev.Skip();
      3. 为什么hereherehere使用wxPanel,wxWindow不是wxControl也许我必须这样做?
      4. OS Window 7 x64; MinGW 4.8.1; wxWidgets 3.1.0

1 个答案:

答案 0 :(得分:0)

wxWidgets对于编写在所有平台上必须具有相同外观的应用程序来说显然不是一个好的选择,因为这直接针对wxWidgets设计目标,这些目标与每个平台下的本机外观无法区分。

使用wxWidgets做你想做的事情的唯一方法是使用它的wxUniversal端口,它在各处实现相同的外观。但请注意,与通常的端口(wxMSW,wxGTK,wxOSX)相比,它有许多错误和缺少的功能,因此如果您决定使用它,您应该准备好处理它们。但是,使用任何原生端口仍然是一个更好的主意,因为你显然正在尝试这样做。