フチなしフォームを移動可能にしますか?


109

境界線があるかのように、フォーム上でマウスをクリックすると、境界線のないフォーム(FormBorderStyleが "none"に設定されている)を移動可能にする方法はありますか?

回答:


252

CodeProjectに関するこの記事では、手法について詳しく説明しています。基本的に要約すると:

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();

private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{     
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
    }
}

これは基本的に、ウィンドウマネージャーの観点から、ウィンドウのタイトルバーを取得することとまったく同じです。


これは私にはまったく効果がありません。コードは問題なく実行され、すべてが正しく、ウィンドウはまだそこにあります。何か案は?
dbrree

8
@dbrreeおそらくForm1_MouseDown、実際のMouseDownイベントに割り当てられていないため、機能しないコードをコピーしましたForm1
Remon Ramy 2017年

2
ドラッグしてフォームをつかんでいるラベルまたはアイコン(または他の前景オブジェクト!)がある場合は、これらのアイテムにもmousedownイベントを追加します。フォームイベントは、フォームオブジェクトを通しては見えません。
ポールネルソン

1
フォームthis.MouseDown += ...Main()関数に追加する必要があります
Richard Peck

1
私の魅力のように働いた!!!! イベント処理をフォームの代わりに配置していたパネルに移動する必要がありましたが、機能しました
Justin

54

物事を必要以上に難しくしないようにしましょう。フォーム(または別のコントロール)をドラッグできるコードスニペットをたくさん見つけました。そしてそれらの多くは、独自の欠点/副作用があります。特に、Windowsをだましてフォーム上のコントロールを実際のフォームであると思わせるようなものです。

そうは言っても、これが私のスニペットです。いつも使っています。また、this.Invalidate();は使用しないでください。フォームがちらつく場合があるので、他の人がやりたいように。そして、場合によってはこれも行います。this.Updateを使用して、ちらつきの問題は発生していません。

private bool mouseDown;
private Point lastLocation;

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if(mouseDown)
        {
            this.Location = new Point(
                (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

            this.Update();
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }

1
dang winforms ...この回答を2時間近く探しました。
PrinceOfRavens 2015

これは私が考えていた方法とまったく同じです。私の唯一の問題は、あなたがそれをどのように行ったかを読むまで、それは地獄のようにバグが多いことでした。ありがとうメイト
EasyBB

これは、オーバーライドWndProcの上の驚くべき小さなスニペットよりも私にとってはうまくいきました。WndProcは機能しました。他のものが機能しなくなっただけです。ありがとう!
うーん2016年

WndProcに依存せず、うまく機能するため、おそらくここで最良のオプションです(Monoを使用して他のプラットフォームに簡単に移植できます)。Y <10の場合、状態を最大化/通常に変更することで改善できます
Sylverdrag '20

モノでは機能せず、.net 4.5.2をモノ/ネット4.5に変更しても機能しません。今すぐ解決策を見つけようとしています。
ロジャーディープ

35

同じことを行う別の簡単な方法。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        // set this.FormBorderStyle to None here if needed
        // if set to none, make sure you have a way to close the form!
    }
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_NCHITTEST)
            m.Result = (IntPtr)(HT_CAPTION);
    }

    private const int WM_NCHITTEST = 0x84;
    private const int HT_CLIENT = 0x1;
    private const int HT_CAPTION = 0x2;
}

1
特定のツール(ラベルなど)を押してフォームを移動できるようにすることのできる人。
Thomas W

2
ダブルクリックすると、フォームが最大化されます。また、これを右クリックすると機能しなくなることも随時お読みください。
Sebastiano

19

MouseDown、MouseMove、MouseUpを使用します。そのための変数フラグを設定できます。サンプルがありますが、修正する必要があると思います。

マウスのアクションをパネルにコーディングしています。パネルをクリックすると、フォームも一緒に移動します。

//Global variables;
private bool _dragging = false;
private Point _offset;
private Point _start_point=new Point(0,0);


private void panel1_MouseDown(object sender, MouseEventArgs e)
{
   _dragging = true;  // _dragging is your variable flag
   _start_point = new Point(e.X, e.Y);
}

private void panel1_MouseUp(object sender, MouseEventArgs e)
{
   _dragging = false; 
}

private void panel1_MouseMove(object sender, MouseEventArgs e)
{
  if(_dragging)
  {
     Point p = PointToScreen(e.Location);
     Location = new Point(p.X - this._start_point.X,p.Y - this._start_point.Y);     
  }
}

そうです。すでに他の場所で述べたように、これはフォームが依然としてMouseMoveイベントを生成していることに依存しています。単純なケースとして、一番上のピクセル行でフォームをグレーディングして上方向にドラッグするとします。フォームにマウスを戻すとすぐにフォームがジャンプしますが、何も起こりません。
ジョーイ

12

WPFのみ


正確なコードはありませんが、最近のプロジェクトでは、MouseDownイベントを使用して、これを単純に記述しました。

