Adsense_top

2009年9月19日土曜日

C# 変形ウインドウにマウス操作を追加した。

先日書いた、「画像を使った変形ウインドウを作ってみた。」の続きです。

前回は画像を読み込んでウインドウを作っていたため タイトルバーないためにCloseBoxの代わりに、フォームのクリックイベットで閉じるようにして逃げていました。
また、同じくタイトルバーがないために、ドラッグしてのフォームの移動が出来ませんでした

今回は上記の点を変更し、独自に画像ファイルを使用してCloseBoxを表示し、フォームのドラッグも出来るように変更してみます。
前回のソースを変更して対応していますので、前回説明した部分ははしょってるかもしれませんので、前回分をみられていない方は前回のエントリーも参照してください

以下のような画像ファイルを用意しました。
Skin.bmp
Close.bmp

20 X 60 の中に、20 X 20で、左から、「通常状態」「マウスがポイントしている状態」「Boxを押下している状態」の3つをまとめて描いてあります。

クラス変数は、画像を格納する変数と、マウスの状態を格納する変数、背景画像上の CloseBoxの描画位置とサイズ情報などを格納した変数を用意しました。
// 背景画像とCloseBox画像を格納する変数
private Bitmap backBmp = null;
private Bitmap closeBmp = null;
// マウスの左ボタンが押下されているかの状態を格納
private bool isMouseDown = false;
// マウスポインタがCloseBox上に位置しているかを格納
private bool isMouseOverBox = false;
// マウスがCloseBox上で押下されたかを格納
private bool isMouseDownOnClose = false;
// マウスポインタの位置を格納
private Point mousePoint;
// CloseBoxの位置とサイズを格納した、
// readonly修飾しているので実質的な実行時定数
private readonly Point boxLocation = new Point(323, 43);
private readonly Size boxSize = new Size(20, 20);
// 「arayan's」と書かれた背景画像上ボタンの位置とサイズを格納した、
// readonly修飾しているので実質的な実行時定数
private readonly Point titleLocation = new Point(16, 15);
private readonly Size titleSize = new Size(137, 30);

フォームのコンストラクタには、CloseBox画像の読み込みを追加しています。
//
// コンストラクタ(初期化処理)
//
public Form1()
{
InitializeComponent();
// 今回はこのイベントハンドラの登録およびハンドラは削除
//this.Click += new System.EventHandler(this.Form1_Click);

// 以下3つのイベントハンドラ登録部今回追加
this.MouseDown += new System.Windows.Forms.
MouseEventHandler(this.Form1_MouseDown);
this.MouseUp += new System.Windows.Forms.
MouseEventHandler(this.Form1_MouseUp);
this.MouseMove += new System.Windows.Forms.
MouseEventHandler(this.Form1_MouseMove);

// 境界線なしにする。
this.FormBorderStyle = FormBorderStyle.None;
// 。ダブル バッファリングを使用するように動作を設定する。
this.SetStyle(ControlStyles.DoubleBuffer
| ControlStyles.UserPaint
| ControlStyles.AllPaintingInWmPaint, true);
// 背景画像ファイルを読み込む
bmp =(Bitmap) Bitmap.FromFile("skin.bmp");

// CloseBox画像を読み込む(今回追加部)
closeBmp = (Bitmap)Bitmap.FromFile("Close.bmp");

// ウインドウサイズを調整(前回分とは少し変更しました。)
this.Width = bmp.Width;
this.Height = bmp.Height;
// ウインドウ領域を設定する。
this.Region = BitmapToRegion(bmp, Color.FromArgb(255, 0, 255));
// 原点の色を使う場合は以下のようにする
// this.Region = BitmapToRegion(bmp, bmp.GetPixel(0, 0));
}
背景描画の部分にCloseBoxの描画メソッドのコール追加しています。
BitmapToRegionメソッドは前回のエントリーに書いたコードを参照してください。
//
// コントロールの背景を描画。
// (OnPaintBackground をオーバーライド)
//
protected override void OnPaintBackground(PaintEventArgs e)
{
// 座標単位を設定
e.Graphics.PageUnit = GraphicsUnit.Pixel;
// 背景描画(画像を描画)
e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);

// CloseBoxの描画メソッドを呼ぶ(今回追加部)
DrawCloaseBox(e.Graphics);
}
//
// CloseBoxを状態に合わせて異なる画像を描画する(今回追加部)
//
private void DrawCloseBox(Graphics g)
{
// closeBmp中の今回使用するCloseBox画像の矩形を格納する変数
Rectangle rectSrc;
if (isMouseOverBox)
{
if (isMouseDown)
{
// CloseBoxが押下された画像
rectSrc =
new Rectangle(new Point(boxSize.Width * 2, 0), boxSize);
}
else
{
// CloseBoxがアクティブ状態の画像
rectSrc =
new Rectangle(new Point(boxSize.Width, 0), boxSize);
}
}
else
{
// 通常時の画像
rectSrc =
new Rectangle(new Point(0, 0), boxSize);
}
// 状態にあった画像でCloseBoxを描画
g.DrawImage(this.closeBmp, new Rectangle(boxLocation,boxSize),
rectSrc, GraphicsUnit.Pixel);
}
「OnPaintBackground」では、前回分に追加してCloseBoxを描画するメソッド「DrawCloseBox」をGraphicsオブジェクトを渡して読んでいます。
「DrawCloseBox」では、マウスイベントハンドラで設定したフラグで状態を判断し、状態にあったCloseBox画像を描画しています。
下図のような表示になります。
  

以下は今回追加したイベントハンドラ部でです。
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
// マウス左クリック時位置を記録
if (e.Button == MouseButtons.Left)
mousePoint = new Point(e.X, e.Y);
// CloseBox上の押下か?を記録
isMouseDownOnClose = isMouseOverButton;
// マウスの押下状態を記録
isMouseDown = true;
// 再描画
Refresh();
}
ここでは、マウス左ボタンの押下状態を記録。
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
// マウス押下記録を消去
isMouseDown = false;
// CloseBox上にマウスがあり且、CloseBox上で
// 押下さたのであればウインドウを閉じる
if (isMouseOverButton && isMouseDownOnClose)
this.Close();
else
isMouseDownOnClose = false;
}
ここでは、変数の値を確認判定して、条件を満たしていればウインドウを閉じています。
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
// マウス左ボタンか確認
if ( e.Button == MouseButtons.Left)
{
// ポインタ位置が「arayan's」ボタンの中にある場合
if (e.X > titleLocation.X)
&& (e.X < titleLocation.X + titleSize.Width)
&& (e.Y > titleLocation.Y)
&& (e.Y < titleLocation.Y + titleSize.Height))
{
// フォームの位置をMouseDown時からの移動分調節(移動)する。
this.SetDesktopLocation(this.Left - mousePoint.X + e.X,
this.Top - mousePoint.Y + e.Y);
}
// ポインタ位置がCloseBoxの中にある場合
if ((e.X > buttonLocation.X)
&& (e.X < buttonLocation.X + buttonSize.Width)
&& (e.Y > buttonLocation.Y)
&& (e.Y < buttonLocation.Y + buttonSize.Height))
{
// 変数にフラグを立てる
isMouseOverButton = true;
}
else
{
isMouseOverButton = false; ;
}
// 再描画
Refresh();
}
}
ここで、フォームのドラッグを処理しています。また、マウスがCloseBox上に位置するかも記録しています。

以上で「arayan's」ボタンをタイトルバーのようにドラッグで移動できるようになり、右上のボタンで閉じることが出来るようになりました。
画像を使ったウインドウは大体出来たので、着せ替えが出来るようにし本当の意味でのスキンを考えてみようかと思います。

1 件のコメント: