【間違った.Netのカスタムコントロールの作り方】こんなもんでいいかな?

やらないと寂しいところを変更した。

  1. 縦横のスクロールバーが表示してる時に気になる右下隅の部分をボタンで隠した。
  2. マウスの左ボタンを押しながらドラッグすると画像を掴んだ感じでスクロール。
  3. マウスのホイールを回すとズーム(1~10倍)。

ズームするのはコンテキストメニューを出しスライダーを操作した方が良いのだろうけど・・・
コンテキストメニューはテキストしかだせないので、
スライダーを載せたフレームの無いフォームを作り、
TopLevelプロパティをちょっとごまかして・・・
ToolStripDropDownの中に放り込まないといけないから、
1ソースで作るのは面倒だったから止めた。
 
さてここまで来ると
もうちょっとで自前のPanelユーザコントロールを作れてしまうというオチです。
class  ccPanel : Rectange
{
・・・
}
また、PictureBoxクラスに頼っているのは

  1. 画像の表示

//基底クラスで画像を描画してもらう。
base.OnPaint(e);

の1点のみなので、これもImageクラスを使えば、
//Imageクラスで画像を描画してもらう。
g.DrawImage(base.Image,new Point(0,0));
で十分ですから・・・
class ccPictureBox : PictureBox

class ccPictureBox : Control
と簡単に書き換えられそうです。
 