frmBorderless.DragMove();

Window.DragMoveメソッド(MSDN)


2
しかし、それはWPFです。わかりました、OPはこれを正確に指定しませんでした。
ジョーイ

ええ、それは私がやっていたプロジェクトについて忘れていたものです。フォームを見ただけで利用できません。ごめんなさい!
クリス

3
@Chrisこれは、WPFプロジェクトで私に役立ちました。回答を削除しないでいただきありがとうございます。
Rembunator

7

参照 ビデオリンク

これはテスト済みで、理解しやすいです。

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case 0x84:
            base.WndProc(ref m);
            if((int)m.Result == 0x1)
                m.Result = (IntPtr)0x2;
            return;
    }

    base.WndProc(ref m);
}

6
このコードは機能しますが、どのように理解するのは簡単ですか?このコードセグメントには、switchステートメント以外は何もありません。
Jamshaid Kamran 2017

これはWM_NCHITTEST偽装です。
Andreas Rejbrand

4

これを魔法のように起こすために反転できるプロパティはありません。フォームのイベントを見て、それが設定することで、これを実装するために些細ななりthis.Topthis.Left。具体的にはMouseDownMouseUpとを確認する必要がありますMouseMove


これらのイベントを使用する必要があると考えましたが、どうすればよいかわかりません。MouseDownイベントが呼び出されたときに、フォームを移動するにはどうすればよいですか?
ユーザー

1
マウスダウンでフラグを設定し、ベース座標を保存します。マウスの移動時-フラグが設定されている場合-新しいマウス座標のオフセットによって上と左を調整します。マウスを上にすると、フラグをクリアします。
マーフ

それでも、これは、マウスイベントの取得に依存しないWindows APIでかなり簡単に実行できます。たとえば、フォームの最上端にあるピクセルをつかんで上方向にドラッグした場合、このメソッドは失敗します。
ジョーイ

4
public Point mouseLocation;
private void frmInstallDevice_MouseDown(object sender, MouseEventArgs e)
{
  mouseLocation = new Point(-e.X, -e.Y);
}

private void frmInstallDevice_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == MouseButtons.Left)
  {
    Point mousePos = Control.MousePosition;
    mousePos.Offset(mouseLocation.X, mouseLocation.Y);
    Location = mousePos;
  }
}

これはあなたの問題を解決することができます...


Control.MousePositionの代わりに「e.Location」を使用することもできます
Reza Taibur

4

https://social.msdn.microsoft.com/Forums/vstudio/en-US/d803d869-68e6-46ff-9ff1-fabf78d6393c/how-to-make-a-borderless-form-in-c?forum=csharpgeneral

上記のリンクからのこのコードは、私の場合はうまくいきました:)

protected override void OnMouseDown(MouseEventArgs e)  

{
      base.OnMouseDown(e);
      if (e.Button == MouseButtons.Left)
      {
        this.Capture = false;
        Message msg = Message.Create(this.Handle, 0XA1, new IntPtr(2), IntPtr.Zero);
        this.WndProc(ref msg);
      }
}

4

私が見つけた最良の方法(もちろん修正済み)

// This adds the event handler for the control
private void AddDrag(Control Control) { Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DragForm_MouseDown); }
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();

private void DragForm_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
        // Checks if Y = 0, if so maximize the form
        if (this.Location.Y == 0) { this.WindowState = FormWindowState.Maximized; }
    }
}

コントロールにドラッグを適用するには、これをInitializeComponent()の後に挿入するだけです

AddDrag(NameOfControl);

4

それは私のために働いた。

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        _mouseLoc = e.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            int dx = e.Location.X - _mouseLoc.X;
            int dy = e.Location.Y - _mouseLoc.Y;
            this.Location = new Point(this.Location.X + dx, this.Location.Y + dy);
        }
    }

Stack Overflow ツアーへようこそ。回答方法を確認してください。このコードがOPの「元のポスター」の問題をどのように解決するかについての説明を提供する必要があります。それはあなたの答えをチェックする人にとってより役立つでしょう。
Mauricio Arias Olave

2

.NET Framework 4の場合

ドラッグに使用しているコンポーネント(この例ではmainLayout)this.DragMove()MouseDownイベントに使用できます。

private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e)
{
    this.DragMove();
}

2

最も簡単な方法は次のとおりです。

まず、label1という名前のラベルを作成します。label1のイベント>マウスイベント> Label1_Mouse Moveに移動して、次のように記述します。

