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

MFC实现自定义控件拖拽(附完整源码) 阅读详情

有人问我,怎么才能使对话框上的控件可以通过鼠标来拖动. 他的方法是:
1) 从标准控件类派生新的类.
2) 处理控件的鼠标消息来实现拖动效果.

这样做当然可以实现,但似乎不太符合常规, 且需要对需要可拖动的所有控件进行子类化以便能响

应控件的鼠标消息. 在这里, 我写了一个类,专门用来处理对控件的拖动, 使用该类只需要少许修

改包含需要拖动的控件的对话框,而不需要对控件再做任何其它处理.

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

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

个拖动过程结束.

类 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);
}

MFC无边框对话框实现拖动 解决无标题栏窗口的拖动问题有两种方案,一种方案是使用常规思路来处理鼠标拖拽事件,当窗口获得WM_LBUTTONDOWN(OnLButtonDown)时,通过设置标志并调用CWnd::SetCapture()函数来让当前窗口捕捉鼠标消息,应用程序进入移动模式,此时只要有WM_MOUSEMOVE消息过来,就可以据此移动框架窗口,最后当用户释放鼠标按钮,则WM_LBUTTONUP消息处理例程清除标志并调用CWnd::ReleaseCapture()函数将鼠标控制返还给Windows。 这种方法比较繁琐,首先要决定 阅读详情

相关推荐

实现MFC时间对话框的缩放功能

MFC(Microsoft Foundation Classes)是微软公司提供的一套C++类库,用于简化Windows应用程序的开发。MFC封装了Windows API,并提供了一个面向对象的框架,这使得开发者可以利用面向对象的方法进行软件设计,提高开发效率和程序的可维护性。为了实现全屏显示功能,我们需要定义一个对话框类的成员函数,用来切换应用的显示模式。通常,这涉及到改变窗口的尺寸和位置,使其覆盖整个屏幕,同时隐藏常规的窗口装饰(如标题栏和边框)。// 切换全屏标志// 获取屏幕尺寸。

weixin_42351520的博客 446

mfc中picture control 自定义控件不能响应鼠标问题

mfc定义了picture control 自定义的控件放上去 不能响应鼠标调整区域后,重新调整大小

xxt1988的专栏 2257

MFC实现可拖动的按钮

实现一个可在父窗口中自由拖动的按钮(CMovableButton),并且不允许拖出父窗口(这样就拖不回来了)。

在VC++中实现无标题栏对话框的拖动

其实,有无标题栏无所谓,本文要实现的是点击客户区实现拖动. 目前,很多基于对话框的应用程序中对话框都是不带框架的,也就是说对话框没有标题栏。众所周知,窗口的移动都是通过鼠标拖动窗口的标题栏来实现的,那么现在应用程序中的对话框没有了标题栏,用户如何移动对话框呢?本实例针对这个问题提出解决的办法。程序编译运行后的界面效果如图一所示: 图一、无标题栏的对话框界面 一、实现方...

weixin_30940783的博客 312

MFC~~鼠标拖动控件~

MFC~~鼠标拖动控件~ 可以跟着鼠标走的控件~

[AbutionGraph] 报表制作-使用Grafana动态可视化知识图谱指标

使用开源报表可视化工具Grafana实时监控时序知识图谱数据仓库AbutionGraph中的数据,实时性报表查询, 满足单次百万千万级的数据查询,毫秒级查询延迟,亚秒级对千亿数据量汇总统计,每日过亿报表查询/多维分析/日志分析等数据指标...

图特摩斯科技-博客 4276

MFC对话框分割条拖动控件的实现

本文介绍了在MFC中如何利用分割条动态拖动控件

_Santiago的博客 2460

MATLAB控制信号发生器(USB-GPIB-HS)GPIB仪器控制教程(含matlab代码)

自动化测试时需要自动产生信号,通过matlab控制信号发生器的频率与功率,以实现自动化信号生成输出

qq_43686057的博客 1606

VC++无标题窗口以及控件拖动的方法,MFC中的对话框怎么拖动不了

首先产考 http://bbs.youkuaiyun.com/topics/290051411   无标题窗口拖动: 方法一:直接在OnNcHitTest中虚拟发送HTCAPTION消息 [cpp] view plaincopyprint? UINT CMainFrame::OnNcHitTest(CPoint point)   {   RECT rectWindows,

zhangyulin54321的专栏 1710

FFmpeg音频转换避坑实录:为什么VOS的REC转MP3比WAV转MP3体积小一半?

本文深入解析了FFmpeg在VOS系统REC格式音频转换中的优化技巧,揭示了REC转MP3比WAV转MP3体积小一半的原因。通过分析REC格式的压缩特性、转码参数陷阱及FFmpeg调优方法,帮助开发者实现高效音频转换,显著降低存储成本。

weixin_30752699的博客 526

orangepi 5 plus ubuntu24.04上安装redroid

OrangePi 5 Plus运行reDroid云手机方案总结 在RK3588+Ubuntu 24.04上部署reDroid(Android容器化方案)的关键步骤: 内核要求:确保启用binderfs(无需ashmem,新版reDroid使用memfd替代); 安装流程: 安装Docker并配置代理加速镜像拉取; 拉取reDroid镜像(推荐Android 12/13 ARM64版本); 通过挂载binderfs启动容器,指定分辨率与DPI参数; 多实例管理: 脚本化创建多个容器(如8个实例),分配独立端口

babytiger的专栏 2287

MFC实现拖动或缩放对话框,控件位置大小也随之改变

如果一个对话框中有很多个控件,可以插入一个子对话框,然后将控件放在子对话框中,通过子对话框的坐标来确定控件的位置和大小以减少代码重复量,当然你也可以每个控件像上面代码一样操作。以下代码需要写在OnSize函数中;也可以写在自定义的函数中,然后在OnSize中调用它。

weixin_46098228的博客 1738

2024从零开始使用VSCode编程(静态页面制作篇)HTML+CSS+JS阶段

VSCode第一个前端静态页面的编写

ssrsrrn的博客 9590

mfc 对话框中实现分割窗口 拖拽控件效果--- SplitterCtrl 使用介绍

SplitterCtrl作为父窗口,对界面进行划分, 子窗口或者控件放在指定区域内,管理子窗口或者控件的显示 缩放,拖动等功能。类来实现这种功能,这是一个预定义的控件,专用于创建可分割的窗口。利用已经写好的类,进行设计,gitb上已有实现的类(.h和cpp 文件),可下载进行使用。向分割的单元格位置添加子窗口或者子控件,注意需要提前将子窗口或者子控件的父指针指向 SplitterCtrl对象。**方案一:**要创建一个具有拖动分隔条的对话框,我们需要实现一个自定义的分隔条控件。

枫飘落的博客 1552

Windows 下运行 openclaw 出现“‘openclaw‘ 不是内部或外部命令,也不是可运行的程序或批处理文件“的解决方案

方案适用场景推荐指数检查并手动添加 PATH明确知道全局安装目录,只是没加进PATH⭐⭐⭐⭐⭐pnpm setup 自动配置使用 pnpm 安装,想要省心的自动化方式⭐⭐⭐⭐⭐npx 免安装临时运行快速验证核心程序是否正常,排除法排查⭐⭐⭐⭐清理残留后重装npm/pnpm 混用导致版本混乱⭐⭐⭐⭐改用 WSL2不熟悉 Windows 路径体系,长期使用⭐⭐⭐'openclaw' 不是内部或外部命令这类报错,本质上不是"程序坏了",而是。

一键难忘的博客 1万+

2024年软考信息安全工程师备考历年真题汇总

信息安全工程师分属“信息系统”专业,位处中级资格,2016年下半年,第一次开考信息安全工程师(中级)考试。目前每年考试一次。已开考六次,2016年11月12日,2017年5月20日,2018年5月26日,2019年5月25日,2020年11月7日,2021年11月6日为第六次考试。 第五次和第六次考试,采用第二版教材。 2024年软考信息安全工程师备考历年真题汇总

