在 Delphi 中用鼠标右键移动无边框窗体

0tdrvxhp  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(119)

我从互联网上找到了这样的代码,通过按住鼠标左键拖动无边框表单:

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;

字符串
它工作正常,但我需要拖动鼠标右键。为此必须更改哪个参数?

hjzp0vay

hjzp0vay1#

How to move window by right mouse button using C++?有一个解决方案,可以自行处理拖动,而不是让Windows来做。要从MFC中预测这些工作,需要知道 Delphi 的Forms已经处理了什么,而不是过度调用WinApi函数。
一个主要问题是合并窗口的标题高度,这可能依赖于多个因素。在我的例子中,我使用了一个普通的窗口,它在Windows 7中没有任何主题(看起来像Windows 95)。没有标题、工具窗口、没有边框、窗口大小不能调整,需要调整GetSystemMetrics()的调用。
我将两者合并:通过鼠标左键和鼠标右键拖动。虽然我鼓励在拖动结束时仍然显示一个潜在的上下文菜单(如Explorer does so for dragging files),因为它仍然是一个鼠标右键,每个用户都希望单击时出现一个弹出菜单。
我的例子也适用于两者:绑定到TWinControlTForm本身。

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

chhkpiq4

chhkpiq42#

这可以用另一种方式来完成。
在接口部分:

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;

相关问题