使用ReadConsoleInput()拖动控制台窗口
Dragging the console window with ReadConsoleInput()
正如您从下面的代码片段中看到的,我已经实现了一种按客户端区域拖动Windows命令提示符的方法。
此代码的问题在于,如果用户遵循以下步骤:
- 展开控制台窗口
- 单击并拖动焦点控制台窗口(不释放)
- 拖动窗口,使光标脱离窗口区域(这可能意味着光标移动过快,或超出设置的界限(第二个监视器),或越过任务栏/其他始终位于顶部的窗口)
控制台窗口将停止跟随光标,直到它再次移动到窗口内。
事实上,当控制台窗口在步骤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;
}
拖动窗口,使光标退出窗口区域[…]控制台窗口将停止跟随光标,直到光标再次移动到窗口内。
这是预期的行为,如https://msdn.microsoft.com/en-us/library/windows/desktop/ms684239.aspx(强调添加)。
每当用户移动鼠标、按下或释放其中一个鼠标按钮时,都会生成鼠标事件只有当控制台组具有键盘焦点并且光标位于控制台窗口的边界内时,鼠标事件才会被放置在控制台的输入缓冲区中。
[编辑]回答有关此问题的后续评论。
当控制台窗口在步骤1 中已经处于焦点时,这种情况不会发生
虽然从官方文档中看不出来,但控制台窗口在单击鼠标时似乎会捕捉鼠标(因此即使在移动到控制台窗口之外时也会跟踪鼠标),只有在单击时鼠标已经有焦点的情况下才。对于失焦的控制台窗口,第一次单击会使其获得焦点(不全局捕获鼠标,因此当光标在其客户端区域内时,它只接收mouse_MOVE通知),而第二次单击会进入独占捕获模式(无论光标位置如何,都会接收所有mouse_MMOVE通知)。
这可以通过设置为快速编辑模式的标准控制台窗口进行验证。如果窗口具有输入焦点,则单击并拖动可在控制台中选择文本,即使将鼠标移到窗口之外也是如此。但是,如果窗口没有焦点。第一次点击只会使其聚焦,但不会进入任何捕捉模式,拖动也不会选择任何文本。
鼠标移动do:
if(button==leftButton){
ReleaseCapture();
SenMessage(hWnd,WM_NCLBUTTON_DOWN,HTCAPTION,lParam);
}
- Visual Studio 2017 停止工作,并在打开后显示许多控制台窗口
- 如何从 Win32 C++ 应用程序输出到父控制台窗口?
- 如何获取控制台窗口的宽度?
- 在C++中隐藏键盘记录器的控制台窗口
- C++ 如何在 OpenGL 程序中远程调用控制台窗口
- 为什么调试时没有显示控制台窗口
- 有没有办法像动画一样移动控制台窗口?
- 如何在C++中居中输出控制台窗口
- 控制台窗口未在开发C++中打开?即使也有 getch() ?
- QTextEdit 提升为构建控制台窗口
- 如何拒绝一个叫做的过程以写入继承的控制台窗口
- Visual C 关闭文本文件和打开新的控制台窗口
- 有没有办法为使用 Boost 生成的进程创建新的控制台窗口
- C++:显示控制台窗口的输出
- C++:如何在控制台窗口中显示结果
- (C++)控制台窗口保持立即关闭,即使我在Visual Studio中是CTRL + F5
- 如何在调用系统()时隐藏控制台窗口
- 在控制台窗口关闭(在Windows上)上优雅地关闭命令行应用程序
- C++控制台窗口放在前面
- C++/CLI 项目如何在控制台窗口中显示消息