C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: マウスオーバーで色を変えるユーザコントロール


(過去ログ 128 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■76010 / inTopicNo.1)  マウスオーバーで色を変えるユーザコントロール
  
□投稿者/ しゃむこ (1回)-(2015/05/22(Fri) 21:11:06)

分類:[.NET 全般] 

マウスオーバー時に背景色をXにする、という仕様の
ラベルコントロールを継承したユーザコントロールを作成しています。

OnMouseHover時に
_tmp = Me.ForeColor ※
Me.ForeColor = X

OnMouseLeave時に
Me.ForeColor = _tmp

とオーバライドしたのですが、
コントロールの初期表示時からマウスオーバーしている時などに、
※で自コントロールのプロパティ値が取れず、想定通りに動かない場合があります。

元々のプロパティ値をtmpに保持して置く、という発想が駄目?な気もしていますが、何か解決策がありますでしょうか。
そもそもユーザコントロールを作るというのが初めての為、お作法的な考え方だけでもお教えいただければと思います。

○環境
VB.NET
.NET Framework 3.5
VS2013
引用返信 編集キー/
■76011 / inTopicNo.2)  Re[1]: マウスオーバーで色を変えるユーザコントロール
□投稿者/ 魔界の仮面弁士 (347回)-(2015/05/22(Fri) 22:12:00)
No76010 (しゃむこ さん) に返信
> マウスオーバー時に背景色をXにする、という仕様の
> ラベルコントロールを継承したユーザコントロールを作成しています。

こういうことで良いのかな。あまりテストしていませんけど。


Public Class MyLabel
 Inherits Global.System.Windows.Forms.Label
 <Global.System.ComponentModel.DefaultValue(GetType(Color), "Highlight")> _
 Public Overridable Property HilightBackColor As Color = SystemColors.Highlight
 Private OriginalBackColor As Color
 Public Sub New()
  Me.OriginalBackColor = MyBase.BackColor
 End Sub
 Protected Overrides Sub OnMouseEnter(e As EventArgs)
  MyBase.BackColor = Me.HilightBackColor
  MyBase.OnMouseEnter(e)
 End Sub
 Protected Overrides Sub OnMouseLeave(e As EventArgs)
  MyBase.BackColor = Me.OriginalBackColor
  MyBase.OnMouseLeave(e)
 End Sub
End Class
引用返信 編集キー/
■76012 / inTopicNo.3)  Re[2]: マウスオーバーで色を変えるユーザコントロール
□投稿者/ 魔界の仮面弁士 (348回)-(2015/05/22(Fri) 23:42:05)
No76011 (魔界の仮面弁士) に追記
> こういうことで良いのかな。あまりテストしていませんけど。

流石に手抜き実装。改めて見直してみましたが、これでは甘いですね。
BackColor がアンビエントなプロパティであることを考慮していませんでした。

たとえば MyLabel1.BackColor が未設定(初期値)の時だった場合には、
親コントロール(Form とか Panel とか) の BackColor 変更に
追従させる必要がありますが、先のコードでは対応していません。


これについては、先ほどの
>  Public Sub New()
>   Me.OriginalBackColor = MyBase.BackColor
>  End Sub
を書きなおして、
 Public Sub New()
  Dim p = TypeDescriptor.GetProperties(GetType(Label)).Find("BackColor", False)
  If p.ShouldSerializeValue(Me) Then
   Me.OriginalBackColor = MyBase.BackColor
  Else
   Me.OriginalBackColor = New AmbientProperties().BackColor
  End If
 End Sub
とすればクリアできそうです。


ただこの実装でも、アプリ実行後に背景色を変更したい場合には対応できません。

マウスオーバー時の背景色は、HilightBackColor として公開しているものの、
通常時の背景色を保存している OriginalBackColor は公開していないためです。
OriginalBackColor も公開プロパティにする必要がありそうですね。


というか、マウスオーバー時の背景色を指定できるようにしたのであれば、
文字色も同様に指定できるようにしておかないとマズイでしょうね。
まともに作りこむなら、HilightBackColorChanged イベントも組み込むべきかな…。
引用返信 編集キー/
■76024 / inTopicNo.4)  Re[1]: マウスオーバーで色を変えるユーザコントロール
□投稿者/ 魔界の仮面弁士 (349回)-(2015/05/25(Mon) 13:49:19)
No76010 (しゃむこ さん) に返信
> マウスオーバー時に背景色をXにする、という仕様の
> ラベルコントロールを継承したユーザコントロールを作成しています。
> OnMouseHover時に
> _tmp = Me.ForeColor ※
> Me.ForeColor = X

【確認事項:その1】
質問文では「背景色」ですが、コードでは「ForeColor」を利用していますね。

ForeColor は文字色を表します。
BackColor は背景色を表します。

設定したいのはどちらでしょうか?(それとも両方?)
背景色だとすれば、先に回答したとおり「アンビエント」である点に注意して下さい。



【確認事項:その2】
質問文では「マウスオーバー時」ですが、コードは「OnMouseHover(マウスホバー時)」ですね。
OnMouseHover が呼ばれるには、0.4秒ほどの「一時停止期間」を必要とされますが、
このメソッドを採用しているのは、意図的なものでしょうか?

