【发布时间】:2014-09-14 13:20:34
【问题描述】:
我想编写一个应用程序,它必须在任何平台上都具有相同的外观。我决定使用 wxWidgets
(I never have a large amount of work with this library).
从 ScrollBar 开始我的自定义。这是一个糟糕的决定,
(inheritance from wxScrollBar = because all control badly flickering)
因为在 OS Windows 下默认 ScrollBar 的自定义能力很差,explanation here。接下来我的步骤是进行与this post 相同的工作,但使用 wxWidgets 而不是 MFC。
- 最好在一个窗口上绘制所有控件,或者用自己的窗口替换每个 4 部分:滚动背景、拇指滑块、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)
- 为什么静态绘制(不改变位置、大小)拇指滑块总是正确绘制并且调整大小不会对该矩形产生任何影响?
然后闪烁的战争开始了。擦除背景根本没有帮助:
#define ENABLE_ERASING 1
Here 我发现解决方案需要添加正确的处理程序来调整大小:
#define ENABLE_ERASING 0
#define UPDATE_ON_RESIZE 1
- 这是正确的解决方案吗?
- 我不明白为什么我必须这样做 ev.Skip(); 在 resize 事件处理程序中?
- 为什么here、here、here 使用 wxPanel、wxWindow 而不是 wxControl,也许我必须这样做?
操作系统窗口 7 x64; MinGW 4.8.1; wxWidgets 3.1.0
【问题讨论】: