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