控件拖拽(立即结分)

illocal 2005-08-22 09:23:05
基于对话框的MFC程序中,
有一组自定义的CStatic控件,数量50个

如何用鼠标实现拖拽功能?
就是,在某个控件上,鼠标左键按下,可以拖着这个控件移动,左键弹起,就放在新位置了.
所有控件可以分别拖拽.
...全文
607 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
RunningYang 2005-08-22
  • 打赏
  • 举报
回复
原理是《Windows下的c/c++高级编程》里面所谓的消息钩子

实现问题:
通过为子窗体附加消息处理过程的方法实现子窗体的消息预处理

未解决问题:
为窗体增加消息钩子的方法可不可以跨进程来做?
RunningYang 2005-08-22
  • 打赏
  • 举报
回复
我试着做了下
还有点收获

:)

需要的话我可以把工程放到空间上


//新的消息处理函数,主要用于处理其中的鼠标事件
LRESULT CALLBACK NewProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp);
//CStatic控件原来的消息处理函数,重要的参数,不要丢失!
WNDPROC OldSSProc;
//当前选中的子窗体
HWND g_hCurWnd;
//事件的状态:
//-1:鼠标移动事件处在无效状态
//0:鼠标移动事件处在就绪状态,有一个MouseUp事件就可以激发
int g_iMStatus;
//鼠标按下的时候,指针对屏幕的坐标
POINT g_p1;
//鼠标松开的时候,指针对屏幕的坐标
POINT g_p2;
//全局变量,主要用于调用其中的移动子窗体的函数
CTestDrawComsDlg* g_dlg;


//新的消息处理函数,主要用于处理其中的鼠标事件
LRESULT CALLBACK NewProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp)
{
if(message==WM_LBUTTONDOWN)
{
g_hCurWnd=hwnd;
g_iMStatus=0;
g_p1.x=LOWORD(lp);
g_p1.y=HIWORD(lp);
::ClientToScreen(hwnd,&g_p1);
}
else if(message==WM_LBUTTONUP)
{
g_hCurWnd=hwnd;
g_iMStatus=-1;
g_p2.x=LOWORD(lp);
g_p2.y=HIWORD(lp);
::ClientToScreen(hwnd,&g_p2);
g_dlg->MoveCldWnd(hwnd,g_p2.x-g_p1.x,g_p2.y-g_p1.y);
}
else
CallWindowProc(OldSSProc,hwnd,message,wp,lp);
return 1;
}

BOOL CTestDrawComsDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

//初始化全局变量,动态创建子窗体
g_dlg=this;
int i;
g_iMStatus=-1;
CString strTemp;
for(i=0;i<10;i++)
{
strTemp.Format("static %d",i);
this->m_statics[i]=new CStatic;
this->m_statics[i]->Create(strTemp,WS_BORDER|WS_CHILD|WS_VISIBLE,CRect(i*2+0,0,i*2+100,i*3+150),this);
//设置新的消息处理函数,并且保存原来处理函数的指针
//原理:在该区域中,所有相同窗口类的消息处理函数其实只有一个。
//因此只需要一次赋值就可以了,此处简化过程,采用了循环赋值
OldSSProc=(WNDPROC)::SetWindowLong(this->m_statics[i]->m_hWnd,GWL_WNDPROC,(LPARAM)NewProc);
this->m_statics[i]->SetWindowPos(&CWnd::wndNoTopMost,0,0,i*2,i*3,SWP_NOOWNERZORDER);
}

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

void CTestDrawComsDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.

void CTestDrawComsDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}

// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestDrawComsDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

void CTestDrawComsDlg::OnOK()
{
// TODO: Add extra validation here

CDialog::OnOK();
}

void CTestDrawComsDlg::MoveCldWnd(HWND hCldWnd, int offSetx, int offSety)
{
//移动子窗体
RECT rect;
::GetWindowRect(hCldWnd,&rect);
this->ScreenToClient(&rect);
::MapDialogRect(hCldWnd,&rect);
::OffsetRect(&rect,offSetx,offSety);
::MoveWindow(hCldWnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,true);
::UpdateWindow(hCldWnd);
}

void CTestDrawComsDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
//如果需要移动子窗体
if(g_iMStatus==0)
{
//复位
g_iMStatus=-1;
this->ScreenToClient(&g_p1);
MoveCldWnd(g_hCurWnd,point.x-g_p1.x,point.y-g_p1.y);
}

CDialog::OnLButtonUp(nFlags, point);
}

void CTestDrawComsDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
//在父窗体上的MouseDown不需要处理,复位
g_iMStatus=-1;
CDialog::OnLButtonDown(nFlags, point);
}
illocal 2005-08-22
  • 打赏
  • 举报
回复
楼上的,怎么判断消息?谢谢
pomelowu 2005-08-22
  • 打赏
  • 举报
回复
classwizzard中有添加PreTranslateMessage的办法,然后判断消息。
illocal 2005-08-22
  • 打赏
  • 举报
回复
请问,如何"放到PreTranslateMessage中映射"
wenkui 2005-08-22
  • 打赏
  • 举报
回复
在控件自身加消息处理不就行了吗?在父窗口做反而麻烦
illocal 2005-08-22
  • 打赏
  • 举报
回复
up
illocal 2005-08-22
  • 打赏
  • 举报
回复
我这样做的

ON_CONTROL_RANGE(WM_LBUTTONDOWN, IDC_STC_STDINFO_FIRST, IDC_STC_STDINFO_LAST,OnStcLButtonDown)

void CTest::OnStcLButtonDown(UINT nID)
{
MessageBox(_T("123"));
}

但是左键压下OnStcLButtonDown无响应
pomelowu 2005-08-22
  • 打赏
  • 举报
回复
横秋说的是处理父窗口的消息,所以不用每一个控件写消息映射。
至于如何判断选中的是哪一个控件,WM_LBUTTONDOWN消息的参数里有坐标的,你只需要判断在那些控件上,并且判断Zorder即可。
illocal 2005-08-22
  • 打赏
  • 举报
回复
具体怎么做呢?
everandforever 2005-08-22
  • 打赏
  • 举报
回复
先从CSTATIC派生一个提供拖动功能的类,比如CSTATIC1,
然后你其它的控件都从这个类派生,不就都有拖动功能了吗
illocal 2005-08-22
  • 打赏
  • 举报
回复
问题是有一组一样的控件啊
不能为每一个都写一个映射啊?
如果区别我点的是哪个控件呢?
vcmute 2005-08-22
  • 打赏
  • 举报
回复
OnLButtonDown中SetCapture
OnMouseMove中GetFocus()->MoveWindow
OnLButtonUp中ReleaseCapture
如果是对话框,放到PreTranslateMessage中映射
对应的消息为WM_LBUTTONDOWN WM_MOUSEMOVE WM_LBUTTONUP
RunningYang 2005-08-22
  • 打赏
  • 举报
回复
已经发过了
想研究的朋友可以到这里下

http://www.zhuansou.com/download/
工程文件压缩包地址:
http://www.zhuansou.com/download/TestDrawComs.rar
illocal 2005-08-22
  • 打赏
  • 举报
回复
楼上的,给我发一份代码吧,谢谢

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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