如何使MFC对话框上的控件可以拖动

草尖上的舞动 2012-12-19 05:12:40
原理是这样的: 通过预处理发往对话框及其上控件的鼠标消息, 如果发现单击落在某个需要拖动的

控件上, 则启动拖动过程, 跟踪鼠标的运动, 并同时对控件做相应的位置调整. 当鼠标松开后,整

个拖动过程结束.

类 CMoveCtrlHandler 用来控制整个拖动的过程, 源代码如下:


// MoveCtrlHandler.h: interface for the CMoveCtrlHandler class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MOVECTRLHANDLER_H__D2C119F0_5B9B_4759_A8EB_8B71F45402B6__INCLUDED_)
#define AFX_MOVECTRLHANDLER_H__D2C119F0_5B9B_4759_A8EB_8B71F45402B6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxtempl.h>


typedef CArray<HWND, HWND> WndowArray;


// for support move controls in the window
class CMoveCtrlHandler
{
public:
CMoveCtrlHandler();
virtual ~CMoveCtrlHandler();
// set the parent window contained the controls.
void Initialize(HWND hParent);
// add a control to moveable controls array.
void AddCtrl(HWND hCtrl);
// hook the message send to the parent window or contorls.
BOOL HookMessage(MSG* pMsg);
private:
BOOL HookLoop(HWND hCtrl, POINT pt);
void DoMoveCtrl(HWND hCtrl, POINT ptOrig, POINT ptNew);
private:

WndowArray m_hWnds; // a array contained all the moveable controls
HWND m_hParent; // parent window of the contorls.
};

#endif //

!defined(AFX_MOVECTRLHANDLER_H__D2C119F0_5B9B_4759_A8EB_8B71F45402B6__INCLUDED_)





// MoveCtrlHandler.cpp: implementation of the CMoveCtrlHandler class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MoveCtrlHandler.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// find the index of the element from a array
template<class T>
int FindArray(CArray<T, T>& arr, T t)
{
for(int i = 0; i < arr.GetSize(); i++)
{
if(arr.GetAt(i) == t)
return i;
}
return -1;
}

// get the mouse point form a message structure.
static POINT MakeMessagePoint(const MSG* pMsg)
{
POINT pt;
pt.x = (long)(short)LOWORD(pMsg->lParam);
pt.y = (long)(short)HIWORD(pMsg->lParam);
return pt;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMoveCtrlHandler::CMoveCtrlHandler()
{
m_hParent = NULL;
}

CMoveCtrlHandler::~CMoveCtrlHandler()
{

}


void CMoveCtrlHandler::Initialize(HWND hParent)
{
ASSERT(hParent != NULL);
m_hParent = hParent;
}

void CMoveCtrlHandler::AddCtrl(HWND hCtrl)
{
ASSERT(hCtrl != NULL);
int id = FindArray(m_hWnds, hCtrl);
if(id >= 0) return;

m_hWnds.Add(hCtrl);
}

BOOL CMoveCtrlHandler::HookMessage(MSG* pMsg)
{
// drag process started when right click a contorl that contained in array.
if(pMsg->message != WM_RBUTTONDOWN)
return FALSE;

int id = FindArray(m_hWnds, pMsg->hwnd);
if(id < 0) return FALSE;

// capture the mouse point
SetCapture(m_hParent);

POINT pt = MakeMessagePoint(pMsg);
// mapping the point to parent window
MapWindowPoints(m_hWnds[id], m_hParent, &pt, 1);

// into dragging loop
if(!HookLoop(m_hWnds[id], pt))
{
return FALSE;
}

return TRUE;
}

BOOL CMoveCtrlHandler::HookLoop(HWND hCtrl, POINT pt)
{
POINT point = pt;
MSG msg;
POINT ptNew;
BOOL bDrag = FALSE;

while(GetMessage(&msg, NULL, 0, 0))
{
switch(msg.message)
{
case WM_RBUTTONDOWN:
break;
case WM_MOUSEMOVE:
// dragging the control.
ptNew = MakeMessagePoint(&msg);
if(msg.hwnd != m_hParent)
MapWindowPoints(msg.hwnd, m_hParent, &ptNew, 1);
if(ptNew.x != point.x || ptNew.y != point.y)
{
DoMoveCtrl(hCtrl, point, ptNew);
point = ptNew;
bDrag = TRUE;
}
break;
case WM_RBUTTONUP:
// leave the dragging mode.
ReleaseCapture();
// if the control isn't dragged. do default act and return
return bDrag;
default:
// process the other message
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
return bDrag;
}

void CMoveCtrlHandler::DoMoveCtrl(HWND hCtrl, POINT ptOrig, POINT ptNew)
{
RECT rc;

// get the rectangle of the control
GetWindowRect(hCtrl, &rc);
ScreenToClient(m_hParent, (LPPOINT)&rc.left);
ScreenToClient(m_hParent, (LPPOINT)&rc.right);

// calculate the new rectangle of the control.
OffsetRect(&rc, ptNew.x - ptOrig.x, ptNew.y - ptOrig.y);
MoveWindow(hCtrl, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,

TRUE);
}


按如下步骤为你的对话框添加控件可拖动的功能:
1) 在对话框类声明一个CMoveCtrlHandler 成员对象.
class CMoveCtrlDlg : public CDialog
{
...
// support to move controls in the dialog.
CMoveCtrlHandler m_movectrl;
...
};

2) 对话框初始化消息内添加初始化拖动控件代码并将需要拖动的控件添加到控制列表:
BOOL CMoveCtrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
...

// Set the parent window of moveable controls.
m_movectrl.Initialize(*this);
// make the contorl IDC_STATIC_1 to be moveable,
// make sure the static has SS_NOTIFY style and its ID cannot be

IDC_STATIC.
m_movectrl.AddCtrl(*GetDlgItem(IDC_STATIC_1));
// make the OK button to be moveable
m_movectrl.AddCtrl(*GetDlgItem(IDOK));

// make the edit box to be moveable
m_movectrl.AddCtrl(*GetDlgItem(IDC_EDIT1));

return TRUE; // return TRUE unless you set the focus to a control
}

3) 添加虚函数PreTranslateMessage 的超越:
BOOL CMoveCtrlDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
m_movectrl.HookMessage(pMsg);

return CDialog::PreTranslateMessage(pMsg);
}


以上代码是从网上找到的,运行完还是不能移动啊,求高手
...全文
3459 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
DS小馒头 2014-10-20
  • 打赏
  • 举报
回复
我的也不能动,而且运行时会提示有中断
hust_wangyajun 2014-08-29
  • 打赏
  • 举报
回复
在对话框初始化中添加代码:m_movectrl.Initialize(m_hWnd);
u011914415 2013-09-27
  • 打赏
  • 举报
回复
很不巧,最近也用到了这样的功能,我的参考地址: http://blog.sina.com.cn/s/blog_7bddd8530100zxp9.html 看你的源码跟我的一样,我的完全能动啊

1,146

社区成员

发帖
与我相关
我的任务
社区描述
探讨BlackBerry智能手机开发相关的技术、软件、产品等话题。
社区管理员
  • BlackBerry
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