正如您从下面的代码片段中看到的,我已经实现了一种通过其客户区拖动Windows命令提示符的方法。使用ReadConsoleInput()拖动控制台窗口
这段代码的问题是,如果用户遵循下列步骤:
- 无焦点控制台窗口
- 焦点控制台窗口通过点击和拖动它(不释放)
- 拖动窗口,以便光标逃离窗口区域(这可能意味着移动光标太快,或超出设置范围(第二个显示器),或通过任务栏/其他永远在顶部的窗口)
控制台窗口将停在光标后面,直到它再次移动到窗口内。
事实上,当控制台窗口在步骤1已经处于对焦状态时,这种情况不会发生,这对我来说真的很奇怪。我已经试过调试了这么多个小时,现在我不能再做了。我会很感激这方面的帮助。
// Continuously read input
while(ReadConsoleInput(hIn, &ir, 1, &nr))
{
switch(ir.EventType)
{
// Left mouse button down that either focuses or unfocuses console window
case FOCUS_EVENT:
// Left mouse button down that focuses console window
if(ir.Event.FocusEvent.bSetFocus)
{
GetCursorPos(&firstPos);
ScreenToClient(hWnd, &firstPos);
}
break;
case MOUSE_EVENT:
// Mouse did something inside console window
switch(ir.Event.MouseEvent.dwButtonState)
{
// Left mouse button down or up
case FROM_LEFT_1ST_BUTTON_PRESSED:
// Left mouse down or up, no drag
if(!ir.Event.MouseEvent.dwEventFlags)
{
GetCursorPos(&firstPos);
ScreenToClient(hWnd, &firstPos);
}
// Left button down, and mouse move. -> drag
if(ir.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
{
GetCursorPos(¤tRelativeToScreen);
// Calculate window position while dragging
// |
// v
if(currentRelativeToScreen.x - firstPos.x > scrnSz.right - ca.right)
wndPos.X = scrnSz.right - ca.right;
else if(currentRelativeToScreen.x - firstPos.x < 0)
wndPos.X = 0;
else
wndPos.X = currentRelativeToScreen.x - firstPos.x;
if(currentRelativeToScreen.y - firstPos.y > scrnSz.bottom - ca.bottom)
wndPos.Y = scrnSz.bottom - ca.bottom;
else if(currentRelativeToScreen.y - firstPos.y < 0)
wndPos.Y = 0;
else
wndPos.Y = currentRelativeToScreen.y - firstPos.y;
// End window position calculations
SetWindowPos(hWnd, 0, wndPos.X, wndPos.Y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
break;
default:
break;
}
break;
default:
break;
}
你怎么又解释说,如果窗口有焦点的整个时间的鼠标事件产生,而光标仍在窗口边界之外?此外,即使这是预期的行为(我怀疑,从UX的角度来看,加上其他窗口的行为并没有这种方式),我仍然有兴趣提供一种方法来规避这种行为。 – user4780006
我编辑了我的答案来覆盖那个部分。不知道有一种解决方法,因为控制台窗口本身是相当特殊的。 – dxiv
很好的编辑,很好的解释。但我仍然在寻找(至少有点)理智的方式......我猜即使在第一次(聚焦)点击时,模拟全局捕获鼠标移动的命令提示符。我假设这会以某种方式手动跟踪鼠标。 – user4780006