if (e.Button == MouseButtons.Left){
    Left += e.X;
    Top += e.Y;`
}

2

WPF Element HostコントロールとWPF Userコントロールを含むボーダーレスウィンドウフォームを移動可能にしようとしていました。

結局、WPFユーザーコントロールにStackPanelというスタックパネルがあり、クリックして移動するのは論理的なことのように思えました。マウスをゆっくり動かすとjunmatsのコードを試すことができましたが、マウスを速く動かすと、マウスがフォームから外れ、フォームが移動の途中で動かなくなります。

これにより、CaptureMouseとReleaseCaptureMouseを使用した私の状況に対する彼の回答が改善され、マウスをすばやく動かしても、フォームの移動中にマウスがフォームから移動しなくなりました。

private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
    _start_point = e.GetPosition(this);
    StackPanel.CaptureMouse();
}

private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)
{
    StackPanel.ReleaseMouseCapture();
}

private void StackPanel_MouseMove(object sender, MouseEventArgs e)
{
    if (StackPanel.IsMouseCaptured)
    {
        var p = _form.GetMousePositionWindowsForms();
        _form.Location = new System.Drawing.Point((int)(p.X - this._start_point.X), (int)(p.Y - this._start_point.Y));
    }
}

    //Global variables;
    private Point _start_point = new Point(0, 0);

2

いくつかの回答では、子コントロールをドラッグできないようにするため、小さなヘルパークラスを作成しました。トップレベルのフォームを渡す必要があります。必要に応じて、より汎用的にすることができます。

class MouseDragger
{
    private readonly Form _form;
    private Point _mouseDown;

    protected void OnMouseDown(object sender, MouseEventArgs e)
    {
        _mouseDown = e.Location;
    }

    protected void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            int dx = e.Location.X - _mouseDown.X;
            int dy = e.Location.Y - _mouseDown.Y;
            _form.Location = new Point(_form.Location.X + dx, _form.Location.Y + dy);
        }
    }
    public MouseDragger(Form form)
    {
        _form = form;

        MakeDraggable(_form);            
    }

    private void MakeDraggable(Control control)
    {
        var type = control.GetType();
        if (typeof(Button).IsAssignableFrom(type))
        {
            return;
        }

        control.MouseDown += OnMouseDown;
        control.MouseMove += OnMouseMove;

        foreach (Control child in control.Controls)
        {
            MakeDraggable(child);
        }
    }
}

1

また、DoubleClickを使用してフォームを大きくしたり小さくしたりする必要がある場合は、最初の回答を使用してグローバル整数変数を作成し、ドラッグに使用するコンポーネントをクリックするたびに1を追加します。場合variable == 2は、フォームを大きく/小さくします。また、0.5秒または1秒ごとにタイマーを使用してvariable = 0


1

MainWindowにMouseLeftButtonDownイベントハンドラーを追加すると、うまくいきました。

自動生成されるイベント関数に、以下のコードを追加します。

base.OnMouseLeftButtonDown(e);
this.DragMove();

1

ToolStrip1_MouseLeaveマウスがすばやく移動して領域を離れるイベントを処理するもう1つのメソッドを使用して、jay_t55からソリューションを拡張しています。

private bool mouseDown;
private Point lastLocation;

private void ToolStrip1_MouseDown(object sender, MouseEventArgs e) {
    mouseDown = true;
    lastLocation = e.Location;
}

private void ToolStrip1_MouseMove(object sender, MouseEventArgs e) {
    if (mouseDown) {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

        this.Update();
    }
}

private void ToolStrip1_MouseUp(object sender, MouseEventArgs e) {
    mouseDown = false;
}

private void ToolStrip1_MouseLeave(object sender, EventArgs e) {
    mouseDown = false;
}

0

私は以下を試してみて、changeoを試してみました。透明なウィンドウはもう固定されていませんが、移動できました!! (上記の他の複雑なソリューションはすべて破棄してください...)

   private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        // Begin dragging the window
        this.DragMove();
    }

この回答はWPF向けです。質問はWinFormsについてです。
Ray

0

Form1(): new Moveable(control1, control2, control3);

クラス:

using System;
using System.Windows.Forms;

class Moveable
{
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HT_CAPTION = 0x2;
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
    public static extern bool ReleaseCapture();
    public Moveable(params Control[] controls)
    {
        foreach (var ctrl in controls)
        {
            ctrl.MouseDown += (s, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    ReleaseCapture();
                    SendMessage(ctrl.FindForm().Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                    // Checks if Y = 0, if so maximize the form
                    if (ctrl.FindForm().Location.Y == 0) { ctrl.FindForm().WindowState = FormWindowState.Maximized; }
                }
            };
        }
    }
}

0
   [DllImport("user32.DLL", EntryPoint = "ReleaseCapture")]
    private extern static void ReleaseCapture();

    [DllImport("user32.DLL", EntryPoint = "SendMessage")]
    private extern static void SendMessage(System.IntPtr hWnd, int Msg, int wParam, int lParam);
    private void panelTitleBar_MouseDown(object sender, MouseEventArgs e)
    {
        ReleaseCapture();
        SendMessage(this.Handle, 0x112, 0xf012, 0);
    }

いくつかの説明を付けて回答をサポートしていただければ幸いです:)
Mustafamg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.