高DPI缩放,鼠标挂钩和WindowFromPoint

时间:2016-09-24 14:41:12

标签: c++ windows winapi dpi setwindowshookex

我有一个设置SetWindowsHookEx(WH_MOUSE_LL ,,,)右键单击钩子的进程。我的进程设置为在窗口10.0.10586上识别DPI系统,在两个监视器上以150%的比例缩放。这是通过调用SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE)来设置的。

我的问题场景是Office 2007是DPI不知道的,所以让我们将MS Word放在屏幕的右边四分之一处。右键单击右下方任务栏上方,鼠标钩子发送坐标1279,675 - 缩放到Word。然后我右键单击视觉工作室(DPI识别),屏幕上几乎四分之三,鼠标钩子发送我的坐标,例如,来自Visual Studio的1279,1008。因此,如果我在屏幕上方点击更高,我可能会得到相同的1279,675。

我的过程是通过调用WindowFromPoint API来尝试确定哪个窗口就在这一点上,但在这种情况下,这显然会失败,因为两个应用程序" share"同一点。

是否可以强制鼠标挂钩始终发送原始物理坐标而不是那些缩放到DPI无意识应用程序的坐标?如果是的话,怎么样?或者,是否有其他方法可以从鼠标钩子中确定hWnd或processID?

2 个答案:

答案 0 :(得分:0)

Microsoft在10.0.14393中修复了它。

除非在LTSB 10.0.10240上,否则您的客户网络中应该没有任何内容,只有较低的内部版本号。

这是解决方案:DPI aware screen capture

答案 1 :(得分:-1)

由于该进程可识别DPI,因此在鼠标钩子回调处理程序中调用GetCursorPos()始终会获取原始物理坐标,而不是缩放到应用程序的逻辑坐标。只需丢弃传递给鼠标回调的坐标。

已于2016年9月30日添加

值得一提的是,虽然GetMessagePos似乎很可能,但如果进程不是dpi虚拟化,它只会返回正确的坐标。

e.g。

VOID MessagePump()
{
    MSG     messageGet = { 0 };
    DWORD   dwPos;
    POINTS  p;

    while (GetMessage(&messageGet,NULL,0,0)) 
    {
        dwPos = GetMessagePos();
        p = MAKEPOINTS( dwPos );
        TranslateMessage( &messageGet );
        DispatchMessage( &messageGet );
    }
}

在GetMessage()调用期间调用Mouse回调处理程序,但是这不会获取正确的物理坐标,其中DPI虚拟化对于进程是活动的。例如物理x = 1909,y = 1072返回1091,612,缩放率为175%,虽然算术上是正确的,但并不是所需要的。