乐者为王

Do one thing, and do it well.

如何实现一个可拖动的无标题栏窗口

无标题栏窗口的实现很简单。先将窗口从wxMiniFrame继承,然后在窗口的构造函数中设置一下窗口的样式。

1
2
3
4
5
MainFrame::MainFrame(const wxPoint& pos, const wxSize& size)
    : wxMiniFrame(NULL, wxID_ANY, wxEmptyString, pos, size)
{
    SetWindowStyleFlag(wxFRAME_NO_TASKBAR | wxNO_BORDER);
}

但是,窗口的移动通常都是通过鼠标点住标题栏拖动窗口来实现的,那么现在没有了标题栏,该如何移动窗口呢?我们知道,当鼠标拖动窗口时,它在窗口中的位置是始终不变的。所以如果能够在鼠标移动过程中,通过改变窗口在桌面上的坐标,并且始终保持鼠标相对于窗口的坐标不变,即可实现鼠标的拖动效果。

在具体的设计中,先在鼠标的MouseDown事件中记录下鼠标相对于窗口的偏移,在鼠标的MouseMove事件中根据鼠标在桌面上的位置实时设置窗口的位置,即可达到鼠标拖动窗口的操作。利用此方法实现鼠标拖动,与常规的标题栏鼠标拖动在效果上有一点区别。通过标题栏拖动时,鼠标移动过程中不重画窗口,只有松开鼠标后才在固定位置重画窗口,因此其速度较快。而采用本方法的拖动过程中,每移动一步都需要重画窗口,因此对速度稍有影响,在慢一些的机器上可能会出现轻微的拖尾现象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void MainFrame::OnMouseMove(wxMouseEvent& event)
{
    if (event.Dragging() && event.LeftIsDown())
    {
        wxPoint pt = ClientToScreen(event.GetPosition());
        int x = pt.x - m_delta.x;
        int y = pt.y - m_delta.y;
        Move(x, y);
    }
}

void MainFrame::OnMouseLeftDown(wxMouseEvent& event)
{
    CaptureMouse();
    wxPoint pt = ClientToScreen(event.GetPosition());
    wxPoint origin = GetPosition();
    int dx = pt.x - origin.x;
    int dy = pt.y - origin.y;
    m_delta = wxPoint(dx, dy);
}

void MainFrame::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event))
{
    if (HasCapture())
    {
        ReleaseMouse();
    }
}

代码下载

Comments