我正试图在遗留代码中模拟CView
窗口上的鼠标点击,我必须说我不完全理解。我们的想法是在CView
中搜索特定项目,获取其坐标,然后使用SendInput
模拟鼠标右键单击。我想了解我所遵循的基本步骤是否正确,然后再继续深入研究遗留代码,遗留代码在协调系统中发生了一系列转换:(以下是我遵循的步骤:
获取CView
中显示的项目的位置坐标。此时,坐标位于内部坐标系中(我们称之为CDPoint
)。
CDPoint gPosn = viewObj->m_point_a ;
使用代码中的现有转换将坐标转换为客户端坐标系统,即CDPoint转换为CPoint。
CPoint newPosn = GetTransform().Scale(gPosn);
//注意:到达这是正确使用的转换的基础是下面的代码,在鼠标单击处理程序代码中发生了精确的反向转换,以将CPoint
转换为CDPoint
:< / p>
`CDesignView::OnLButtonDown(UINT nFlags, CPoint p) {
CDPoint np = GetTransform().DeScale(p);
}`
这种想法是正确的,在OnLButtonDown()处理程序中收到的CPoint将始终在客户端坐标中,因此反向转换应该将CDPoint(内部坐标)转换为客户端坐标(CPoint)吗?
将客户坐标转换为屏幕坐标:
ClientToScreen(&newPosn);
转换为像素坐标后,将这些值传递给SendInput
函数:
INPUT buffer[1];
MouseSetup(buffer);
MouseMoveAbsolute(buffer, newPos.x, newPos.y);
MouseClick(buffer);
Mousexxx()函数定义如下,类似于这篇文章中的示例代码: How to simulate a mouse movement
#define SCREEN_WIDTH (::GetSystemMetrics( SM_CXSCREEN )-1)
#define SCREEN_HEIGHT (::GetSystemMetrics( SM_CYSCREEN )-1)
static void inline makeAbsXY(double &x, double &y) {
x = (x * 0xFFFF) / SCREEN_WIDTH ;
y = (y * 0xFFFF) / SCREEN_HEIGHT ;
}
static void inline MouseSetup(INPUT *buffer)
{
buffer->type = INPUT_MOUSE;
buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
buffer->mi.mouseData = 0;
buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
buffer->mi.time = 0;
buffer->mi.dwExtraInfo = 0;
}
static void inline MouseMoveAbsolute(INPUT *buffer, double x, double y)
{
makeAbsXY(x,y) ;
buffer->mi.dx = x ;
buffer->mi.dy = y ;
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);
SendInput(1, buffer, sizeof(INPUT));
}
static void inline MouseClick(INPUT *buffer)
{
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTDOWN);
SendInput(1, buffer, sizeof(INPUT));
Sleep(10);
buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_RIGHTUP);
SendInput(1, buffer, sizeof(INPUT));
}
任何人都可以提供有关这些步骤中可能出错的指示,因为模拟的mosue点击似乎总是向左移动一些因素随着x更大的增加而不断增加。我已经确认gPosn指向(0,0)它总是模拟客户端屏幕右上角的鼠标单击。
感谢您的时间。
答案 0 :(得分:0)
如果您在客户端坐标中有x
和y
,则必须将它们转换为屏幕坐标:
POINT point;
point.x = x;
point.y = y;
::ClientToScreen(m_hWnd, point);
其中m_hWnd
是拥有对象的窗口。 x
和y
相对于此窗口客户区左上角。
假设point.x
和point.y
在屏幕坐标中,SendInput
的其余转换是正确的。您还可以为INPUT
创建SendInput
数组,这将不间断地发送鼠标消息。
INPUT input[3];
for (int i = 0; i < 3; i++)
{
memset(&input[i], 0, sizeof(INPUT));
input[i].type = INPUT_MOUSE;
}
input[0].mi.dx = (point.x * 0xFFFF) / (GetSystemMetrics(SM_CXSCREEN) - 1);
input[0].mi.dy = (point.y * 0xFFFF) / (GetSystemMetrics(SM_CYSCREEN) - 1);
input[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input[1].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
input[2].mi.dwFlags = MOUSEEVENTF_RIGHTUP;
SendInput(3, input, sizeof(INPUT));