除了手动跟踪鼠标或交换按钮之外,还有一种更简单的方法 - 作为响应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);
}
该代码区分了右键单击和右键移动操作。如果用户右键单击鼠标而不移动鼠标,则允许默认弹出菜单正常出现。如果用户按住鼠标右键并四处移动窗口,则当用户释放右键时不会显示默认弹出窗口。