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

「DateTimePicker」の背景色が変更できない

環境/言語:[VB2005,vista]
分類:[.NET]

いつも参考にさせて頂いております。

「DateTimePicker」の背景色が変更出来ない件についてネットに載っていた
下記内容を組み込みました。

「DateTimePicker」を継承したコントロールを作成し、

Private Const WM_ERASEBKGND As Integer = &H14
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_ERASEBKGND Then
Dim g As Graphics = Graphics.FromHdc(m.WParam)
Dim backBrush As New SolidBrush(Me.BackColor)
g.FillRectangle(backBrush, MyBase.ClientRectangle)
backBrush.Dispose()
g.Dispose()
Return
End If
MyBase.WndProc(m)
End Sub
↑上記処理を追加しました。

テスト時は問題なく変更出来るのを確認できましたが、本番環境に組み込みと
変更されなくなりました。
何が違うのかいろいろためしてみましたが、本番環境に組み込まれている
「Application.EnableVisualStyles()」が原因のようです。

「Application.EnableVisualStyles()」を止めてしまうと画面がまったく
違ったものになってしまうので出来れば避けたいと考えています。
何か他の解決策はないでしょうか?
2009/01/12(Mon) 00:23:31 編集(投稿者)

私のPC(XPHome)の場合、Application.EnableVisualStyles()の有無に関わらず、
hana さんのコードでうまくいきました。
しかし、hana さんのPCで動作しないとのことなので、代替案を考えてみました。
非常に苦しいコードですが、とりあえず以下のコードで試してみてください。
(私のPCでは動作しました)
 
# 2009/01/12コードを修正
Public Class DateTimePickerEx_ver2
    Inherits DateTimePicker
 
    Private ReadOnly WM_PAINT As Integer = &HF
    Private WithEvents Timer1 As New Timer
 
    Public Sub New()
        Me.Timer1.Interval = 100 ' ← 適宜修正してください
        Me.Timer1.Start()
    End Sub
 
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing = True Then
                Me.Timer1.Stop()
                Me.Timer1.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        ' ↓先に、既定の描画処理をさせる
        MyBase.WndProc(m)
        If m.Msg = Me.WM_PAINT Then
            Me.Redraw()
        End If
    End Sub
 
    Public Function GetControlImage() As Bitmap
        ' 自分自身の画像をBitmapにコピー
        Dim bmp As New Bitmap(Me.Width, Me.Height)
        Me.DrawToBitmap(bmp, New Rectangle(0, 0, Me.Width, Me.Height))
        ' Bitmapの背景色をMe.BackColorに変更する
        Using g As Graphics = Graphics.FromImage(bmp)
            Dim cm As Imaging.ColorMap() = {New Imaging.ColorMap}
            cm(0).OldColor = SystemColors.Window
            cm(0).NewColor = Me.BackColor
            Dim ia As New Imaging.ImageAttributes()
            ia.SetRemapTable(cm)
            Dim r As New Rectangle(0, 0, bmp.Width, bmp.Height)
            g.DrawImage(bmp, New Rectangle(0, 0, bmp.Width, bmp.Height), _
                        0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, ia)
        End Using
 
        Return bmp
    End Function
 
    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        ' ↓をコメントアウトしても、背景色が変更されますか?(Yesなら、タイマー不要)
        Me.Redraw()
    End Sub
 
    Private Sub Redraw()
        ' Bitmapを自分の上に描画する
        Dim bsz As Size = SystemInformation.Border3DSize
        Using g As Graphics = Me.CreateGraphics, bmp As Bitmap = Me.GetControlImage
            g.DrawImage(bmp, -bsz.Width, -bsz.Height)
        End Using
    End Sub
 
End Class
■No23771に返信(H.K.R.さんの記事)
> 2009/01/12(Mon) 00:23:31 編集(投稿者)

H.K.R.さん いつもありがとうございます。
解決しました。
フォーカス取得で背景色を変えるようにするようにしていますが、
このコントロールの使用を半ばあきらめていました。
本当にありがとうございます。

ちなみにタイマーを外しても動作しました。

> 私のPC(XPHome)の場合、Application.EnableVisualStyles()の有無に関わらず、
> hana さんのコードでうまくいきました。
> しかし、hana さんのPCで動作しないとのことなので、代替案を考えてみました。

私の環境はvista(Business)です。やはり動作しません。
XPでの確認環境も後で作るつもりですが、環境の違いなのでしょうか。
いろいろと確認作業が必要のようです。

あと、
コントロールが影付き(コントロールの下側と右側が二重線のように)になって
しまいますが、これはどうしようもないのでしょうか?
解決済み!
> コントロールが影付き(コントロールの下側と右側が二重線のように)になって
> しまいますが、これはどうしようもないのでしょうか?
私のPCでは、ぴったりと位置が合っていますが、もし輪郭線が2重に表示される場合は、とりあえず、私のコードのRedrawメソッド内のg.DrawImageの引数をいじってみてください。

P.S.
hana さんの最初のコードで、MyBase.WndProc(m)をメソッドの先頭に移動するとどうなるでしょうか?
解決済み!
■No23786に返信(H.K.R.さんの記事)
>>コントロールが影付き(コントロールの下側と右側が二重線のように)になって
>>しまいますが、これはどうしようもないのでしょうか?
> 私のPCでは、ぴったりと位置が合っていますが、もし輪郭線が2重に表示される場合は、とりあえず、私のコードのRedrawメソッド内のg.DrawImageの引数をいじってみてください。

返信ありがとうございます。
指摘のとおり引数を調整(+2)したらぴったりの位置になりました。

Private Sub Redraw()
' Bitmapを自分の上に描画する
Dim bsz As Size = SystemInformation.Border3DSize
Using g As Graphics = Me.CreateGraphics, bmp As Bitmap = e.GetControlImage
g.DrawImage(bmp, -bsz.Width + 2, -bsz.Height + 2) '←調整(+2)
End Using
End Sub

ただ、PC環境によって違いがでてくるかも知れません。
その時は環境による調整ロジックを追加します。たぶん?

> P.S.
> hana さんの最初のコードで、MyBase.WndProc(m)をメソッドの先頭に移動するとどうなるでしょうか?

元に戻して試してみましたが、やはりXP Visualスタイルを有効にすると
背景色が変わりません。
なのでH.K.R.さんのコードで進めていきたいと思います。
いろいろありがとうございました。
すみません。
解決済みにするのを忘れました。
解決済み!

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