mouse_event的mousemove移动后发现位置不对

nihongsheng 2016-03-25 11:07:58
不知大家用过mouseevent 中的mousemovement没有,现在发现位置一点都不对。
我想要把一个鼠标移动到一个窗体中心。我是这样做的:
先求得窗体中心坐标:
LPRECT lprect=new RECT();
::GetWindowRect(hVitualGridCtrl,lprect);
int tempy=(int)((lprect->top+lprect->bottom)/2);
int tempx=(int)((lprect->left+lprect->right)/2);

现取得现在鼠标位置:
	LPPOINT lppoint=new POINT();
::GetCursorPos( lppoint);

输出调试们息:
	strTrace.Format("中心x点坐标%d,中心y点坐标%d,鼠标点坐标x%d,鼠标点坐标y %d,x向移动%d,y向移动%d",tempx,tempy,lppo                  int->x,lppoint->y,tempx-(lppoint->x),tempy-(lppoint->y));
cout << (LPCTSTR)strTrace;

鼠标相对移动:
mouse_event(MOUSEEVENTF_MOVE,tempx-(lppoint->x),tempy-(lppoint->y),0,0);


我用了一个显示屏幕鼠标坐标的软件来看现在鼠标X坐标,Y坐村的值
当前中心位置是:743,493,
鼠标当前光标点是:312,335
故鼠标要移动:X向431,Y向158
实际执行上面的mouse_event(MOUSEEVENTF_MOVE,tempx-(lppoint->x),tempy-(lppoint->y),0,0);后,鼠标移动到了(1004,588)点
即X向实际移动:692,253点。
需要移动的距离大约是实际移动距离的0.622(X, Y向都是)

下面是采用鼠标相对移动:
mouse_event(MOUSEEVENTF_MOVE|ABSOLUTE,tempx,tempy,0,0);

鼠标实际移动到了(1625,767)点
这是输出的调试信息拷贝上来的。中心x点坐标742,中心y点坐标493,鼠标点坐标x426,鼠标点坐标y 409,x向移动316,y向移动84


请问各位大师,是什么地方出错
...全文
5781 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
LinSno 2017-03-28
  • 打赏
  • 举报
回复 1
引用 24 楼 zzz3265 的回复:
xx=65535.0/GetSystemMetrics(SM_CXSCREEN)*tempx; 这个算法是对的, 问题是你们的电脑可能开启了鼠标加速, 到控制面板去把这个关掉, 然后看看结果 mouse_event 输入是比较底层的, 由于是模拟, 所以鼠标加速认为你的速度很快, 所以给你加速了 mouse_event 输入的数值越大, 系统认为你的速度越快, 所以加速的也说, 也导致楼上说的一些问题 我用以下的代码一直都没什么问题

BOOL	NSys::InputMouseMove(int x, int y, int z, BOOL bScreenPos)
{
	INPUT		input;
	BOOL		bRetVal;
	int			nScrW, nScrH;

	nScrW = GetSystemMetrics(SM_CXSCREEN);
	nScrH = GetSystemMetrics(SM_CYSCREEN);
	x = (x)*(65536-1)/(nScrW-1);
	y = (y)*(65536-1)/(nScrH-1);
	input.type				= INPUT_MOUSE;
	input.mi.dwExtraInfo	= NULL;
	input.mi.dx				= x;
	input.mi.dy				= y;
	input.mi.mouseData		= z;
	input.mi.time			= 0;
	if(bScreenPos)
		input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
	else
		input.mi.dwFlags = MOUSEEVENTF_MOVE;
	if(z != 0)
		input.mi.dwFlags	|= MOUSEEVENTF_WHEEL;
	else
		input.mi.dwFlags	|= MOUSEEVENTF_MOVE;

	bRetVal = SendInput(1, &input, sizeof(input));
	return bRetVal;
}
为什么这里nScrW nScrH 要减1?@zzz3265
Yofoo 2016-11-19
  • 打赏
  • 举报