マウスカーソルがコントロールの上を通過しても、OnMouseHover が発生するとは限りません。
もしも HTML/JavaScript の onmouseover イベントの動作を想定しているなら、OnMouseEnter ですし、
マウスが移動するたびに違う色に変化させたいのであれば、MouseMove (あるいは Timer 利用)などを
使った方が良いかと思います。


一応、それぞれのイベントの違いについて記しておきます。


MouseEnterイベント/OnMouseEnterメソッド:
 カーソルがコントロール領域内に進入した時に呼ばれます。
 一度呼ばれると、次に MouseLeave が発生するまでは呼ばれません。
 非表示のコントロールが「表示された瞬間」に、コントロールの領域内に
 マウス座標が入っていた場合も呼ばれます。

MouseHoverイベント/OnMouseHoverメソッド:
 MouseEnter後、カーソルが一時停止した時に呼ばれます。
 一度呼ばれると、次に MouseLeave が発生するまでは呼ばれません。
 一時停止と認識されるまでの時間は SystemInformation.MouseHoverTime、
 一時停止と認識される移動許容範囲は SystemInformation.MouseHoverSize です。
 http://blog.firstsync.net/daily/1911/

MouseMoveイベント/OnMouseMoveメソッド:
 MouseEnter 後、マウス座標が変更されるたびに呼ばれます。
 マウスの分解能が低い場合や、マウス移動速度が速い場合、途中の座標は
 必ずしも連続した点とはならず、間引かれて呼ばれることがありますし、逆に、
 マウスの分解能が高い場合は、同一座標の通知が複数回呼ばれることもあります。
 このイベントは、マウスがコントロール領域外に出ると呼ばれなくなりますが、
 MouseDown 発生後は、MouseUpするまでの間、領域外でも MouseMove が呼ばれ続けます。

MouseLeaveイベント/OnMouseLeaveメソッド:
 カーソルがコントロール領域外に抜けた時に呼ばれます。
 一度呼ばれると、次に MouseEnter が発生するまでは呼ばれません。


> ※で自コントロールのプロパティ値が取れず、想定通りに動かない場合があります。

『自コントロールのプロパティ値』を取得するコードは、
どのタイミングで実行されていますか?

今回、「色」が変更されるタイミングは 4 種類あるかと思います。

(1)コントロールが生成された直後の色設定
(2)デザイン時に設定された色設定 (InitializeComponent)
(3)実行時に、Form1 側から指定した色設定
(4)マウス操作に応じて、自作コントロール自身が変更する色設定
引用返信 編集キー/
■76030 / inTopicNo.5)  Re[2]: マウスオーバーで色を変えるユーザコントロール
□投稿者/ しゃむこ (2回)-(2015/05/25(Mon) 19:43:03)
No76024 (魔界の仮面弁士 さん) に返信

非常にご丁寧に解説いただきありがとうございます。
とても浅い理解で進めていたので、とても参考になります。

> 【確認事項:その1】
アンビエントなプロパティの考慮は全くできていませんでした。

> 【確認事項:その2】
その通りでした、OnMouseLeaveの対になる、
もとい理想の動きはOnMouseEnterですね。

> 今回、「色」が変更されるタイミングは 4 種類あるかと思います。
整理できていなかったので、混乱していたようです。
(1)はユーザコントロールクラスのSub New()が動いた時、
(2)はForm1のSub New()が動いた時、
(3)はForm1の任意のコードでユーザコントロールクラスのプロパティ値を指定した時、
(4)はイベント発生時、
という理解でよろしいでしょうか?

例えば(1)でMe.BackColorをMe.OriginalBackColorに取得しても、
Form1のデザイナで指定したBackColorが(2)で反映される前のため、(1)の時点では取得できていない。
都度BackColorは変わっていくので、BackColorの取得元、またOrginalBackColorに取得するタイミングは注意しないといけない。

確認事項1とも関連するのですが、
今回はUI、デザインがかっちり決まっているので、パーツとして使用する色も限られており、開発標準化や今後のメンテナンスも考えて、
白系色ボタン、赤系色ボタンのように色変化パターンも決められたユーザコントロールを各種作り、フォーム側でのプロパティの指定は無視する動きにしたいとも思っています。

いろいろ考えて、以下の様にしています。

【実装】
Public Class Palette
Public Shared ReadOnly Ash1 As Color = Color.FromArgb(255, 230, 234, 235) '↑淡 Normal
Public Shared ReadOnly Ash2 As Color = Color.FromArgb(255, 213, 220, 222) '↓濃 Hover
'Active、Enable, etc...
End Class

Public Class RactangleButton
Inherits Windows.Forms.Label
Dim _status As String
Public Sub New()
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Select Case _status
Case "hover"
Me.BackColor = Palette.Ash2
Case Else
Me.BackColor = Palette.Ash1
End Select
End Sub
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
MyBase.OnMouseEnter(e)
_status = "hover"
Me.Refresh()
End Sub
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
MyBase.OnMouseLeave(e)
_status = ""
Me.Refresh()
End Sub
End Class
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -