Web検索はbingがおすすめ!

ドラッグによりリサイズ可能なパネルを実装する - 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進数の値動作
0x000100000001左方向のリサイズ
0x000200000010右方向のリサイズ
0x000300000011上方向のリサイズ
0x000600000110下方向のリサイズ
0x000400000100左上方向のリサイズ
0x000500000101右上方向のリサイズ
0x000700000111左下方向のリサイズ
0x000800001000右下方向のリサイズ
斜め方向の値は、縦、横方向の値を加算すると求めることができます。
(例) 左上(4)=左(1)+上(3)

MouseMoveイベント

パネル内でのマウスポインタの位置からカーソルを変更します。カーソルの変更についてはこちらの記事を参照してください。

実行結果

アプリケーションを実行します。下図のウィンドウが表示されます。


パネルの境界にマウスポインタを合わせるとポインタの形状が変化します。ドラッグするとパネルのサイズを変更できます。


縦横方向どちらにもリサイズできます。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2014-04-21
iPentec all rights reserverd.