回复
xx=65535.0/GetSystemMetrics(SM_CXSCREEN)*tempx; 这个算法是对的, 问题是你们的电脑可能开启了鼠标加速, 到控制面板去把这个关掉, 然后看看结果 mouse_event 输入是比较底层的, 由于是模拟, 所以鼠标加速认为你的速度很快, 所以给你加速了 mouse_event 输入的数值越大, 系统认为你的速度越快, 所以加速的也说, 也导致楼上说的一些问题 我用以下的代码一直都没什么问题

BOOL	NSys::InputMouseMove(int x, int y, int z, BOOL bScreenPos)
{
	INPUT		input;
	BOOL		bRetVal;
	int			nScrW, nScrH;

	nScrW = GetSystemMetrics(SM_CXSCREEN);
	nScrH = GetSystemMetrics(SM_CYSCREEN);
	x = (x)*(65536-1)/(nScrW-1);
	y = (y)*(65536-1)/(nScrH-1);
	input.type				= INPUT_MOUSE;
	input.mi.dwExtraInfo	= NULL;
	input.mi.dx				= x;
	input.mi.dy				= y;
	input.mi.mouseData		= z;
	input.mi.time			= 0;
	if(bScreenPos)
		input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
	else
		input.mi.dwFlags = MOUSEEVENTF_MOVE;
	if(z != 0)
		input.mi.dwFlags	|= MOUSEEVENTF_WHEEL;
	else
		input.mi.dwFlags	|= MOUSEEVENTF_MOVE;

	bRetVal = SendInput(1, &input, sizeof(input));
	return bRetVal;
}
li714644953 2016-11-18
  • 打赏
  • 举报
回复
我也遇到了,这个问题,请问楼主有没有什么解决办法?
  • 打赏
  • 举报
回复
所以我估计,相对移动实际上模拟了作为硬件的真实鼠标的移动?参数越大表示鼠标在鼠标垫上移动的速度越快(或者说瞬间移动的距离越大)?从而在屏幕上引起鼠标图标的位置变化也越大?里面有一个加速度(参数100所得到的比例一定大于参数10所得到的比例),而这个加速度是和电脑的系统设置有关。 我在控制面板里面修改“鼠标指针移动速度”,发现,如果调快,那么上述那些比例就会增加。如果调慢,比例就会减少。最后那个例子,“X要求移动30像素,Y要求移动100像素,实际上X移动了75,Y移动了250。比例2.5。”调快的时候达到4.5,调慢的时候只有0.5。 所以,看来无法直接用这个API的“相对移动”来指定鼠标在屏幕上的精确坐标。
  • 打赏
  • 举报
回复
百度百科“mouse_event”里面这样写: 如果没指定MOUSEEVENTF_ABSOLUTE,dX和dy表示相对于上次鼠标事件产生的位置(即上次报告的位置)的移动。正值表示鼠标向右(或下)移动;负值表示鼠标向左(或上)移动。 鼠标的相对移动服从鼠标速度和加速度等级的设置,一个最终用户用鼠标控制面板应用程序来设置这些值,应用程序用函数SystemParameterslnfo来取得和设置这些值。 在应用加速时系统对指定相对鼠标移动提供了两个测试。如果指定的沿X轴y轴的距离比第一个鼠标阈值大,并且鼠标的加速等级非零,则操作系统将距离加倍。如果指定的沿X轴或y轴的距离比第二个鼠标阈值大,并且鼠标的加速等级为2,则操作系统将从第一个阈测试得来的距离加倍。这样就允许操作系统将指定鼠标沿X轴或y轴的相对位移加到4倍。 一旦应用了加速,系统用期望的鼠标速度换算合成的值。鼠标速度的范围是从1(最慢)到20(最快),并代表基于鼠标移动的距离指示符移动的数量。缺省值是10,表示对鼠标的移动设有附加的修改。
  • 打赏
  • 举报
回复
在VB6里面用这个API也出现这样的问题。如果是绝对移动,那么用65535转换一下就对了, 但如果是相对移动,好像是X和Y要移动的值的绝对值10(像素)以内,是正确的。但是10以上的话,就有一个比例, 而且这个比例还不是固定的。随着参数的变化而引起这个比例变化。 而且,X和Y之间也会互相影响。假如Y不变,而X变化,则Y的比例也会变化。 看网上的资料,好像都采用了setcursorpos来实现的,没有用这个API来做相对移动的。 我电脑上VB运行的情况是:(每次第一次的值好像是混乱的,第二次起基本上稳定。) 比如,X要求移动9像素,Y要求移动-5像素(往上),实际上X移动了9或10,Y移动了-6或-5。比例1.1。 改为:X要求移动30像素,Y要求移动-5像素(往上),实际上X移动了61,Y移动了-10。比例2。 再改:X要求移动30像素,Y要求移动100像素,实际上X移动了75,Y移动了250。比例2.5。 只能确定的是,X和Y轴的比例基本相同。 楼主现在有其他发现吗?
schlafenhamster 2016-03-28
  • 打赏
  • 举报
回复
我这里 是 0.4 左右 (1152;864),而且 还 时大 时小。
nihongsheng 2016-03-28
  • 打赏
  • 举报
回复
所以说用mouse_event(MOUSEEVENTF_MOVE,) 时要小心,其中的dx,dy点不是想象中的像素点。简单的用setcursorpos来代替就行了,这个函数用的是象素点。
schlafenhamster 2016-03-27
  • 打赏
  • 举报
回复
是不是与鼠标的 DPI (CPI)有关 ?
schlafenhamster 2016-03-27
  • 打赏
  • 举报
回复
“A mickey is the amount that a mouse has to move for it to report that it has moved” 到底 多少 , 不知道。
schlafenhamster 2016-03-26
  • 打赏
  • 举报
回复
其实 mouse 的 全屏 范围 是 0-》65535. 测试如下: void CCheckCursorDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default #if 1 #define FULLSCREEN_MOUSE 65535 static int x=0; static int y=3000; mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0); x+=6553;// 大约 10 步 if (x > 65535 ) x=0; #endif } SetTimer(1,3000,0); 从 11 楼 int mx = ptc.x * 65535 / GetSystemMetrics(SM_CXSCREEN);// 7FFF=32767=65535/2 int my = ptc.y * 65535 / GetSystemMetrics(SM_CYSCREEN);// 76D0 可以看出
nihongsheng 2016-03-26
  • 打赏
  • 举报
回复
引用 14 楼 schlafenhamster 的回复:
即 “在鼠标坐标系统中,屏幕在水平和垂直方向上均匀分割成65535×65535个单元”
您大概没看懂我的意思。 我说的是相对移动情况,没有MOUSEEVENTF_ABSOLUTE 在我的例子里 我移动431个象素点,它就移动了692个点,如果你再移动431*65535/1280,它会移动到什么地方? 绝对移动可能是你说的,但根据资料,相对移动的单位是:给出的相对数据作为移动的mickeys数
schlafenhamster 2016-03-26
  • 打赏
  • 举报
回复
即 “在鼠标坐标系统中,屏幕在水平和垂直方向上均匀分割成65535×65535个单元”
nihongsheng 2016-03-25
  • 打赏
  • 举报
回复
好象一直就是这么new新建一个对象用来着。而且我用spy++和鼠标坐标软件来看数值都是对的。 你可查看连接:http://blog.csdn.net/coolszy/article/details/5601455 里面也是这么写的: IntPtr hwnd = FindWindow("", "计算器"); Rect rect = new Rect(); GetWindowRect(hwnd, out lpRect); 显示器设置是1280X768像素。
dustpg 2016-03-25
  • 打赏
  • 举报
回复
1.
LPRECT lprect=new RECT();
::GetWindowRect(hVitualGridCtrl,lprect);
为什么不是
RECT rc = { 0 };
::GetWindowRect(hVitualGridCtrl, &rc);
为什么要new一个 下面的POINT同理 2. 你不说说的显示器的状态么
nihongsheng 2016-03-25
  • 打赏
  • 举报
回复
考查了好长时间,发现相对移动的 mouse_event( MOUSEEVENTF_MOVE, mx, my, 0, 0);//就是没有mouseeventtf_absolute的 其中的mx ,my绝对不是象素位移,而是象素位移乘上一个比例。 这个比例是多少,怎么算出来的,偶不知道,只知道在现在我电脑上是0.622 网上是这么说的: dy:指定鼠标沿y轴的绝对位置或者从上次鼠标事件产生以来移动的数量, 依赖于MOUSEEVENTF_ABSOLUTE的设置。 给出的绝对数据作为鼠标的实际y坐标, 给出的相对数据作为移动的mickeys数。 这个mickey数是怎么从象素换算过来,网上查之不出。请各位大神指点。 偶显示器的分辨率是1280x768,
schlafenhamster 2016-03-25
  • 打赏
  • 举报
