タイトルバーを持たないフォームをマウスで移動させる方法を紹介します。
まずは、最も基本的なやり方です。次のコードでは、単純にフォーム(Form1)上でマウスの左ボタンが押され、移動させたことを感知することにより処理しています。
'マウスのクリック位置を記憶 Private mousePoint As Point 'Form1のMouseDownイベントハンドラ 'マウスのボタンが押されたとき Private Sub Form1_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseDown If (e.Button And MouseButtons.Left) = MouseButtons.Left Then '位置を記憶する mousePoint = New Point(e.X, e.Y) End If End Sub 'Form1のMouseMoveイベントハンドラ 'マウスが動いたとき Private Sub Form1_MouseMove(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseMove If (e.Button And MouseButtons.Left) = MouseButtons.Left Then Me.Left += e.X - mousePoint.X Me.Top += e.Y - mousePoint.Y 'または、つぎのようにする 'Me.Location = New Point( _ ' Me.Location.X + e.X - mousePoint.X, _ ' Me.Location.Y + e.Y - mousePoint.Y) End If End Sub
//マウスのクリック位置を記憶 private Point mousePoint; //Form1のMouseDownイベントハンドラ //マウスのボタンが押されたとき private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { //位置を記憶する mousePoint = new Point(e.X, e.Y); } } //Form1のMouseMoveイベントハンドラ //マウスが動いたとき private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { this.Left += e.X - mousePoint.X; this.Top += e.Y - mousePoint.Y; //または、つぎのようにする //this.Location = new Point( // this.Location.X + e.X - mousePoint.X, // this.Location.Y + e.Y - mousePoint.Y); } }
上の例ではフォーム上にあるコントロールの上でマウスのボタンを押してドラッグしてもウィンドウは移動しません。コントロール上のドラッグでも移動できるようにするには、そのコントロールのMouseDownおよびMouseMoveイベントハンドラにForm1_MouseDownおよびForm1_MouseMoveを追加します。例えばForm1にPictureBox1オブジェクトがあり、PictureBox1上でマウスボタンを押してドラッグを開始してもForm1が移動できるようにするには次のようにします。
Private mousePoint As Point 'Form1のMouseDownイベントハンドラ Private Sub Form1_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseDown, PictureBox1.MouseDown '(上の例と同じため省略) End Sub 'Form1のMouseMoveイベントハンドラ Private Sub Form1_MouseMove(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseMove, PictureBox1.MouseMove '(上の例と同じため省略) End Sub
//Form1のLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { PictureBox1.MouseDown += new MouseEventHandler(Form1_MouseDown); PictureBox1.MouseMove += new MouseEventHandler(Form1_MouseMove); } private Point mousePoint; //Form1のMouseDownイベントハンドラ private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { //(上の例と同じため省略) } //Form1のMouseMoveイベントハンドラ private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { //(上の例と同じため省略) }
Win32 APIのReleaseCaptureとSendMessageを使って、フォーム上でマウスの左ボタンが押されたら、タイトルバー上でマウスの左ボタンが押されたことにするという方法があります。これは、「Move window/form without Titlebar in C#」などで紹介されている方法です。
'Imports System.Runtime.InteropServices Private Const WM_NCLBUTTONDOWN As Integer = &HA1 Private Const HT_CAPTION As Integer = &H2 <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Shared Function SendMessage(hWnd As IntPtr, _ Msg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr End Function <DllImportAttribute("user32.dll")> _ Private Shared Function ReleaseCapture() As Boolean End Function 'Form1のMouseDownイベントハンドラ Private Sub Form1_MouseDown(sender As Object, _ e As System.Windows.Forms.MouseEventArgs) _ Handles MyBase.MouseMove If e.Button = MouseButtons.Left Then 'マウスのキャプチャを解除 ReleaseCapture() 'タイトルバーでマウスの左ボタンが押されたことにする SendMessage(Handle, WM_NCLBUTTONDOWN, _ New IntPtr(HT_CAPTION), IntPtr.Zero) End If End Sub
//using System.Runtime.InteropServices; private const int WM_NCLBUTTONDOWN = 0xA1; private const int HT_CAPTION = 0x2; [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); [DllImportAttribute("user32.dll")] private static extern bool ReleaseCapture(); //Form1のMouseDownイベントハンドラ private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button == MouseButtons.Left) { //マウスのキャプチャを解除 ReleaseCapture(); //タイトルバーでマウスの左ボタンが押されたことにする SendMessage(Handle, WM_NCLBUTTONDOWN, (IntPtr)HT_CAPTION, IntPtr.Zero); } }
この方法も前の方法と同じように、フォーム上にあるコントロールの上でマウスのボタンを押してドラッグしてもウィンドウは移動しません。
次は、フォームのWndProcメソッドをオーバーライドする方法です。この方法では、あたかもタイトルバーをマウスで移動させているふりをして、フォームを移動させています。
'Imports System.Security.Permissions <SecurityPermission(SecurityAction.Demand, _ Flags:=SecurityPermissionFlag.UnmanagedCode)> _ Protected Overrides Sub WndProc(ByRef m As Message) MyBase.WndProc(m) Const WM_NCHITTEST As Integer = &H84 Const HTCLIENT As Integer = 1 Const HTCAPTION As Integer = 2 'マウスポインタがクライアント領域内にあるか If (m.Msg = WM_NCHITTEST) AndAlso (m.Result.ToInt32() = HTCLIENT) Then 'マウスがタイトルバーにあるふりをする m.Result = New IntPtr(HTCAPTION) End If End Sub
//using System.Security.Permissions; [SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] protected override void WndProc(ref Message m) { base.WndProc (ref m); const int WM_NCHITTEST = 0x84; const int HTCLIENT = 1; const int HTCAPTION = 2; //マウスポインタがクライアント領域内にあるか if ((m.Msg == WM_NCHITTEST) && (m.Result.ToInt32() == HTCLIENT)) { //マウスがタイトルバーにあるふりをする m.Result = (IntPtr) HTCAPTION; } }
この方法では、フォームをダブルクリックした時にフォームが最大化されます。フォームの最大化を防ぐ方法は、「フォームを最大化、最小化できないようにする」で説明しています。
この方法もはじめの方法と同様、このままでは、フォーム上にあるコントロールの上でマウスのボタンを押して移動させようとしてもウィンドウは移動しません。