#画面キャプチャ時のフレーム
デスクトップ画面のキャプチャをするときに、
ユーザーが選択範囲を選んで位置を確認するためのフレームをC#のFormにて作成
###--- ユーザー操作 ---
- ドラッグで移動
- ドラッグで拡大縮小(呼び出し側で切り替え可能)
#サンプルコード(呼び出し側)
using System;
using System.Drawing;
using System.Windows.Forms;
using CaptureAreaSelector;
namespace testForm
{
public partial class Form1 : Form
{
FrameForm frame;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
frame = new FrameForm();
frame.ShowInTaskbar = false; //タスクバーに表示させない
frame.FrameBorderSize = 10; //線の太さ
frame.FrameColor = Color.Blue; //線の色
frame.AllowedTransform = true; //サイズ変更の可否
frame.Show();
}
private void button2_Click(object sender, EventArgs e)
{
if (frame!=null)
MessageBox.Show(frame.SelectedWindow.ToString());
}
}
}
#サンプルコード
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace CaptureAreaSelector
{
public partial class FrameForm : Form
{
private static readonly Color PrimaryTransparencyKey = Color.White;
private static readonly Color SecondaryTransparencyKey = Color.Black;
/// <summary>
/// 選択範囲の位置と範囲です。
/// </summary>
[Category("配置"), Description("選択範囲の位置と範囲です")]
public Rectangle SelectedWindow
{
get
{
var rect = this.Bounds;
rect.Inflate(_FrameBorderSize * -1, _FrameBorderSize * -1);
return rect;
}
}
private Color _FrameColor = Color.Red;
/// <summary>
/// フレームの色です
/// </summary>
[Category("表示"), Description("フレームの色です")]
[DefaultValue(typeof(Color), "Red")]
public Color FrameColor {
get { return _FrameColor; }
set
{
_FrameColor = value;
if (_FrameColor == PrimaryTransparencyKey)
this.TransparencyKey = SecondaryTransparencyKey;
else
this.TransparencyKey = PrimaryTransparencyKey;
this.Refresh();
}
}
private int _FrameBorderSize = 5;
/// <summary>
/// フレームの線の太さです
/// </summary>
[Category("表示"), Description("フレームの線の太さです")]
[DefaultValue(5)]
public int FrameBorderSize
{
get { return _FrameBorderSize; }
set
{
_FrameBorderSize = value;
this.Refresh();
}
}
/// <summary>
/// フレームの変形を許可します
/// </summary>
[Category("動作"), Description("フレームの変形を許可します")]
[DefaultValue(true)]
public bool AllowedTransform { get; set; } = true;
Point mousePoint; //マウス位置の一時記憶
public FrameForm()
{
InitializeComponent();
FormBorderStyle = FormBorderStyle.None;
this.TransparencyKey = PrimaryTransparencyKey;
}
/// <summary>
/// 枠だけ残して透明にする
/// </summary>
/// <param name="g"></param>
void draw(Graphics g)
{
var rct = this.ClientRectangle;
g.FillRectangle(new SolidBrush(FrameColor), rct);
rct.Inflate(FrameBorderSize * -1, FrameBorderSize * -1);
g.FillRectangle(new SolidBrush(TransparencyKey), rct);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
//位置を記憶する
mousePoint = new Point(e.X, e.Y);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (AllowedTransform)
{
if (e.X > Width * 2 / 3 && e.Y > Height * 1 / 2) //カーソルが右下なら
frameTransform(e);
else
frameMove(e);
}
else
frameMove(e);
base.OnMouseMove(e);
}
void frameMove(MouseEventArgs e)
{
Cursor = Cursors.SizeAll;
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
this.Left += e.X - mousePoint.X;
this.Top += e.Y - mousePoint.Y;
}
}
void frameTransform(MouseEventArgs e)
{
if (AllowedTransform)
{
Cursor = Cursors.SizeNWSE;
if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
{
this.Width += e.X - mousePoint.X;
mousePoint.X += e.X - mousePoint.X;
this.Height += e.Y - mousePoint.Y;
mousePoint.Y += e.Y - mousePoint.Y;
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
draw(e.Graphics);
base.OnPaint(e);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.Refresh();
}
}
}
※呼び出し側と呼び出され側で別プロジェクトになっています
#課題
1.サイズを拡大するときに残像が残る
→解決しました、o2kazuma様ありがとうございます。
2.サイズ変更可否の切り替えに無理やり感
→サイズ変更可否のプロパティは派生クラスに乗せて、OnMouseMoveメソッドをオーバーライドした方がよい??
3.ドラッグで移動させるためのMouseイベントがいくつか並んでいるが、どうもすっきりしない(Controlに対してたまに使う機能群なので)
→すっきり一まとめにする良い方法はないものか
#作ってみて
このフレームは、キャプチャのための枠取りとして何となく作ったが、他にもいろいろと応用が利きそう。呼び出し側FormのPictureBoxに投影させてみたり。
そこまで考えると、実はcontrolクラスから継承させたほうがよい?わからん。
とりあえず、コントロールを作るのは楽しい。