提问人:JimPapas 提问时间:7/9/2023 最后编辑:AmigoJackJimPapas 更新时间:7/10/2023 访问量:245
在 Delphi 中用鼠标右键单击移动无边框表单
Move borderless form with right mouse button in Delphi
问:
我从互联网上有这个代码,可以通过按住鼠标按钮来拖动无边框表单:Left
procedure TForm6.Image1MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState;X,Y: Integer);
const
SC_DRAGMOVE = $F012;
begin
if Button = mbLeft then
begin
ReleaseCapture;
Perform(WM_SYSCOMMAND, SC_DRAGMOVE, 0);
end;
end;
它工作正常,但我需要用鼠标按钮拖动。为此必须更改哪个参数?Right
答:
0赞
dwrbudr
7/9/2023
#1
这可以通过另一种方式完成。
在界面部分:
TMyForm = class(TForm)
private
procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
end;
在实施部分:
procedure TMyForm.WMNCHitTest(var Msg: TWMNCHitTest);
begin
inherited;
Msg.Result := HTCAPTION;
end;
评论
2赞
Uwe Raabe
7/9/2023
这确实可以按照要求使用鼠标右键吗?
0赞
Remy Lebeau
7/9/2023
@UweRaabe 我对此表示怀疑(但尚未测试过),因为通常不会出于拖动目的跟踪右按钮
0赞
JimPapas
7/10/2023
如果鼠标放在另一个组件上,则它不适用于左键或右键。只有当我击中表单的区域时,它才有效。并且只有左按钮。
1赞
AmigoJack
7/10/2023
#2
如何使用C++通过鼠标右键单击移动窗口?有一个解决方案可以处理拖动本身,而不是让 Windows 来做。从 MFC 预测工作需要知道 Delphi 的 Forms 已经处理了什么,而不是过度调用 WinApi 函数。
一个主要问题是合并窗口的标题高度,这可能取决于多种因素。在我的示例中,我为一个相当大的窗口使用了一个普通的窗口,它使用没有任何主题的 Windows 7(看起来像 Windows 95)按预期工作。没有标题,或者有工具窗口,或者没有边框,或者有一个无法调整大小的窗口,需要调整对 GetSystemMetrics()
的调用。
我合并了两者:用鼠标左键和鼠标右键拖动。尽管我仍然鼓励在拖动结束时显示一个潜在的上下文菜单(就像资源管理器在拖动文件时所做的那样),因为它仍然是一个鼠标右键,并且每个用户都希望该单击有一个弹出菜单。
我的示例也适用于两者:绑定到 a 或 本身。TWinControl
TForm
unit Unit1;
interface
uses
Windows, Messages, Classes, Controls, Forms, ExtCtrls;
const
SC_DRAGMOVE= SC_MOVE or $0002; // The four low-order bits of the wParam parameter are used internally by the system
SM_CXPADDEDBORDER= 92;
type
TForm1= class( TForm )
Panel1: TPanel;
procedure Panel1MouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
procedure FormMouseMove( Sender: TObject; Shift: TShiftState; X, Y: Integer );
procedure FormMouseUp( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
private
vStart: TPoint;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// Mouse button is pressed down and held
procedure TForm1.Panel1MouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
case Button of
mbLeft: begin // Dragging through left mouse button
ReleaseCapture(); // Restore normal mouse input processing; self.MouseCapture is already FALSE at this point
self.Perform( WM_SYSCOMMAND, SC_DRAGMOVE, 0 ); // Handles all the rest of dragging the window
end;
mbRight: begin // Through right mouse button
GetCursorPos( self.vStart ); // Remember position on form, relative to screen
self.vStart:= self.ScreenToClient( self.vStart );
Inc( self.vStart.Y, GetSystemMetrics( SM_CYCAPTION ) // Window title height
+ GetSystemMetrics( SM_CXPADDEDBORDER ) // Width of potential border padding
+ GetSystemMetrics( SM_CYSIZEFRAME ) // Height of a potential window border when sizable; SM_CYEDGE is not enough
);
self.MouseCapture:= TRUE; // WinApi: SetCapture( Handle )
end;
end;
end;
// Mouse is moved, unrelated to button status; must be handled by form, not panel
procedure TForm1.FormMouseMove( Sender: TObject; Shift: TShiftState; X, Y: Integer );
var
pt: TPoint;
begin
if self.MouseCapture then begin // WinApi: GetCapture()= Handle
GetCursorPos( pt ); // Position on desktop
Dec( pt.X, self.vStart.X ); // Subtract relative starting position
Dec( pt.Y, self.vStart.Y );
MoveWindow( self.Handle, pt.X, pt.Y, self.Width, self.Height, TRUE ); // Reposition window by horizontal and vertical deltas
end;
end;
// Mouse button is released; must be handled by form, not panel
procedure TForm1.FormMouseUp( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
if Button= mbRight then self.MouseCapture:= FALSE; // End dragging
end;
请注意,启动拖动绑定到控件的事件,但处理和结束拖动必须绑定到窗体的事件:OnMouseDown
object Form1: TForm1
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
object Panel1: TPanel
OnMouseDown = Panel1MouseDown
end
end
评论
0赞
JimPapas
7/10/2023
是的!这就是我需要的。我支持您的解决方案,但我不知道如何标记为已接受。
0赞
AmigoJack
7/10/2023
阅读 当有人回答我的问题时,我该怎么办? 以及 接受答案如何运作? 关于如何单击 ✅︎ 复选标记。通过你的其他问题,也接受那里的答案。你在一月份就已经做到了,但又忘记了......?
0赞
JimPapas
7/10/2023
我忘了!我是一个狂热的周末爱好者,也是一个老人,所以请耐心等待我的错误。再次感谢。
评论
mbLeft
mbRight
SC_DRAGMOVE