C:\Windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe /target:winexe /out:ChatApp.exe ChatApp.vb /r:System.Windows.Forms.dll
 

Imports System.IO

Imports System.Threading

Imports System.Windows.Forms

Imports System.Drawing

Imports System.Collections.Generic ' Dictionaryのためのインポート

 

Public Class ChatApp

    Inherits Form

 

    ' UI要素

    Private userName As String

    Private messageLog As RichTextBox ' RichTextBoxで色付きテキストを表示

    Private messageBox As TextBox

    Private sendButton As Button

    Private Shared logFilePath As String = "chatlog.txt"

    Private logWatcher As Thread

 

    ' ユーザーごとの色を管理するディクショナリ

    Private Shared userColors As New Dictionary(Of String, Color)

 

    ' 自分で送信した最後のメッセージを保持

    Private lastSentMessage As String = ""

 

    Public Sub New(user As String)

        ' ユーザー名を設定

        userName = user

 

        ' UIのセットアップ

        Me.Text = "Simple Chat App"

        Me.Width = 600

        Me.Height = 400

 

        ' メッセージログの表示領域

        messageLog = New RichTextBox()

        messageLog.Multiline = True

        messageLog.Dock = DockStyle.Top

        messageLog.Height = 250

        messageLog.ReadOnly = True

        messageLog.BackColor = Color.White

        messageLog.ForeColor = Color.Black

        Me.Controls.Add(messageLog)

 

        ' メッセージ入力ボックス

        messageBox = New TextBox()

        messageBox.Multiline = False

        messageBox.Dock = DockStyle.Bottom

        AddHandler messageBox.KeyDown, AddressOf HandleEnterKeyPress

        Me.Controls.Add(messageBox)

 

        ' 送信ボタン

        sendButton = New Button()

        sendButton.Text = "Send"

        sendButton.Dock = DockStyle.Bottom

        AddHandler sendButton.Click, AddressOf SendMessage

        Me.Controls.Add(sendButton)

 

        ' ユーザーの色を割り当て

        AssignUserColor(user)

 

        ' 過去のログを読み込んで表示

        If File.Exists(logFilePath) Then

            LoadExistingLog()

        End If

 

        ' ログの自動読み込みスレッドを開始

        logWatcher = New Thread(AddressOf WatchLogUpdates)

        logWatcher.IsBackground = True

        logWatcher.Start()

    End Sub

 

    ' ユーザーごとに色を割り当てる

    Private Sub AssignUserColor(user As String)

        If Not userColors.ContainsKey(user) Then

            ' ランダムな色を割り当てる

            Dim rand As New Random(user.GetHashCode())

            Dim userColor As Color = Color.FromArgb(rand.Next(50, 200), rand.Next(50, 200), rand.Next(50, 200))

            userColors(user) = userColor

        End If

    End Sub

 

    ' Enterキーでメッセージ送信

    Private Sub HandleEnterKeyPress(sender As Object, e As KeyEventArgs)

        If e.KeyCode = Keys.Enter Then

            SendMessage(sender, e)

            e.SuppressKeyPress = True ' Enterキーが押されても改行しないようにする

        End If

    End Sub

 

    ' メッセージを送信してログに追加

    Private Sub SendMessage(sender As Object, e As EventArgs)

        Dim message As String = messageBox.Text

        If Not String.IsNullOrEmpty(message) Then

            ' 文字列補間の代わりに文字列連結を使用

            Dim logEntry As String = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") & " " & userName & ": " & message & Environment.NewLine

 

            ' ファイルに保存

            File.AppendAllText(logFilePath, logEntry)

 

            ' メッセージログに追加(自動読み込みで重複表示されないようにする)

            lastSentMessage = logEntry ' 最後に送信したメッセージを記憶

            AppendMessageToLog(userName, message)

 

            ' メッセージボックスをクリア

            messageBox.Clear()

            ' メッセージボックスを再びアクティブにする

            messageBox.Focus()

        End If

    End Sub

 

    ' メッセージログにユーザーごとの色でメッセージを追加し、自動スクロール

    Private Sub AppendMessageToLog(user As String, message As String)

        If userColors.ContainsKey(user) Then

            Dim timestamp As String = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")

            ' 文字列補間の代わりに連結

            Dim fullMessage As String = timestamp & " " & user & ": " & message & Environment.NewLine

 

            messageLog.SelectionStart = messageLog.TextLength

            messageLog.SelectionLength = 0

            messageLog.SelectionColor = userColors(user)

            messageLog.AppendText(fullMessage)

            messageLog.SelectionColor = messageLog.ForeColor ' デフォルトの色に戻す

 

            ' 新しいメッセージが追加されたらスクロール

            messageLog.ScrollToCaret()

        End If

    End Sub

 

    ' ログファイルの変更を監視し、更新があればメッセージログに反映

    Private Sub WatchLogUpdates()

        Dim lastReadLength As Long = 0

 

        ' 初期状態としてファイルの現在の長さを取得

        If File.Exists(logFilePath) Then

            lastReadLength = New FileInfo(logFilePath).Length

        End If

 

        While True

            Thread.Sleep(1000) ' 1秒ごとにチェック

 

            ' ファイルの長さを確認し、変更があれば読み込む

            Dim currentLength As Long = New FileInfo(logFilePath).Length

            If currentLength > lastReadLength Then

                ' 新しいテキストを読み込んで表示

                Dim newText As String = ReadNewLogEntries(lastReadLength)

                If Not String.IsNullOrEmpty(newText) Then

                    Me.Invoke(New MethodInvoker(Sub() AppendLogWithColors(newText)))

                End If

                lastReadLength = currentLength

            End If

        End While

    End Sub

 

    ' ログファイルから新規エントリを読み込む

    Private Function ReadNewLogEntries(lastReadLength As Long) As String

        Using fs As New FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)

            fs.Seek(lastReadLength, SeekOrigin.Begin)

            Using sr As New StreamReader(fs)

                Return sr.ReadToEnd()

            End Using

        End Using

    End Function

 

    ' ログを色付きで表示し、自動スクロール

    Private Sub AppendLogWithColors(newText As String)

        Dim logEntries As String() = newText.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)

        For Each entry In logEntries

            ' 最後に送信したメッセージと一致する場合はスキップ

            If entry.Trim() = lastSentMessage.Trim() Then

                Continue For

            End If

 

            ' ユーザー名を抽出して色を割り当て

            Dim parts As String() = entry.Split(New String() {": "}, 2, StringSplitOptions.None)

            If parts.Length = 2 Then

                Dim user As String = parts(0).Substring(20).Trim() ' タイムスタンプを除いてユーザー名を取得

                Dim message As String = parts(1).Trim()

 

                ' ユーザーの色を割り当ててログに追加

                If Not userColors.ContainsKey(user) Then

                    AssignUserColor(user)

                End If

                AppendMessageToLog(user, message)

            End If

        Next

 

        ' 新しいログが追加されたらスクロール

        messageLog.ScrollToCaret()

    End Sub

 

    ' 過去のログを色付きで読み込む

    Private Sub LoadExistingLog()

        Dim logEntries As String = File.ReadAllText(logFilePath)

        AppendLogWithColors(logEntries)

    End Sub

 

    <STAThread>

    Public Shared Sub Main()

        Application.EnableVisualStyles()

 

        ' ユーザー名を入力するフォーム

        Dim userName As String = InputBox("Enter your name:", "User Registration", "User")

        If String.IsNullOrEmpty(userName) Then

            ' MessageBoxの呼び出し方法を修正

            System.Windows.Forms.MessageBox.Show("A user name is required to start the chat.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)

            Return

        End If

 

        ' チャットアプリケーションのインスタンスを作成

        Application.Run(New ChatApp(userName))

    End Sub

End Class