[英]Create a Titleless/Borderless draggable wxFrame in wxWidgets
Hi i am trying to create a wxApp that will have not have a titlebar(including the minimize, maximize and close) icons that are by default provided.嗨,我正在尝试创建一个 wxApp,它没有默认提供的标题栏(包括最小化、最大化和关闭)图标。 The code that i have is as follows: main.h
我的代码如下: main.h
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
main.cpp主程序
bool MyApp::OnInit()
{
MyFrame *prop = new MyFrame(wxT("MyFrame"));
prop->Show(true);
return true;
}
myframe.h myframe.h
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title);
void OnClick(wxMouseEvent& event);
};
myframe.cpp myframe.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我的面板.h
class MyPanel : public wxPanel
{
public:
MyPanel(wxFrame *frame, int id);
void OnClick(wxMouseEvent& event);
};
mypanel.cpp我的面板.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我的按钮.h
class MyButton : public wxPanel
{
public:
MyButton(wxPanel *panel, int id, const wxString &label);
void OnClick(wxMouseEvent& event);
};
mybutton.cpp mybutton.cpp
void MyButton::onClick(wxMouseEvent &event)
{
}
What i want is:我想要的是:
Is this possible in wxWidgets?这在 wxWidgets 中可能吗? If yes, how can i achieve this?
如果是,我怎样才能做到这一点?
I am not proposing any new way of dragging.我没有提出任何新的拖动方式。 The new frame/window that we will have should also be dragged only by its own customized title bar.
我们将拥有的新框架/窗口也应该仅由其自定义标题栏拖动。 It's exactly like dragging the old frame by double clicking and dragging the frame in the native case.
就像在原生情况下通过双击并拖动框架来拖动旧框架一样。 I just want to customize the native title bar.
我只想自定义本机标题栏。 Like increase its height, change it's colour, change how to three buttons(minimize, maximize and close) look.
比如增加它的高度,改变它的颜色,改变三个按钮(最小化,最大化和关闭)的外观。
Here's the simplest example I can think of how to create a frame with a pseudo titlebar that can be clicked to drag the frame around.这是我能想到的最简单的例子,如何创建一个带有伪标题栏的框架,可以点击它来拖动框架。 This example shows which mouse events need to be handled to drag the window around and how to do the calculations needed in those event handlers.
此示例显示需要处理哪些鼠标事件以拖动窗口以及如何在这些事件处理程序中进行所需的计算。
Note that moving the frame needs to be done in screen coordinates, but the coordinates received in the event handlers will be in client coordinates for the title bar.请注意,移动框架需要在屏幕坐标中完成,但在事件处理程序中接收到的坐标将在标题栏的客户端坐标中。 This example also shows how to do those coordinate conversions.
此示例还展示了如何进行这些坐标转换。
#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);
On windows, it looks like this.在 Windows 上,它看起来像这样。
You should be able to add whatever buttons you want to the custom title bar exactly as you would add buttons to any other window.您应该能够将任何您想要的按钮添加到自定义标题栏,就像您将按钮添加到任何其他窗口一样。
" Is this possible in wxWidgets? " “这在 wxWidgets 中可行吗? ”
Yes.是的。 You need to use a wxWindow instead of a wxFrame and set some style for it.
您需要使用wxWindow而不是 wxFrame 并为其设置一些样式。 like
wxBORDER_NONE
.像
wxBORDER_NONE
。 But you will have to implement many things that wxFrame already provides.但是您必须实现 wxFrame 已经提供的许多东西。
And your proposed way of dragging seems wrong/confusing to me.你提议的拖动方式对我来说似乎是错误的/令人困惑的。 99.99% of users prefer a UI they are used to it, avoiding to learn a new way of doing simple things they already know.
99.99% 的用户更喜欢他们习惯的 UI,避免学习一种新的方式来做他们已经知道的简单事情。
If you just want to avoid resizing then you have two ways:如果您只想避免调整大小,那么您有两种方法:
event.Skip(false)
(to prevent handling in parent) is not neccessary. event.Skip(false)
调用event.Skip(false)
(以防止在父event.Skip(false)
处理)。 In both cases the user will see a "resize" mouse pointer when hovering the mouse at any border, but nothing else, no resizing, will be done.在这两种情况下,用户将鼠标悬停在任何边框上时都会看到“调整大小”鼠标指针,但不会执行任何其他操作,不调整大小。
@JasonLiam, @杰森利亚姆,
Don't forget to place the application icon in the top left corner of you title bar and handle the right/left mouse clicks appropriately (as in native application) (if you want to go this route and get rid of the native frame window).不要忘记将应用程序图标放置在标题栏的左上角并适当处理鼠标右键/左键单击(如在本机应用程序中)(如果您想走这条路并摆脱本机框架窗口) .
Thank you.谢谢你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.