我想编写一个应用程序,它必须在任何平台上具有相同的外观。我决定使用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。
我先选择了:
#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)
然后闪烁的战争就开始了。删除背景根本没有帮助:
#define ENABLE_ERASING 1
Here我发现解决方案需要为调整大小添加正确的处理程序:
#define ENABLE_ERASING 0
#define UPDATE_ON_RESIZE 1
答案 0 :(得分:0)
wxWidgets对于编写在所有平台上必须具有相同外观的应用程序来说显然不是一个好的选择,因为这直接针对wxWidgets设计目标,这些目标与每个平台下的本机外观无法区分。
使用wxWidgets做你想做的事情的唯一方法是使用它的wxUniversal端口,它在各处实现相同的外观。但请注意,与通常的端口(wxMSW,wxGTK,wxOSX)相比,它有许多错误和缺少的功能,因此如果您决定使用它,您应该准备好处理它们。但是,使用任何原生端口仍然是一个更好的主意,因为你显然正在尝试这样做。