じゃぁ~なんでPictureBoxなんてVSにあるんでしょうね?
やっぱりVBがまだあるからでしょうかね???(大笑
いやそうではなく
/// <summary>
/// 描画時のイベントハンドラ
/// </summary>
/// <param name=”e”></param>
protected override void OnPaint(PaintEventArgs e)
{
//カスタムコントロールの描画オブジェクトを取得
Graphics g = e.Graphics;
g.DrawImage(base.Image,new Point(0,0));
//ここで借り物の描画オブジェクトをDisposeすると後悔するだろう。
}
・・・
/// <summary>
/// ファイルを読んでみる
/// </summary>
/// <param name=”fileName”></param>
public void  ImageLocation(string fileName)
{
this.Image = Image.FromFile(fileName);
}
まで書き上げ、
参考記事を見ながら
[Browsable(false)]
public override bool AllowDrop { get; set; }
と書いたところ、プロパティウインドウにAllowDrop が出なったので
[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]
と書いたものの
 
多国語対応ができず、
 
結局時間切れでデフォルトの設定に戻ってしまったまま・・・・・・・・・・・
それが原因で
【間違った.Netのカスタムコントロールの作り方】ほぼ完成版までたどり着いた訳です。
 
と、想像すると笑えますね。
ともあれ、簡単にカスタムコントロールが作れれば、色々と便利かと思います。
 
【以下、ほぼ完成版のWindows Form(C#)のPictureBoxのスクロールバーとズーム付きのカスタムコントール】
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Custom.Control
{
class ccPictureBox : PictureBox
{
/// <summary>
/// 画像の高さがコントロールのそれよりも大きい場合に表示する縦スクロール・コントロール
/// </summary>
private VScrollBar sbV;
/// <summary>
/// 画像の幅がコントロールのそれよりも大きい場合に表示する横スクロール・コントロール
/// </summary>
private HScrollBar sbH;
/// <summary>
/// 縦横スクロール・コントロールが表示している時に右下隅の気になる部分を隠すためのボタン・コントロール
/// </summary>
private Button btnNG;
/// <summary>
///現在の横スクロール量
/// </summary>
private float dx = 0.0f;
/// <summary>
///現在の縦スクロール量
/// </summary>
private float dy = 0.0f;
/// <summary>
///現在の画像の描画倍率
/// (等倍=1.0)
/// </summary>
private float zoom = 1.0f;
//マウスのホィールで倍率を増減する単位
private float dZoom = 0.1f;
//マウスのホィールで倍率を増減の最大値
private float dZoomMax = 10.0f;
//マウスのホィールで倍率を増減の最小値
private float dZoomMin = 1.0f;
/// <summary>
/// コンストラクター
/// </summary>
public ccPictureBox()
{
//縦スクロールバー
sbV = new VScrollBar();
sbV.Parent = this;
sbV.Scroll += sbV_Scroll;
sbV.Visible = false;
//横スクロールバー
sbH = new HScrollBar();
sbH.Parent = this;
sbH.Scroll += sbH_Scroll;
sbH.Visible = false;
//気になる部分を隠すためのボタン
btnNG = new Button();
btnNG.Parent = this;
btnNG.Visible = false;
//各イベントハンドラの登録
this.DragDrop += new System.Windows.Forms.DragEventHandler(myDragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(myDragEnter);
this.ClientSizeChanged += new System.EventHandler(myClientSizeChanged);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(myMouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(myMouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(myMouseUp);
this.MouseWheel += new System.Windows.Forms.MouseEventHandler(myMouseWheel);
//全ての設定を終えたのでスクロールバーを改めて再調整する
ChkScrollBar();
}
/// <summary>
/// 横スクロール時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
void sbH_Scroll(object sender, ScrollEventArgs e)
{
dx = e.NewValue;
this.Invalidate();
}
/// <summary>
/// 縦スクロール時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
void sbV_Scroll(object sender, ScrollEventArgs e)
{
dy = e.NewValue;
this.Invalidate();
}
/// <summary>
/// 描画時のイベントハンドラ
/// </summary>
/// <param name=”e”></param>
protected override void OnPaint(PaintEventArgs e)
{
//カスタムコントロールの描画オブジェクトを取得
Graphics g = e.Graphics;
//バックアップ
GraphicsState bk = g.Save();
//座標系の水平移動でスクロール操作と連携する。
g.TranslateTransform(-dx, -dy);
g.ScaleTransform(zoom, zoom);
//基底クラスで画像を描画してもらう。
base.OnPaint(e);
//リストア
g.Restore(bk);
//ここで借り物の描画オブジェクトをDisposeすると後悔するだろう。
}
/// <summary>
/// 基底クラスのPictureBoxのImageプロパティをちょっと改造した個所
/// </summary>
[Bindable(true)]
[Localizable(true)]
public new Image Image
{
get
{
// 基底クラスPictureBoxのImageを返す。
return base.Image;
}
set
{
// 基底クラスPictureBoxのImageを更新。
base.Image = value;
//スクロールバーを調整。
ChkScrollBar();
}
}
/// <summary>
/// 直近のSizeの値
/// </summary>
private Size oldSize;
/// <summary>
/// 基底クラスのPictureBoxのSizeプロパティをちょっと改造した個所
/// </summary>
[Bindable(true)]
[Localizable(true)]
public new Size Size
{
get
{
// 基底クラスPictureBoxのSizeを返す。
return base.Size;
}
set
{
// 基底クラスPictureBoxのSizeを更新。
base.Size = value;
if (oldSize == null || !oldSize.Equals(value))
{
//スクロールバーを調整。
ChkScrollBar();
}
//直近のSizeの値を更新。
oldSize = value;
}
}
[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]
public override bool AllowDrop { get; set; }
/// <summary>
/// ドラッグ処理のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myDragEnter(object sender, DragEventArgs e)
{
//ファイルならOKにしておく。
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}
/// <summary>
/// ドラッグ処理のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myDragDrop(object sender, DragEventArgs e)
{
//ファイルなら
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// ドラッグ中のファイルなどを取得
string[] drags = (string[])e.Data.GetData(DataFormats.FileDrop);
string fileName = null;
foreach (string d in drags)
{
if (!System.IO.File.Exists(d))
{
// ファイル以外であれば読み飛ばす。
continue;
}
fileName = d;
//最後のファイルを使うならbreakをコメントアウトする
break;
}
if (fileName != null)
{
try
{
this.Image = Image.FromFile(fileName);
}
catch (Exception ex)
{
//画像ファイルではなかったらしい。
MessageBox.Show(“【” + fileName + “】” + ex.Message);
return;
}
//画像ファイルの読み込みに成功した場合。
e.Effect = DragDropEffects.Copy;
//スクロール位置や倍率は初期化する
dx = sbH.Value = 0;
dy = sbV.Value = 0;
zoom = 1;
ChkScrollBar();
}
}
}
/// <summary>
/// スクロールバーを表示するかどうかチェックし
/// 表示する際には位置や設定範囲を調整する
/// </summary>
/// <returns></returns>
private bool ChkScrollBar()
{
bool rc = false;
if (this.Image != null)
{
//各スクロールバーを表示するかどうかを判定
bool showV = (this.Height < this.Image.Size.Height * zoom);
bool showH = (this.Width < this.Image.Size.Width * zoom);
//判定結果の和を戻り値とする
rc = showH | showH;
//縦スクロールバーを表示する場合は
if (showV)
{
sbV.Top = 0;
sbV.Left = this.ClientSize.Width – sbV.Width;
//両方表示する場合、横スクロールバーの高さ分小さくする
sbV.Height = this.ClientSize.Height – (showH ? sbH.Height : 0);
//大雑把な操作はスクロールバーの高さ分
sbV.LargeChange = sbV.Height;
//範囲の補正
//最大値=(画像の高さ)-(縦スクロールバーの高さ)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbV.Maximum = (int)(this.Image.Size.Height * zoom – sbV.Height + (sbV.LargeChange + 1));
sbV.Visible = true;
}
//縦スクロールバーを表示しない場合は
else
{
sbV.Visible = false;
}
//横スクロールバーを表示する場合は
if (showH)
{
sbH.Top = this.ClientSize.Height – sbH.Height;
sbH.Left = 0;
//両方表示する場合、縦スクロールバーの幅分小さくする
sbH.Width = this.ClientSize.Width – (showV ? sbV.Width : 0);
//大雑把な操作はスクロールバーの幅分
sbH.LargeChange = sbH.Width;
//範囲の補正
//最大値=(画像の幅)-(横スクロールバーの幅)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbH.Maximum = (int)(this.Image.Size.Width * zoom – sbH.Width + (sbH.LargeChange + 1));
//
sbH.Visible = true;
}
//横スクロールバーを表示しない場合は
else
{
sbH.Visible = false;
}
//縦横スクロールバーを両方表示するなら、右下隅の気になる部分にボタンを表示する。
if (showV && showH)
{
btnNG.Left = sbV.Left – 1;
btnNG.Top = sbH.Top – 1;
btnNG.Width = sbV.Width + 2;
btnNG.Height = sbH.Height + 2;
btnNG.Visible = true;
}
//それ以外はボタンを隠しておく。
else
{
btnNG.Visible = false;
}
}
return rc;
}
/// <summary>
/// Sizeが変更された後のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myClientSizeChanged(object sender, EventArgs e)
{
ChkScrollBar();
}
/// <summary>
/// MouseDown時のマウス座標
/// </summary>
private Point pointCaptureStartMousePoint;
/// <summary>
/// MouseDown時のスクロール位置
/// </summary>
private Point pointCaptureStartScrollPoint;
/// <summary>
/// マウスをボタンを押した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseDown(object sender, MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
pointCaptureStartMousePoint = new Point(e.X, e.Y);
pointCaptureStartScrollPoint = new Point(sbH.Value,sbV.Value);
this.Capture = true;
break;
}
}
/// <summary>
/// マウスをボタンを離した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseUp(object sender, MouseEventArgs e)
{
this.Capture = false;
}
/// <summary>
/// マウスをドラッグ操作時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseMove(object sender, MouseEventArgs e)
{
try
{
switch (e.Button)
{
case MouseButtons.Left:
Point pointMousePoint = new Point(e.X, e.Y);
//マウスダウン時からの相対位置に変換。
Point dMove = new Point(pointMousePoint.X – pointCaptureStartMousePoint.X, pointMousePoint.Y – pointCaptureStartMousePoint.Y);
//スクロール量を計算
Point dScroll = new Point(pointCaptureStartScrollPoint.X – dMove.X, pointCaptureStartScrollPoint.Y – dMove.Y);
//スクロール
//スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
if (0 <= dScroll.X && dScroll.X <= (sbH.Maximum – sbH.LargeChange + 1))
{
dx = sbH.Value = dScroll.X;
}
//スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
if (0 <= dScroll.Y && dScroll.Y <= (sbV.Maximum – sbV.LargeChange + 1))
{
dy = sbV.Value = dScroll.Y;
}
this.Invalidate();
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// マウスのホィールを回した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseWheel(object sender, MouseEventArgs e)
{
//ZOOM
int d = e.Delta;
Trace.WriteLine(d.ToString());
if(d <0)
{
if (zoom <= dZoomMax)
{
zoom += dZoom;
ChkScrollBar();
this.Invalidate();
}
}
else
{
if (zoom >= dZoomMin)
{
zoom -= dZoom;
ChkScrollBar();
this.Invalidate();
}
}
}
}
}
 
// EOF.




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA