DOBON.NET DOBON.NETプログラミング掲示板過去ログ

選択時にラベルの枠に点線表示

環境/言語:[Windows XP C# VisualStudio2010]
分類:[.NET]

早速質問に入らせていただきます。

ラベルをドラッグアンドドロップで
配置場所を変えるというプログラムを作っています。
ラベルの配置を変えることは出来たのですが、
ドラッグしているラベル(選択しているラベル)が
わかるようにしたいということで
ラベルの枠に点線を表示することにしました。
他のラベルが選択されるまで点線は表示していたいです。

ラベルの枠に点線を表示することは出来ました。
下記がそのコードです。
カスタムコントロール(名:CustomLabel)で作成しました。

質問したいのは、ラベルを選択したときのみ
点線を表示したいのですが、
下記コードを実行すると最初から(Form表示時点で)
点線が表示されてしまいます。
ラベルを選択(MouseDownイベントなど)しているときに
点線を表示するというのはどのようにすればいいのでしょうか?

CustomLabel内でMouseDownイベントを起こし
そのイベント内でOnPaint()を呼びたいのですが
可能でしょうか?
また、OnPaint()が呼べない場合、どのように定義すればいいでしょうか?
よろしくお願いします。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace CustomLabel
{
public partial class CustomLabel: Label
{
public CustomLabel()
{
InitializeComponent();
}

/// <summary>
/// 点線表示
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
{
base.OnPaint(pe);

using (System.Drawing.Pen hPen = new System.Drawing.Pen(System.Drawing.Color.Black, 1))
{
hPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
pe.Graphics.DrawRectangle(hPen, 0, 0, this.Width - 1, this.Height - 1);
}
}

/// <summary>
/// ラベル選択
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FreeLabel_MouseDown(object sender, MouseEventArgs e)
{
※ここでOnPaint()を呼びたい
}
}
}
■No29908に返信(こたろうさんの記事)
> そのイベント内でOnPaint()を呼びたいのですが
> 可能でしょうか?

Invalidate メソッドを呼び出すと、再描画要求が発生します。
http://dobon.net/vb/dotnet/control/refreshupdateinvalidate.html
■No29909に返信(魔界の仮面弁士さんの記事)
返信ありがとうございます。

Form1にCustomLabelを配置しているのですが、
Form1が表示されるときに
CustomLabelのOnPaint()が呼ばれてしまい、
Form1が表示されるときに点線が表示されてしまいます。

これを点線を表示させないようにすることはできませんか?
思いつく方法としては、CustomLabelクラス内にPrivateなフラグ変数を用意し、

・このラベルが点滅対象となった時(このラベルのMouseDownイベント時?)に
 このフラグを立てる。
・オーバーライドしたOnPaintメソッドでは、このフラグが立っている時だけ
 点線描画を行う。

という方法が手っ取り早いとおもいます。
ただし、点線表示を元に戻すタイミングがこのラベルのMouseUpではなく、親フォーム上の
他のCustomLabelを選択した時ということなので、その場合、他のCustomLabelの選択を
親フォームで検知し、先ほどまで選択していたCustomLabelのフラグを親フォーム側で
解除できるようにしなくてはなりませんね。
■No29911に返信(こたろうさんの記事)
> CustomLabelのOnPaint()が呼ばれてしまい、
> Form1が表示されるときに点線が表示されてしまいます。

マウス押下中のみの描画で良いなら、描画時にマウスの状態で判断するとか。
http://dobon.net/vb/dotnet/system/mousebuttons.html
http://dobon.net/vb/dotnet/system/cursorposition.html

マウスボタンが押されている最中に点線を描画するのではなく、
チェックボックスのようにクリックのたびにトグル指定するのであれば、
選択されている最中かどうかを管理する変数を用意するとか。

デザイン時と実行時を区別したいという意味であれば、
Control.DesignMode プロパティを使ってみるとか。
■No29912に返信(ズッカさんの記事)
ありがとうございます。
> 思いつく方法としては、CustomLabelクラス内にPrivateなフラグ変数を用意し、
>
> ・このラベルが点滅対象となった時(このラベルのMouseDownイベント時?)に
>  このフラグを立てる。
> ・オーバーライドしたOnPaintメソッドでは、このフラグが立っている時だけ
>  点線描画を行う。
>
> という方法が手っ取り早いとおもいます。
下記のようにすることで出来ました!
public partial class CustomLabel: Label
{
public bool checkFlg
{
get;
set;
}

public CustomLabel()
{
InitializeComponent();
this.checkFlg = false;
}

/// <summary>
/// 点線表示
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(System.Windows.Forms.PaintEventArgs pe)
{
base.OnPaint(pe);

using (System.Drawing.Pen hPen = new System.Drawing.Pen(System.Drawing.Color.Black, 1))
{
if (this.checkFlg)
{
hPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
pe.Graphics.DrawRectangle(hPen, 0, 0, this.Width - 1, this.Height - 1);
}
}
}

private void CustomLabel_MouseDown(object sender, MouseEventArgs e)
{
this.checkFlg = true;
this.Invalidate();
}
}


> ただし、点線表示を元に戻すタイミングがこのラベルのMouseUpではなく、親フォーム上の
> 他のCustomLabelを選択した時ということなので、その場合、他のCustomLabelの選択を
> 親フォームで検知し、先ほどまで選択していたCustomLabelのフラグを親フォーム側で
> 解除できるようにしなくてはなりませんね。
試行錯誤した結果、下記のようにすることで解決できました!
ありがとうございました。

private void customLabel_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
foreach (Control c in this.Controls)
{
if (c.GetType() == typeof(CustomLabel))
{
CustomLabel label = (CustomLabel)c;
CustomLabel downLabel = (CustomLabel)sender;
if (label.checkFlg && (downLabel != label))
{
label.checkFlg = false;
this.Invalidate();
}
}
}
}
}
解決済み!
■No29913に返信(魔界の仮面弁士さんの記事)
返信ありがとうございます。
> マウス押下中のみの描画で良いなら、描画時にマウスの状態で判断するとか。
押下中のみではなく、押下後も他のCustomLabelが選択されるまで
描画させなければならないので、
ズッカさんの方法を使用し、解決いたしました。

今後、同じような問題で悩んだときに
魔界の仮面弁士さんの回答も参考にしたいと思います。
勉強になります。
ありがとうございました。

お二人とも、貴重なお時間を割いていただき
ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板