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

Color.Transparentに書いた描画を塗りつぶす

環境/言語:[Windows 7/VB.NET 2010]
分類:[.NET]

FormにTabコントロールを貼りその上にPanelコントロールを貼っています。
更にPanelコントロールにはCheckBox、TextBox、Labelを張り貼っています。

BackColorはデフォルトのまま変更していないので
FormのBackColorは System.Drawing.SystemColors.Controlで
TabコントロールとPanelコントロールのBackColorは
System.Drawing.Color.Transparentとなっており、
私の環境で見るとFormは淡い灰色、Tabコントロールは白で見えています。


以下のソースを書いたところ、CheckBox1_Leaveが思い描いた通りの動作となりません。

思い描いた通りの動作 → 「CheckBox1のEnterで枠が描画されLeaveで枠が消える」

そこでCheckBox1_Leaveの New SolidBrush(Panel1.BackColor) を
New SolidBrush(TabPage1.BackColor) としました。すると枠は消えますが、
枠の内側がSystemColors.Controlで塗り潰されてしまいました。

仕方が無いのでソースは替えずTabコントロールとPanelコントロールのBackColorを
System.Drawing.SystemColors.Controlとしましたが、何だか納得がいきません。

何とかBackColor = System.Drawing.Color.Transparentに書いた描画を塗りつぶすことは
出来ないものでしょうか?

***** 以下ソース **************************************************

Imports System.Text
Imports System.Drawing.Drawing2D

Public Class Form1

Private canvas As Bitmap
Private g As Graphics
Private rAngle As Rectangle

Private CONS_SHIFT_JIS As String = "Shift_JIS"

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

Me.Font = New Font("MS ゴシック", 9.75!)
Me.DoubleBuffered = True


TabPage1.BackColor = Color.Transparent

With Panel1
.Location = New Point(0, 0)
.Size = New System.Drawing.Size(760, 500)

canvas = New Bitmap(.Width, .Height)
g = Graphics.FromImage(canvas)
g.SmoothingMode = SmoothingMode.HighQuality

.BackColor = Color.Transparent
.BackgroundImageLayout = ImageLayout.Center
.BackgroundImage = canvas
End With



With CheckBox1
.Location = New System.Drawing.Point(10, 14)
.Size = New System.Drawing.Size(15, 14)
.Text = vbNullString
End With

With TextBox1
.Location = New System.Drawing.Point(30, 10)
.Size = New System.Drawing.Size(73, 20)
.MaxLength = 10
.Text = "名前"
.TabStop = False
End With

With Label1
.Location = New System.Drawing.Point(105, 14)
.Size = New System.Drawing.Size(77, 13)
.Text = "を表示する"
End With



rAngle = New Rectangle(TextBox1.Left - 4, TextBox1.Top - 2, Label1.Left + Label1.Width - TextBox1.Left + 5, TextBox1.Height + 4)

End Sub

Private Sub CheckBox1_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles CheckBox1.Enter
'枠を描く
ControlPaint.DrawFocusRectangle(g, rAngle)
Panel1.Invalidate()
End Sub

Private Sub CheckBox1_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles CheckBox1.Leave
'枠を消す
g.FillRectangle(New SolidBrush(Panel1.BackColor), rAngle.X - 1, rAngle.Y - 1, rAngle.Width + 2, rAngle.Height + 2)
Panel1.Invalidate()
End Sub

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Dim _index As Integer = TextBox1.SelectionStart
Dim _Value As String = TextBox1.Text

'MaxLendthを超えた入力は取り消す
If fncMaxLength(_index, _Value, TextBox1.MaxLength) Then
TextBox1.Text = _Value
TextBox1.SelectionStart = _index
End If

End Sub

Private Sub Label1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Label1.Click
'ラベルをクリックした時もチェックボックスクリックと同じ処理
CheckBox1.Checked = Not CheckBox1.Checked
End Sub

Public Function fncGetTextLength(ByVal pValue As String) As Integer

Return Encoding.GetEncoding(CONS_SHIFT_JIS).GetByteCount(pValue)

End Function

Public Function fncMaxLength(ByRef pIndex As Integer, ByRef pValue As String, ByVal pMaxlength As Integer) As Boolean
Dim _length As Integer = fncGetTextLength(pValue)

'MaxLendth以上の入力を許さない
If _length > pMaxlength Then
Do Until _length <= pMaxlength
pIndex -= 1
pValue = pValue.Remove(pIndex, 1)
_length = fncGetTextLength(pValue)
Loop
Return True
Else
Return False
End If
End Function

End Class
試していませんが、次のプロパティについて調べてみてはいかがでしょうか。

http://msdn.microsoft.com/ja-jp/library/system.drawing.graphics.compositingmode.aspx
http://msdn.microsoft.com/ja-jp/library/system.drawing.drawing2d.compositingmode.aspx


規定値の SourceOver は色を混ぜるという動作を指します。
Color の Red などはα値がない(=不透明)なので上書きと等しくなりますが、半透明の色を描いたときに元の色と混ぜる動きになっています。
今回の Transparent は混ぜた結果、元の色と同じになる効果になるので、SourceCopy を指定して色をコピー(上書き)する動作を指定する必要があるはずです。
結果の報告が遅れて大変申し訳ありません。

g.CompositingMode = CompositingMode.SourceCopy

を追記することにより望んだ動作をさせることが出来ました。
有難うございます。

何となくですけど、VB6でBitBlt APIを使用する際に指定した、
ラスタ オペレーション定数のvbSrcCopyみたいなもんですかね?
解決済み!
■No31800に返信(ぴちさんの記事)
> 何となくですけど、VB6でBitBlt APIを使用する際に指定した、
> ラスタ オペレーション定数のvbSrcCopyみたいなもんですかね?

そうです。
実際に CompositingMode.SourceCopy の説明と vbSrcCopy の説明を見比べると見えてくると思います。
解決済み!

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