TextBoxで行数を表示してみる(サブクラス) VB2005
TextBoxで行数を表示してみる(サブクラス) VB2005
前回はRichTextBoxで行ってみた、行番号を表示するプログラムを
今回はTextBoxで行ってみる。
ポイントは、テキストボックスにはスクロールイベントが無いので
ウィンドウズのメッセージを取得する必要がある事。
そのために、テキストボックスを継承したクラスを作り(昔はサブクラスと言った。今でも言うのかな?)
そのクラスをフォームに配置する必要がある。(本当は配置ではなく置き換えるだけ)
以下に紹介した他にも方法があり、MSのサイトに掲載されていました。
Visual Basic .NET または Visual Basic 2005 を使用して Windows フォームでウィンドウをサブクラス化する方法
※この方法で実装した行番号の表示ですが、マウスでドラッグしてスクロールしている最中は1・2行ズレてしまう欠点がある。
離せば大丈夫なのですが・・・・・
テキストボックスを継承したクラスを作成
Public Class SCTextBox
'テキストボックスを継承する
Inherits TextBox
'メッセージの定数
Private Const WM_VSCROLL As Integer = &H115
'イベントを作成
Public Event TextBoxScroll(ByVal sender As Object, ByVal e As EventArgs)
'ウィンドウズメッセージをキャッチするためにWndProcオーバーライドする
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_VSCROLL
'イベントを起こす
RaiseEvent TextBoxScroll(Me, New EventArgs)
End Select
MyBase.WndProc(m)
End Sub
End Class
|
フォームに作ったSCTextBoxクラスを配置する
フォームにテキストボックスを継承したクラスを配置する手順ですが、
まず、通常のテキストボックスをフォームに貼り付けて、
そのあと、「ソリューションエクスプローラ(ファイルが並んで表示されている窓)」でファイルを全て表示するモードに切り替えて、
Form.Designer.vb
を表示させ、開きます。
で、下の赤字で書いている二箇所を、作成した「SCTextBox」に書き換えます。
やっていることは、通常のテキストボックスを自作のテキストボックスに置き換えているという作業。
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form2
Inherits System.Windows.Forms.Form
'フォームがコンポーネントの一覧をクリーンアップするために dispose をオーバーライドします。
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Windows フォーム デザイナで必要です。
Private components As System.ComponentModel.IContainer
'メモ: 以下のプロシージャは Windows フォーム デザイナで必要です。
'Windows フォーム デザイナを使用して変更できます。
'コード エディタを使って変更しないでください。
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TextBox1 = New MyEdit2.SCTextBox のように書き換える
Me.ScTextBox1 = New MyEdit2.SCTextBox
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Anchor = System.Windows.Forms.AnchorStyles.None
Me.TextBox1.Location = New System.Drawing.Point(68, 3)
Me.TextBox1.Multiline = True
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both
Me.TextBox1.Size = New System.Drawing.Size(441, 248)
Me.TextBox1.TabIndex = 0
'
'ScTextBox1
'
Me.ScTextBox1.Anchor = System.Windows.Forms.AnchorStyles.None
Me.ScTextBox1.Location = New System.Drawing.Point(3, 3)
Me.ScTextBox1.Multiline = True
Me.ScTextBox1.Name = "ScTextBox1"
Me.ScTextBox1.Size = New System.Drawing.Size(59, 248)
Me.ScTextBox1.TabIndex = 1
'
'Form2
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 12.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(521, 263)
Me.Controls.Add(Me.ScTextBox1)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form2"
Me.Text = "Form2"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
'Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents TextBox1 As SCTextBox 'のように書き換える
Friend WithEvents ScTextBox1 As MyEdit2.SCTextBox
End Class
|
残るはフォームにプログラムを書く
Public Class Form2
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Integer, ByVal MSG As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const EM_GETFIRSTVISIBLELINE As Short = &HCES
Private Sub TextBox1_TextBoxScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextBoxScroll
'クラスで作成したイベント
' Debug.Print("sssss")
SetLineNo()
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
SetLineNo()
End Sub
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
SetLineNo()
End Sub
Private Sub SetLineNo()
'行番号をふる
Dim row As Integer
'先頭の行数を取得する
row = SendMessage(TextBox1.Handle, EM_GETFIRSTVISIBLELINE, 0, 0) + 1
Me.ScTextBox1.Text = row.ToString
Dim i As Integer
Dim lines As String = ""
Do Until i = 60 '一度に表示できる行数が60ぐらいとして設定 モニタによるので 120でも可
If lines = "" Then
lines = GetFormat(i + row)
Else
lines = lines & vbCrLf & GetFormat(i + row)
End If
i = i + 1
Loop
Me.ScTextBox1.Text = lines
End Sub
Private Function GetFormat(ByVal row As Integer) As String
'文字を5桁右寄せにする
Dim i As Integer
i = Len(row.ToString)
Select Case i
Case 1
Return " " & row.ToString
Case 2
Return " " & row.ToString
Case 3
Return " " & row.ToString
Case Else
Return " " & row.ToString
End Select
End Function
End Class
|
|