VBオブジェクト指向プログラミング講座 第11回 手続きも関数もオブジェクト
突然ですが、オブジェクト指向プログラミングというだけあって、VBでは手続きも関数もオブジェクトとして扱えます。さっそく確認してみましょう。
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Shapes
Friend Interface IIdentifier
ReadOnly Property Number() As Integer
End Interface
Friend Class MessageWindow
Inherits Window
Implements IIdentifier
'このウィンドウの名前
Private m_id As String
Public ReadOnly Property Number As Integer _
Implements IIdentifier.Number
Get
Return Me.m_id
End Get
End Property
'インスタンスを識別するための定義
Private Shared NextID As Integer
'Windowのサイズを指定するための定義
Private Shared random As Random =
New Random(DateTime.Now.Ticks Mod Integer.MaxValue)
'使用するメッセージ
Private m_message As String
Private Function CheckMessage(ByVal value As String) As Boolean
If value Is Nothing OrElse value.Length = 0 Then
Return False
Else
Return True
End If
End Function
Public Property Message() As String
Get
Return Me.m_message
End Get
Private Set(value As String)
If Me.CheckMessage(value) = False Then
Throw New ArgumentException(
"1文字以上の文字列を指定して下さい。")
End If
Me.m_message = value
End Set
End Property
'各種コントロール
Dim input As TextBlock
Dim text As TextBox
'メッセージを指定してインスタンスを生成する
Public Sub New(Optional ByVal msg As String = "Hello World")
'Windowの設定
Me.Height = random.Next(100, 1000)
Me.Width = random.Next(100, 1000)
Me.Message = msg
'-------------------- ボタン上のコントロール --------------------
Me.input = New TextBlock()
text = New TextBox()
Dim panel As New StackPanel()
'作成ボタン
Dim createBtn As New Button()
createBtn.Content = "作成"
Dim createBtnAction =
Sub(sender As Object, e As KeyEventArgs)
If e.Key = Key.Enter Then
createBtn.Focus()
e.Handled = True
End If
End Sub
AddHandler text.KeyDown, createBtnAction
createBtn.ToolTip = createBtnAction.GetType().Name &
"型のオブジェクトが関連付けられています。"
'検索ボタン
Dim searchBtn = New Button()
searchBtn.Content = "番号検索"
AddHandler searchBtn.Click, AddressOf SearchWindow
'名前表示ボタン
Dim nameBtn As New Button()
nameBtn.Content = "番号は?"
Dim nameBtnAction =
Sub(sender As Object, e As RoutedEventArgs)
MessageBox.Show(
"私は" & Me.Number & "号",
"識別子",
MessageBoxButton.OK,
MessageBoxImage.Information)
e.Handled = True
End Sub
AddHandler nameBtn.Click, nameBtnAction
nameBtn.ToolTip = nameBtnAction.GetType().Name &
"型のオブジェクトが関連付けられています。"
Dim endBtn As New Button()
endBtn.Content = "終了"
Dim endBtnAction = Sub() Application.Current.Shutdown()
AddHandler endBtn.Click, endBtnAction
endBtn.ToolTip = endBtnAction.GetType().Name &
"型のオブジェクトが関連付けられています。"
'------------------------------------------------------------------
panel.Children.Add(input)
panel.Children.Add(text)
panel.Children.Add(createBtn)
panel.Children.Add(searchBtn)
panel.Children.Add(nameBtn)
panel.Children.Add(endBtn)
'ボタン
Dim btn = CreateEllipseButton()
btn.Content = panel
Me.Content = btn
AddHandler btn.Click, Sub() Me.CreateWindow()
AddHandler btn.KeyDown, Sub() text.Focus()
'その他の処理
Me.SetMessages()
Me.m_id = MessageWindow.NextID
MessageWindow.NextID += 1
End Sub
'指定した番号を持つウィンドウを検索
Private Sub SearchWindow(sender As Object, e As RoutedEventArgs)
Dim value As Integer
If Integer.TryParse(text.Text, value) = True Then
For Each win In Application.Current.Windows
Dim w As MessageWindow = CType(win, MessageWindow)
If w.Number = value Then
MessageBox.Show(
"見つかりました♪",
"検索結果",
MessageBoxButton.OK,
MessageBoxImage.Information)
e.Handled = True
w.Activate()
Exit Sub
End If
Next
End If
MessageBox.Show(
"指定のウィンドウはありません。",
"検索結果",
MessageBoxButton.OK,
MessageBoxImage.Exclamation)
e.Handled = True
End Sub
'新しいウインドウを作成する
Private Sub CreateWindow()
Dim win As MessageWindow
If Me.CheckMessage(Me.text.Text) = False Then
win = New MessageWindow()
Else
win = New MessageWindow(Me.text.Text)
End If
win.Show()
Dim btn As Button = CType(win.Content, Button)
btn.Focus()
End Sub
'指定されたメッセージを各種要素に反映する
Private Sub SetMessages()
Dim str As String = Me.Message
Me.Title = str
input.Text = str
End Sub
'楕円ボタンを作成
Private Function CreateEllipseButton() As Button
'原型となるボタン
Dim btn As Button = New Button()
'ファクトリーオブジェクトを用意
Dim mainFact As FrameworkElementFactory =
New FrameworkElementFactory(GetType(Grid))
'楕円を用意
Dim brush As LinearGradientBrush = New LinearGradientBrush()
brush.EndPoint = New Point(0, 1)
brush.GradientStops.Add(
New GradientStop(Color.FromArgb(100, 255, 255, 0), 0))
brush.GradientStops.Add(
New GradientStop(Color.FromArgb(255, 0, 255, 0), 1))
Dim ellipseFact As FrameworkElementFactory =
New FrameworkElementFactory(GetType(Ellipse))
ellipseFact.SetValue(
Ellipse.StrokeThicknessProperty, 5.0)
ellipseFact.SetValue(
Ellipse.FillProperty, brush)
mainFact.AppendChild(ellipseFact)
'楕円の位置
Dim position As FrameworkElementFactory =
New FrameworkElementFactory(GetType(ContentPresenter))
position.SetValue(
ContentPresenter.HorizontalAlignmentProperty,
HorizontalAlignment.Center)
position.SetValue(
ContentPresenter.VerticalAlignmentProperty,
VerticalAlignment.Center)
mainFact.AppendChild(position)
'ボタンにテンプレートを適用
Dim tmp As ControlTemplate =
New ControlTemplate(GetType(Button))
tmp.VisualTree = mainFact
btn.Template = tmp
Return btn
End Function
End Class
ボタンのイベントを指定する部分(AddHandler)に注目してください。今までは直接指定していましたが、変数を宣言して手続きと関数を割り当てることもできます。この変数の型が手続きの型です。サンプルをビルド後実行すると、手続きの型を見られます。手続きの型を見ると、Delegateとなっている点に注目してください。手続きと関数と同様の働きをする不思議なオブジェクトの正体はデリゲートです。デリゲートオブジェクトが、手続きと関数をオブジェクトして扱うことを可能としています。続く...