wxWidgets实现无标题栏窗口拖动 wxWidgets实现无标题栏窗口拖动效果
zfwjsjzy 人气:2最近需要做一个自定义的标题栏,而其中最重要的就是要实现窗口的拖动。默认情况下有标题栏,都可以通过拖动系统默认的标题栏,但是自定义的标题栏需要自己实现拖动。
实现无标题窗口的拖动,在MFC中可以在鼠标在窗口中拖动时,发送虚假的消息给窗口来进行实现(注:MFC可以发送鼠标在标题栏拖动的消息)。但是在wxWidgets中,暂时没有看到类似的消息。因工作需要,才学习wxWidgets不久。如果有知道相关消息的朋友,请发消息告诉。而自己实现拖动,大致可以分为三个步骤。
1、在鼠标左键按下时,记录下鼠标位置,使用CaptureMouse来进行鼠标捕获 。注意,这里如果不捕获鼠标,那么也能实现拖动窗口,但是会出现一个小问题,就是当鼠标在窗口边缘快速的拖出窗口的时候,窗口不能进行移动。因为系统对鼠标的移动事件的发送是有事件间隔的,窗口收到该消息时鼠标已经离开了窗口,所以不能正确拖动。一定要记得设置鼠标捕获。
2、当鼠标拖动的时候(在鼠标事件中判断鼠标左键按下且在拖拽),计算鼠标新的位置相对之前的位移向量,并移动窗口到相应的位置。
3、处理鼠标左键抬起事件,在鼠标抬起事件中使用ReleaseMouse来释放之前捕获的鼠标。
4、处理EVT_MOUSE_CAPTURE_LOST(func)事件,在其中释放鼠标捕获。官方文档有说明,对鼠标进行捕获必须处理该事件,并在其中释放鼠标捕获。因为弹出对话框等情况会导致鼠标是按下的,但是父窗口却失去了鼠标焦点的状况,所以必须处理该事件释放鼠标。
下面给出我自己实现的一个可以通过鼠标拖拽实现移动的无标题栏窗口的代码,可以对照上边的介绍看一下具体的实现。这个类实现的是拖动自己,当然可以利用在计算坐标之后获取父窗口来进行移动,那样就可以实现鼠标在子窗口上拖动来实现整个窗口的移动。也就是自定义的标题栏应该具有的基本功能。
头文件:MyTitleWnd.h
#pragma once #include <wx/wx.h> class MyTitleWnd:public wxFrame { public: MyTitleWnd(wxWindow *parent,wxWindowID id=wxID_ANY); virtual ~MyTitleWnd(); void OnMouseMove(wxMouseEvent& event); void OnMouseLeave(wxMouseEvent& event); void OnMouseLDown(wxMouseEvent& event); void OnMouseLUp(wxMouseEvent& event); void OnMouseCaptureLost(wxMouseCaptureLostEvent& event); private: wxPoint mLastPt; wxString mText; DECLARE_EVENT_TABLE() };
源文件:MyTitleWnd.cpp
#include "MyTitleWnd.h" BEGIN_EVENT_TABLE(MyTitleWnd, wxFrame) EVT_MOUSE_CAPTURE_LOST(MyTitleWnd::OnMouseCaptureLost) //EVT_LEFT_DOWN(MyTitleWnd::OnMouseLDown) EVT_LEFT_UP(MyTitleWnd::OnMouseLUp) EVT_MOUSE_EVENTS(MyTitleWnd::OnMouseMove) EVT_LEAVE_WINDOW(MyTitleWnd::OnMouseLeave) END_EVENT_TABLE() MyTitleWnd::MyTitleWnd(wxWindow *parent, wxWindowID id/*=wxID_ANY*/) :wxFrame(parent, id,"", wxDefaultPosition, wxDefaultSize, wxBORDER_NONE) { } MyTitleWnd::~MyTitleWnd() { } void MyTitleWnd::OnMouseMove(wxMouseEvent &event) { if(event.LeftIsDown()&&event.Dragging()) { wxPoint pt = event.GetPosition(); wxPoint wndLeftTopPt = GetPosition(); int distanceX = pt.x - mLastPt.x; int distanceY = pt.y - mLastPt.y; wxPoint desPt; desPt.x = distanceX + wndLeftTopPt.x; desPt.y = distanceY + wndLeftTopPt.y; this->Move(desPt); } if (event.LeftDown()) { this->CaptureMouse(); mLastPt = event.GetPosition(); } } void MyTitleWnd::OnMouseLeave(wxMouseEvent& event) { if (event.LeftIsDown() && event.Dragging()) { wxPoint pt = event.GetPosition(); wxPoint wndLeftTopPt = GetPosition(); int distanceX = pt.x - mLastPt.x; int distanceY = pt.y - mLastPt.y; wxPoint desPt; desPt.x = distanceX + wndLeftTopPt.x; desPt.y = distanceY + wndLeftTopPt.y; this->Move(desPt); } } void MyTitleWnd::OnMouseLDown(wxMouseEvent& event) { this->CaptureMouse(); } void MyTitleWnd::OnMouseLUp(wxMouseEvent& event) { if (HasCapture()) ReleaseMouse(); } void MyTitleWnd::OnMouseCaptureLost(wxMouseCaptureLostEvent& event) { if (HasCapture()) ReleaseMouse(); }
好了,最后贴出效果图。
加载全部内容