我需要以某种方式允许使用右键单击拖动选项移动窗口。我通过一些我不太喜欢但却很有效的代码来做到这一点。
目前我正在捕获WM_NCRBUTTONDOWN消息并设置bool以表示我处于移动模式,在收到WM_NCRBUTTONUP时重置此变量。在移动模式下,我正在检查WMNCMouseMove并自行移动表单。由于跟上快速鼠标移动的速度很慢,我还设置了一个使用GetCursorPos来执行相同操作的计时器。
我最近发现了SwapMouseButton函数,这正是我想要的。但是有一个但是!我需要有条件地交换它,并且只有当用户右键单击窗口的CAPTION区域时才需要。
所以当我收到WM_NCRBUTTONDOWN并在WM_NCRBUTTONUP上重置时,我将鼠标按钮交换。但是,如果WM_NCRBUTTONUP从未重置它,这将适用于后续点击。我认为这是因为点击事件已经发生,所以交换时间较晚,这就是为什么它适用于后续的右键点击,而不是右键点击和拖动导致鼠标交换!
任何人都可以看到解决这个问题的方法。请记住,我需要左键单击功能,关闭,最小化,最大化按钮等。右键单击onyl移动!
请帮助!!!!!
谢谢, 乔
答案 0 :(得分:0)
而不是手动跟踪鼠标或交换按钮,有一种更简单的方法 - 响应WM_NCRBUTTONDOWN
,只需通过向窗口发送特殊的WM_SYSCOMMAND
消息将窗口置于移动模式,然后它将处理拖拽你的所有艰苦工作,例如:
const WPARAM MOUSE_MOVE = SC_MOVE + 2;
case WM_NCRBUTTONDOWN:
{
POINT pt;
GetCursorPos(&pt);
SendMessage(Handle, WM_NCRBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
SendMessage(Handle, WM_SYSCOMMAND, MOUSE_MOVE, MAKELPARAM(pt.x, pt.y));
break;
}
有关详细信息,请参阅Q114593。
更新:我无法让WM_SYSCOMMAND
右键单击(但是在左键单击子控件时效果很好)。我认为操作系统正在进行一些内部处理,这使得无法正常工作。因此,我采用拦截鼠标移动的方法手动移动窗口,使用SetCapture()
而不使用计时器,使其快速鼠标移动正常运行:
bool RightButton_CanMove = false;
bool RightButton_WindowMoved = false;
POINTS LastPoint;
void __fastcall TForm1::WndProc(TMessage &Message)
{
switch( Message.Msg )
{
case WM_NCRBUTTONDOWN:
LastPoint = MAKEPOINTS(Message.LParam);
RightButton_CanMove = true;
RightButton_WindowMoved = false;
SetCapture(Handle);
Message.Result = 0;
return;
case WM_MOUSEMOVE:
if( (Message.WParam & MK_RBUTTON) && (RightButton_CanMove) )
{
POINT CurPoint;
GetCursorPos(&CurPoint);
SetWindowPos(Handle, NULL, Left + (CurPoint.x - LastPoint.x), Top + (CurPoint.y - LastPoint.y), 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
LastPoint.x = CurPoint.x;
LastPoint.y = CurPoint.y;
RightButton_WindowMoved = true;
}
break;
case WM_RBUTTONUP:
if( RightButton_CanMove )
{
RightButton_CanMove = false;
ReleaseCapture();
if( RightButton_WindowMoved )
{
RightButton_WindowMoved = false;
Message.Result = 0;
return;
}
}
break;
}
TForm::WndProc(Message);
}
代码区分右键单击和右键单击操作。如果用户右键单击鼠标而不移动它,则允许默认弹出菜单正常显示。如果用户按住鼠标右键并移动窗口,则当用户释放右键时,不会显示默认弹出窗口。