2010年8月30日月曜日

.NET MDI子フォームにToolTipコントロールをプログラムで動的に配置するとメモリーリークが発生する。

おもいっきりハマったYo。・゚・(ノД`)・゚・。

ある画面を開いたり閉じたりしているとOutOfMemoryExceptionが発生します。
タスクマネージャで確認するとGDIオブジェクトの数がどんどん増加していき
1万ちょうどでOutOfMemoryExceptionが発生しました。

原因はMDI子フォームにToolTipコントロールをプログラムで動的に配置するとメモリーリークが発生するそうです。
http://support.microsoft.com/kb/817795/ja

Ver1.1で修正されたのに、Ver2.0で復活したようです。
http://social.msdn.microsoft.com/Forums/ja-JP/vsgeneralja/thread/cb1688ae-2156-4713-92d0-fc3454fc1f49


ToolTipコントロールをプログラムで動的に配置した場合は、
Disposeで開放するかComponentsに追加するようにします。
デザイナで配置した場合はComponentsに追加されるので問題ありません。

2010年8月18日水曜日

.NET TextBoxの枠線の色を変えるには

TextBoxの枠線の色を変えるサンプルです。
BorderStyleプロパティがWindows.Forms.BorderStyle.FixedSingleの場合のみ枠線の色を変えます。

Imports System.ComponentModel

Public Class CsTextBox
    Inherits System.Windows.Forms.TextBox

    Private _BorderColor As Color = System.Drawing.SystemColors.ControlText

    <EditorBrowsable(EditorBrowsableState.Always), Browsable(True), _
      DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), _
      DefaultValue(GetType(Color), "ControlText"), Category("カスタム"), _
      Description("境界線の色です。BorderStyleプロパティがWindows.Forms.BorderStyle.FixedSingleの場合のみ有効です。")> _
      Public Property BorderColor() As Color
        Get
            Return Me._BorderColor
        End Get
        Set(ByVal value As Color)
            Me._BorderColor = value
            Me.Invalidate()
        End Set
    End Property

    Private Const WM_PAINT As Integer = &HF

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Select Case m.Msg
            Case WM_PAINT
                MyBase.WndProc(m)
                Call DrawRectangle()

            Case Else
                MyBase.WndProc(m)

        End Select
    End Sub

    Protected Overridable Sub DrawRectangle()
        If Me.BorderStyle = Windows.Forms.BorderStyle.FixedSingle Then
            Dim g As Graphics = Me.CreateGraphics()
            Dim rect As Rectangle = Me.ClientRectangle
            Dim LinePen As New Pen(Me.BorderColor)
            Try
                g.DrawRectangle(LinePen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1)
            Finally
                LinePen.Dispose()
            End Try
        End If
    End Sub
End Class

2010年8月17日火曜日

.NET 右クリックメニューを表示したコントロールを取得する

右クリックメニューを表示するには
.NET Framework 1.1以前はContextMenuクラスを使用します。
.NET Framework 2.0からはContextMenuStripクラスを使用します。

右クリックメニューを表示したコントロールを取得するには
ToolStripMenuItemのOwnerプロパティよりContextMenuStripを取得し、
ContextMenuStripのSourceControlプロパティより取得できます。



Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
    Handles Me.Load
        Dim lbl As New Label
        lbl.Name = "Label1"
        lbl.Text = lbl.Name
        lbl.Location = New Point(10, 10)
        Me.Controls.Add(lbl)

        Dim cms As New System.Windows.Forms.ContextMenuStrip
        cms.Items.Add("テスト(&T)", Nothing, AddressOf ContextMenuItem_Clicked)
        lbl.ContextMenuStrip = cms
    End Sub

    Private Sub ContextMenuItem_Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim tsi As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
        Dim cms As ContextMenuStrip = DirectCast(tsi.Owner, ContextMenuStrip)
        Dim ctrl As Control = cms.SourceControl
        Console.WriteLine(ctrl.Name)
    End Sub

End Class