在wxWidget中创建无标题/无边框的可拖动wxFrame [英] Create a Titleless/Borderless draggable wxFrame in wxWidgets

查看:69
本文介绍了在wxWidget中创建无标题/无边框的可拖动wxFrame的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我正在尝试创建一个wxApp,它将没有默认提供的标题栏(包括最小化、最大化和关闭)图标。我拥有的代码如下: 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;
}

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)
{

}

我想要的是:

  1. 顶部不应有标题栏(包括三个最大化、最小化和关闭按钮)。
  2. 现在,由于框架顶部没有标题栏,因此无法拖动、关闭、最大化或最小化窗口。为此,我想在顶部创建一个自定义标题栏,其中应该有三个自定义的最大化、最小化和关闭按钮,并且我应该能够通过双击并按住并拖动新创建的框架的最上面部分来拖动框架。

这在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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