月梦工作室 5101

MFC开发之各种笔记

1、问题:获取CString长度时使用GetLength获取的都为0 解决办法:在取长度之前用GetBuffer()了 如果用了,就在用后ReleaseBuffer()一下 2、从一个类调用另一个类的函数(函数中有控件操作) 一般的从一个类调用另一个类的函数、变量一般就是:A、B两个类, 在B类中添加就可以 CMyA a; a.变量或者函数; 但如果调用A中的函数有控件操作就会程序错...

金属服务,美好生活,天网改变世界,华帝量子科技。 426

Ubuntu Rtx3090 Cuda11.7 安装 pytorch3d

pytorch ubuntu pytorch3d 安装

G果的博客 2272

MFC Slider控件 去掉边上的虚线

MFC Slider控件 去掉边上的虚线

tangaowen的专栏 3793

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

MFC在鼠标自定义的一定的范围内实现拖动窗口移动、错误:不支持尝试执行的操作、实现进度条颜色的渐变或者背景和前景色的改变

模拟自己设计的窗口上面的客户部分鼠标点击可以实现移动 这部分是MFC的对话框中Border选中None 将对话框的上面一部分设定为客户去,采用下面代码模拟客户区 void CDfuCtrlServiceToolDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 if (m_bIsMo

有塔耶奥多的专栏 1071

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

mfc中调用ocx控件

ocx是有状态的。所以先调用第一步,再调用第二步。要按照顺序来。 可以用来分析ocx的 东西有dllexp 查看导出函数 在vc6 tools里面还有TSTCON32.EXE 可以用于直接 调用ocx的函数。直接填写参数数据就可以。 如果是假如要用MFC的话。 1先创建一个MFC工程 2工程->添加类->MFC->TypeLib中的MFC类 3从以下来源中添加类 选文件->选o

groundhappy的专栏 1438

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

MFC-UI相关

void CclientDlg::OnSize(UINT nType, int cx, int cy) { if (cx == 0 || cy == 0) { return; } CDialog::OnSize(nType, cx, cy); CWnd *pWnd = GetWindow(GW_CHILD); while(pWnd) { CRect rc; pWnd->

naaaa的专栏 553

为对话框添加PNG图片作为背景

(1)新建一个基于对话框的MFC应用程序PNGBackgroundDialogTest,删除对话框中原有控件。 (2)设置对话框的Border属性为none,编译运行,生成Debug目录,把bk.png图片放到Debug目录下。 (3)在CPNGBackgroundDialogTestApp添加获取应用程序路径的函数: //带斜杠 CString CPNGBackgroundDialogTestApp::GetAppPath(void) { CString path=AfxGetApp()->m_p

LV_ZengMengyao的博客 1241

Yuv overlay 显示出现新问题,寻求解决办法!

<br />yuv overlay 时,显示在mfc的picture控件上,然后我拖动对话框,发现yuv overlay的表面有时会拖出picture控件,<br />还有一个问题就是当我将MFC对话框拖出屏幕范围,yuv overlay的表面还是在屏幕的范围内;<br />还有就是当切换到另一个页面的时候,此时对话框看不到,但是yuv overlay的表面还是显示在屏幕上;<br /> <br />我看vlc也是采用yuv overlay ,但是它的播放器,就可以最大最小化,任意拖动;<br /> <br

smilestone322的专栏 1551

Vs2013 用mfc创建的对话框初始大小的变更

mfc创建对话框总是默认那么一小块区域,当控件比较多时就存在放不下的情况。此时我们希望改变对话框的大小和屏幕大小一致。快速的方法是直接拖拉对话框,在Vs2013的右下角会有对话的实际大小,如图 0,0是左上角位置,680*370是对话框的尺寸,但是他的单位却不是像素单位,而是DLU单位。DLU单位与像素单位的换算可以参考博文:https://www.cnblogs.com/yangj...

weixin_42337612的博客 897
上一篇: 固定内存和内存池比较
下一篇: linux arch目录下处理器体系架构介绍
angusing
博客等级 码龄15年 11粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值