回复
移动鼠标到 对话框 中心

void CCheckCursorDlg::OnButton3() 
{
	// TODO: Add your control notification handler code here
	CRect wrc;
	GetWindowRect(wrc);
	CPoint ptc=wrc.CenterPoint();
//	SetCursorPos(ptc.x,ptc.y); //比较这句
	int mx = ptc.x * 65535 / GetSystemMetrics(SM_CXSCREEN);
	int my = ptc.y * 65535 / GetSystemMetrics(SM_CYSCREEN);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, mx, my, 0, 0);
}
// SetCursorPos(ptc.x,ptc.y); //比较这句
kuankuan_qiao 2016-03-25
  • 打赏
  • 举报
回复
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  0,  0, 0, 0);
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535 / 2, 0, 0, 0);
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535 , 0, 0, 0);
	
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535, 65535/2, 0, 0);
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535 , 65535, 0, 0);
	Sleep(1000);

	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535 /2, 65535, 0, 0);
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  0, 65535, 0, 0);
	Sleep(1000);

	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  0 , 65535/2, 0, 0);
	Sleep(1000);
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  65535 /2, 65535/2, 0, 0);
kuankuan_qiao 2016-03-25
  • 打赏
  • 举报
回复
	mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,  0,  0, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535 / 2, 0, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535 , 0, 0, 0);

Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535, 65535/2, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535 , 65535, 0, 0);
Sleep(1000);

mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535 /2, 65535, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0, 65535, 0, 0);
Sleep(1000);

mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 0 , 65535/2, 0, 0);
Sleep(1000);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, 65535 /2, 65535/2, 0, 0);
nihongsheng 2016-03-25
  • 打赏
  • 举报
回复
引用 7 楼 zgl7903 的回复:
[quote=引用 6 楼 nihongsheng 的回复:] [quote=引用 5 楼 zgl7903 的回复:] MSDN 上说明很详细了

  CWnd *pWnd = GetDlgItem(IDC_BUTTON1);
  CRect rcWnd;
  pWnd->GetWindowRect(&rcWnd);

  CPoint ptTgt = rcWnd.CenterPoint(); //目标位置

  //换算到event点
  int mx = ptTgt.x * 65535 / GetSystemMetrics(SM_CXSCREEN);
  int my = ptTgt.y * 65535 / GetSystemMetrics(SM_CYSCREEN);
  mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, mx, my, 0, 0);

这个网上也看到了, 你确认你说的是正确的吗? 我移动431个象素点,它就移动了692个点,如果你再移动431*65535/1280,它会移动到什么地方? 实际上我也试过了,采用相对移动时,它移动到了右下角,鼠标都看不见了 采用绝对移动时,它移动到了左上角,不动鼠标根本都找不到。[/quote] 这个是移动到绝对位置, 和原来的位置无关 [/quote] 后面是这么试过的的: int xx=65535.0/GetSystemMetrics(SM_CXSCREEN)*tempx; int yy=65535.0/GetSystemMetrics(SM_CYSCREEN)*tempy; mouse_event(MOUSEEVENTF_MOVE|ABSOLUTE,xx,yy,0,0); 之所以弄个xx,yy,是想看看它是个什么值。 结果还是不对。它移动到了左上角,不动鼠标根本都找不到。
加载更多回复(5)
今天用vue+原生js的mousemove事件,写了个拖动,发现只能慢慢拖动才行,鼠标只要移动快了,就失效,不能拖动了; 搞了半天在,总算解决了,但是问题的深层原理还没搞清楚,知道的大侠可以留言分享,下面直接上代码: 只能慢速拖动的代码: <!DOCTYPE html> <html> <head> <title>vue结合原生js实现拖动</title> [removed][removed] </head> <body>

16,473

社区成员

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

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

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