自定义wxControl子类CDropDownTool的两个技术问题求助
自定义wxControl子类CDropDownTool的两个技术问题求助
你好,我正在实现一个类似带下拉按钮的工具栏控件,自定义了CDropDownTool这个wxControl子类,目前功能基本正常,但遇到两个问题:
- 鼠标悬停时没有像普通按钮那样的高亮效果
- 将控件添加到ToolBar后,重写的
DoGetBestSize函数从未被调用
我的实现代码如下:
构造函数代码
CDropDownTool::CDropDownTool(wxWindow* parent, int id, const wxBitmap& bmptool, const wxBitmap& bmpDrop, const wxString& tooltip) : wxControl(parent, id, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE) { m_BMPTool = bmptool; m_BMPDrop = bmpDrop; m_ID = id; wxSize sz1 = m_BMPTool.GetSize(); wxSize sz2 = m_BMPDrop.GetSize(); SetClientSize(wxSize(sz1.x + sz2.x + GAP, std::max(sz1.y, sz2.y))); Bind(wxEVT_PAINT, &CDropDownTool::OnPaint, this); Bind(wxEVT_LEFT_DOWN, &CDropDownTool::OnLeftDown, this); }
绘制函数代码
void CDropDownTool::OnPaint(wxPaintEvent& event) { wxPaintDC pdc(this); wxSize szBMP = m_BMPTool.GetSize(); auto Rect = GetClientRect(); int y = (Rect.GetHeight() - szBMP.GetHeight()) / 2; wxPoint TL = Rect.GetTopLeft(); TL.y = y; m_Tool = wxRect(TL, szBMP); pdc.DrawBitmap(m_BMPTool, TL); wxPoint TL2 = TL; TL2.x += m_BMPTool.GetSize().x + GAP; m_DropTool = wxRect(TL2, m_BMPDrop.GetSize()); pdc.DrawBitmap(m_BMPDrop, TL2); }
问题1:添加鼠标悬停高亮效果
要实现和原生按钮一致的悬停高亮,你需要跟踪鼠标状态并在绘制时动态调整样式,具体步骤如下:
在
CDropDownTool类中添加一个成员变量,用来标记悬停状态:private: bool m_isHovering = false;在构造函数中绑定鼠标进入/离开事件,更新状态并触发重绘:
// 补充到构造函数的Bind代码后 Bind(wxEVT_ENTER_WINDOW, &CDropDownTool::OnEnterWindow, this); Bind(wxEVT_LEAVE_WINDOW, &CDropDownTool::OnLeaveWindow, this);实现事件处理函数:
void CDropDownTool::OnEnterWindow(wxMouseEvent& event) { m_isHovering = true; Refresh(); // 触发重绘更新样式 event.Skip(); // 允许事件继续传递,不影响其他逻辑 } void CDropDownTool::OnLeaveWindow(wxMouseEvent& event) { m_isHovering = false; Refresh(); event.Skip(); }修改
OnPaint函数,根据悬停状态绘制高亮效果。这里推荐使用系统默认的高亮配色,保证和原生控件风格统一:void CDropDownTool::OnPaint(wxPaintEvent& event) { wxPaintDC pdc(this); wxSize szBMP = m_BMPTool.GetSize(); auto Rect = GetClientRect(); int y = (Rect.GetHeight() - szBMP.GetHeight()) / 2; wxPoint TL = Rect.GetTopLeft(); TL.y = y; m_Tool = wxRect(TL, szBMP); // 悬停时绘制高亮背景 if (m_isHovering) { wxColour highlightCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); // 可以设置半透明效果,让高亮更柔和 highlightCol.SetAlpha(128); pdc.SetBrush(wxBrush(highlightCol)); pdc.SetPen(wxPen(highlightCol, 1)); // 可以选择高亮整个控件,或者分别高亮两个按钮区域 pdc.DrawRectangle(Rect); } pdc.DrawBitmap(m_BMPTool, TL); wxPoint TL2 = TL; TL2.x += m_BMPTool.GetSize().x + GAP; m_DropTool = wxRect(TL2, m_BMPDrop.GetSize()); pdc.DrawBitmap(m_BMPDrop, TL2); }
问题2:DoGetBestSize未被调用的解决方法
wxToolBar对添加的自定义控件有特殊的布局逻辑,你需要确保最佳尺寸的实现和传递是正确的:
首先正确重写
DoGetBestSize函数,返回控件的理想尺寸:wxSize CDropDownTool::DoGetBestSize() const override { wxSize sz1 = m_BMPTool.GetSize(); wxSize sz2 = m_BMPDrop.GetSize(); return wxSize(sz1.x + sz2.x + GAP, std::max(sz1.y, sz2.y)); }修改构造函数中的尺寸设置逻辑,用
SetInitialSize替代SetClientSize,让wxWidgets记录下最佳尺寸:// 替换原来的SetClientSize代码 wxSize bestSize = DoGetBestSize(); SetInitialSize(bestSize);当把控件添加到ToolBar时,确保调用
Realize()让工具栏重新布局:// 示例添加代码 wxToolBar* toolbar = new wxToolBar(this); CDropDownTool* dropTool = new CDropDownTool(toolbar, ...); toolbar->AddControl(dropTool); toolbar->Realize(); // 必须调用,让工具栏应用布局
如果还是不生效,可以尝试在添加控件后手动强制设置尺寸:
dropTool->SetSize(dropTool->GetBestSize());
备注:内容来源于stack exchange,提问作者macroland
相关产品推荐
相关产品推荐

