Create a Titleless/Borderless draggable wxFrame in wxWidgets(在wxWidget中创建无标题/无边框的可拖动wxFrame)
问题描述
您好,我正在尝试创建一个wxApp,它将没有默认提供的标题栏(包括最小化、最大化和关闭)图标。我拥有的代码如下: main.hclass MyApp : public wxApp
{
public:
virtual bool OnInit();
};
main.cpp
bool MyApp::OnInit()
{
MyFrame *prop = new MyFrame(wxT("MyFrame"));
prop->Show(true);
return true;
}
myFra.h
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
void OnClick(wxMouseEvent& event);
};
myFra.cpp
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(250, 130))
{
MyPanel *panel = new MyPanel(this, wxID_ANY);
panel->SetBackgroundColour(wxColour(255,255,255));
MyButton *button = new MyButton(panel, wxID_ANY, wxT("Ok"));
Connect( wxEVT_LEFT_UP,
wxMouseEventHandler(MyFrame::OnClick));
panel->Centre();
}
void MyFrame::OnClick(wxMouseEvent& event)
{
std::cout << "event reached frame class" << std::endl;
}
mypanel.h
class MyPanel : public wxPanel
{
public:
MyPanel(wxFrame *frame, int id);
void OnClick(wxMouseEvent& event);
};
mypanel.cpp
MyPanel::MyPanel(wxFrame *frame, int id)
: wxPanel(frame, id)
{
Connect( wxEVT_LEFT_UP,
wxMouseEventHandler(MyPanel::OnClick));
}
void MyPanel::OnClick(wxMouseEvent& event)
{
std::cout << "event reached panel class" << std::endl;
}
myButton.h
class MyButton : public wxPanel
{
public:
MyButton(wxPanel *panel, int id, const wxString &label);
void OnClick(wxMouseEvent& event);
};
myButton.cpp
void MyButton::onClick(wxMouseEvent &event)
{
}
我想要的是:
- 顶部不应有标题栏(包括三个最大化、最小化和关闭按钮)。
- 现在,由于框架顶部没有标题栏,因此无法拖动、关闭、最大化或最小化窗口。为此,我想在顶部创建一个自定义标题栏,其中应该有三个自定义的最大化、最小化和关闭按钮,并且我应该能够通过双击并按住并拖动新创建的框架的最上面部分来拖动框架。
这在wxWidget中可能吗?如果是,我如何实现这一点?
我不是在提议任何新的拖拽方式。我们将拥有的新框架/窗口也应该只由它自己的定制标题栏拖动。这与在本机情况下通过双击并拖动框架来拖动旧框架完全一样。我只想自定义本机标题栏。如增加其高度、更改其颜色、更改三个按钮(最小化、最大化和关闭)的外观。
推荐答案
这是我能想到的最简单的示例,如何创建一个带有伪标题栏的框架,可以单击它来拖动框架。此示例显示了需要处理哪些鼠标事件才能拖动窗口,以及如何在这些事件处理程序中进行所需的计算。
请注意,移动框架需要在屏幕坐标中完成,但事件处理程序中接收的坐标将在标题栏的客户端坐标中进行。此示例还说明如何执行这些坐标转换。
#include "wx/wx.h"
class CustomTitleBar:public wxWindow
{
public:
CustomTitleBar(wxWindow* p) : wxWindow(p,wxID_ANY)
{
m_dragging = false;
SetBackgroundColour(*wxGREEN);
Bind(wxEVT_LEFT_DOWN,&CustomTitleBar::OnMouseLeftDown,this);
Bind(wxEVT_MOUSE_CAPTURE_LOST, &CustomTitleBar::OnMouseCaptureLost,
this);
}
wxSize DoGetBestClientSize() const override
{
return wxSize(-1,20);
}
private:
void OnMouseLeftDown(wxMouseEvent& event)
{
if ( !m_dragging )
{
Bind(wxEVT_LEFT_UP,&CustomTitleBar::OnMouseLeftUp,this);
Bind(wxEVT_MOTION,&CustomTitleBar::OnMouseMotion,this);
m_dragging = true;
wxPoint clientStart = event.GetPosition();
m_dragStartMouse = ClientToScreen(clientStart);
m_dragStartWindow = GetParent()->GetPosition();
CaptureMouse();
}
}
void OnMouseLeftUp(wxMouseEvent&)
{
FinishDrag();
}
void OnMouseMotion(wxMouseEvent& event)
{
wxPoint curClientPsn = event.GetPosition();
wxPoint curScreenPsn = ClientToScreen(curClientPsn);
wxPoint movementVector = curScreenPsn - m_dragStartMouse;
GetParent()->SetPosition(m_dragStartWindow + movementVector);
}
void OnMouseCaptureLost(wxMouseCaptureLostEvent&)
{
FinishDrag();
}
void FinishDrag()
{
if ( m_dragging )
{
Unbind(wxEVT_LEFT_UP,&CustomTitleBar::OnMouseLeftUp,this);
Unbind(wxEVT_MOTION,&CustomTitleBar::OnMouseMotion,this);
m_dragging = false;
}
if ( HasCapture() )
{
ReleaseMouse();
}
}
wxPoint m_dragStartMouse;
wxPoint m_dragStartWindow;
bool m_dragging;
};
class Customframe : public wxFrame
{
public:
Customframe(wxWindow* p)
:wxFrame(p, wxID_ANY, wxString(), wxDefaultPosition, wxSize(150,100),
wxBORDER_NONE)
{
CustomTitleBar* t = new CustomTitleBar(this);
SetBackgroundColour(*wxBLUE);
wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
szr->Add(t,wxSizerFlags(0).Expand());
SetSizer(szr);
Layout();
}
};
class MyFrame: public wxFrame
{
public:
MyFrame():wxFrame(NULL, wxID_ANY, "Custom frame Demo", wxDefaultPosition,
wxSize(400, 300))
{
wxPanel* bg = new wxPanel(this, wxID_ANY);
wxButton* btn = new wxButton(bg, wxID_ANY, "Custom frame");
wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
szr->Add(btn,wxSizerFlags(0).Border(wxALL));
bg->SetSizer(szr);
Layout();
btn->Bind(wxEVT_BUTTON, &MyFrame::OnButton, this);
m_customFrame = NULL;
}
private:
void OnButton(wxCommandEvent&)
{
if ( m_customFrame )
{
m_customFrame->Close();
m_customFrame = NULL;
}
else
{
m_customFrame = new Customframe(this);
m_customFrame->CenterOnParent();
m_customFrame->Show();
}
}
wxFrame* m_customFrame;
};
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
MyFrame* frame = new MyFrame();
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(MyApp);
在Windows上,它看起来是这样的。
您应该能够将所需的任何按钮添加到自定义标题栏,就像将按钮添加到任何其他窗口一样。
这篇关于在wxWidget中创建无标题/无边框的可拖动wxFrame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在wxWidget中创建无标题/无边框的可拖动wxFrame
基础教程推荐
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 设计字符串本地化的最佳方法 2022-01-01
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- C++,'if' 表达式中的变量声明 2021-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04