ドラッグによりリサイズ可能なパネルを実装する - C#
Windows Form アプリケーションでドラッグによりリサイズ可能なパネルを実装するコードを紹介します。
概要
パネルのMouseDownイベントでWM_SYSCOMMAND メッセージをパネルに対して送信します。パラメーターにSC_SIZEを与えることでドラッグによるリサイズができます。
プログラム
UI
下図のUIを作成します。PanelとLabelを配置します。
コード
下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ResizePanel
{
public partial class FormMain : Form
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_MOVE = 0xF010;
const int SC_SIZE = 0xF000;
[DllImport("User32.dll", EntryPoint = "SendMessage")]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, int lParam);
[DllImport("User32.dll")]
public static extern bool SetCapture(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ReleaseCapture();
public FormMain()
{
InitializeComponent();
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
SetCapture(panel1.Handle);
ReleaseCapture();
int flag = 0;
if (e.X < 10) {
flag += 0x0001;
}
if (panel1.Width - 10 < e.X) {
flag += 0x0002;
}
if (e.Y < 10) {
flag += 0x0003;
}
if (panel1.Height - 10 < e.Y) {
flag += 0x0006;
}
label1.Text = Convert.ToString(flag);
SendMessage(panel1.Handle, WM_SYSCOMMAND, SC_SIZE | flag, 0);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
int flag = 0;
if (e.X < 10) {
flag += 0x0001;
}
if (panel1.Width - 10 < e.X) {
flag += 0x0002;
}
if (e.Y < 10) {
flag += 0x0003;
}
if (panel1.Height - 10 < e.Y) {
flag += 0x0006;
}
switch (flag) {
case 0:
panel1.Cursor = Cursors.Default;
break;
case 1:
case 2:
panel1.Cursor = Cursors.SizeWE;
break;
case 3:
case 6:
panel1.Cursor = Cursors.SizeNS;
break;
case 4:
case 8:
panel1.Cursor = Cursors.SizeNWSE;
break;
case 5:
case 7:
panel1.Cursor = Cursors.SizeNESW;
break;
}
}
}
}
解説
MouseDownイベント
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
SetCapture(panel1.Handle);
ReleaseCapture();
int flag = 0;
if (e.X < 10) {
flag += 0x0001;
}
if (panel1.Width - 10 < e.X) {
flag += 0x0002;
}
if (e.Y < 10) {
flag += 0x0003;
}
if (panel1.Height - 10 < e.Y) {
flag += 0x0006;
}
label1.Text = Convert.ToString(flag);
SendMessage(panel1.Handle, WM_SYSCOMMAND, SC_SIZE | flag, 0);
}
MouseDownイベントでは、パネルでボタンのクリックされた位置から移動モードのフラグを求めます。その後、SendMessageでWM_SYSCOMMANDメッセージをPanelに対して送信します。送信時にSC_SIZEと移動モードのフラグのORを撮った値を送信します。
SC_SIZEと合わせて送信するフラグの値と意味は以下の通りです。
値 | 2進数の値 | 動作 |
0x0001 | 00000001 | 左方向のリサイズ |
0x0002 | 00000010 | 右方向のリサイズ |
0x0003 | 00000011 | 上方向のリサイズ |
0x0006 | 00000110 | 下方向のリサイズ |
| | |
0x0004 | 00000100 | 左上方向のリサイズ |
0x0005 | 00000101 | 右上方向のリサイズ |
0x0007 | 00000111 | 左下方向のリサイズ |
0x0008 | 00001000 | 右下方向のリサイズ |
斜め方向の値は、縦、横方向の値を加算すると求めることができます。
(例) 左上(4)=左(1)+上(3)
MouseMoveイベント
パネル内でのマウスポインタの位置からカーソルを変更します。カーソルの変更については
こちらの記事を参照してください。
実行結果
アプリケーションを実行します。下図のウィンドウが表示されます。
パネルの境界にマウスポインタを合わせるとポインタの形状が変化します。ドラッグするとパネルのサイズを変更できます。
縦横方向どちらにもリサイズできます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用