我想通过允许用户使用鼠标创建一个矩形区域来实现对象选择。 我正在创建一个继承自
TPanel
的面板 wxWindow
来处理某些事件并执行重绘。
然后我向其中添加一个 wxWrapSizer* imageWrapper
,在其中添加 ImageContainer
中的 std::vector<ImageContainer*> imageContent
元素,来自 std::vector<wxImage> images
MyFrame.cpp:
TPanel leftPanel = new TPanel(menuSplitter, &cManager, wxID_ANY, wxDefaultPosition, wxSize(600, 494));
wxWrapSizer imageWrapper = new wxWrapSizer(wxHORIZONTAL);
leftPanel->SetSizer(imageWrapper);
for (auto& img : images) {
auto image = new ImageContainer(leftPanel, &img, &cManager, wxID_ANY, wxDefaultPosition, wxSize(120, 100));
imageContent.push_back(image);
imageWrapper->Add(image, 0, wxALL, FromDIP(10));
}
所以我跟踪我需要的选择区域TPanel.h / TPanel.cpp:
class TPanel : public wxScrolled<wxWindow> {
public:
TPanel(wxWindow* parent, ColorManager* clrM, wxWindowID winid = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL | wxNO_BORDER, const wxString& name = wxASCII_STR(wxPanelNameStr));
private:
wxPoint startSel, endSel;
ColorManager* colorManager;
bool isSelect = false;
// ... and other minor details
};
void TPanel::OnMouseLeftDown(wxMouseEvent& evt) {
if (!isSelect) {
CaptureMouse();
isSelect = true;
startSel = ScreenToClient(wxGetMousePosition());
}
}
void TPanel::OnMouseLeftUp(wxMouseEvent& evt) {
if (isSelect) {
ReleaseMouse();
isSelect = false;
Refresh();
}
}
void TPanel::OnMouseMove(wxMouseEvent& evt) {
if (isSelect) {
endSel = ScreenToClient(wxGetMousePosition());
Refresh();
}
}
void TPanel::OnMouseLost(wxMouseCaptureLostEvent& evt) {
ReleaseMouse();
isSelect = false;
Refresh();
}
void TPanel::OnSize(wxSizeEvent& event) {
wxSize size = GetClientSize();
this->SetVirtualSize(size);
event.Skip();
}
好吧,我可以直接在面板上绘制这个区域,但是然后它会显示在
imageContent
的元素下。我想要的是将其显示在面板的所有子窗口之上,在其边界内。
wxWindow
的构造函数中初始化 TPanel
以在上面创建一个透明窗口并在其上绘制选区。窗口确实是在子元素上方创建的,但是 wxBG_STYLE_TRANSPARENT
没有提供任何透明度。wxOverlay
的信息和示例太少,我无法理解如何正确使用它。在wxClientDC
、wxWindowDC
、wxScreenDC
等方法中,我只用wxScreenDC
就实现了闪烁绘制。在其他情况下,我根本无法显示该区域。更新。 现在我选择了一个解决方法。
TPanel
生成选择开始事件,MyFrame
在 MultiSelection()
中处理该事件。这里,检查矩形描边区域与控件的wxRect
的交集,并传递需要在子元素上绘制的区域。该方法有效,但我不确定它在大型商业程序或操作系统中是否同样有效。
void MyFrame::MultiSelection(wxCommandEvent& evt) {
wxRect selectRC = wxRect(leftPanel->strSel, leftPanel->endSel);
for (auto& item : imageContent) {
if (item->GetRect().Intersects(selectRC)) {
item->isMark = true;
item->isSelect = true;
item->selectRC = wxRect(selectRC.GetX() - item->GetPosition().x, selectRC.GetY() - item->GetPosition().y,
selectRC.GetWidth(), selectRC.GetHeight());
}
else {
item->isMark = false;
item->isSelect = false;
}
}
}
你应该看看wxOverlay