add chatserver & client
This commit is contained in:
184
Project/Dialog/fChat.Designer.cs
generated
Normal file
184
Project/Dialog/fChat.Designer.cs
generated
Normal file
@@ -0,0 +1,184 @@
|
||||
namespace Project.Dialog
|
||||
{
|
||||
partial class fChat
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.txtChatDisplay = new System.Windows.Forms.TextBox();
|
||||
this.txtInput = new System.Windows.Forms.TextBox();
|
||||
this.btnSend = new System.Windows.Forms.Button();
|
||||
this.lblStatus = new System.Windows.Forms.Label();
|
||||
this.timerStatus = new System.Windows.Forms.Timer(this.components);
|
||||
this.panelTop = new System.Windows.Forms.Panel();
|
||||
this.panelBottom = new System.Windows.Forms.Panel();
|
||||
this.lblRecipient = new System.Windows.Forms.Label();
|
||||
this.cboRecipient = new System.Windows.Forms.ComboBox();
|
||||
this.panelTop.SuspendLayout();
|
||||
this.panelBottom.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// txtChatDisplay
|
||||
//
|
||||
this.txtChatDisplay.BackColor = System.Drawing.Color.White;
|
||||
this.txtChatDisplay.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtChatDisplay.Font = new System.Drawing.Font("Consolas", 9F);
|
||||
this.txtChatDisplay.Location = new System.Drawing.Point(0, 30);
|
||||
this.txtChatDisplay.Multiline = true;
|
||||
this.txtChatDisplay.Name = "txtChatDisplay";
|
||||
this.txtChatDisplay.ReadOnly = true;
|
||||
this.txtChatDisplay.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtChatDisplay.Size = new System.Drawing.Size(500, 340);
|
||||
this.txtChatDisplay.TabIndex = 0;
|
||||
//
|
||||
// txtInput
|
||||
//
|
||||
this.txtInput.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.txtInput.Font = new System.Drawing.Font("Malgun Gothic", 9F);
|
||||
this.txtInput.Location = new System.Drawing.Point(0, 0);
|
||||
this.txtInput.Name = "txtInput";
|
||||
this.txtInput.Size = new System.Drawing.Size(420, 23);
|
||||
this.txtInput.TabIndex = 1;
|
||||
this.txtInput.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtInput_KeyDown);
|
||||
//
|
||||
// btnSend
|
||||
//
|
||||
this.btnSend.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.btnSend.Location = new System.Drawing.Point(420, 0);
|
||||
this.btnSend.Name = "btnSend";
|
||||
this.btnSend.Size = new System.Drawing.Size(80, 30);
|
||||
this.btnSend.TabIndex = 2;
|
||||
this.btnSend.Text = "Send";
|
||||
this.btnSend.UseVisualStyleBackColor = true;
|
||||
this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
|
||||
//
|
||||
// lblStatus
|
||||
//
|
||||
this.lblStatus.AutoSize = true;
|
||||
this.lblStatus.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.lblStatus.Font = new System.Drawing.Font("Malgun Gothic", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.lblStatus.ForeColor = System.Drawing.Color.Green;
|
||||
this.lblStatus.Location = new System.Drawing.Point(5, 5);
|
||||
this.lblStatus.Name = "lblStatus";
|
||||
this.lblStatus.Padding = new System.Windows.Forms.Padding(5);
|
||||
this.lblStatus.Size = new System.Drawing.Size(83, 25);
|
||||
this.lblStatus.TabIndex = 3;
|
||||
this.lblStatus.Text = "Connected";
|
||||
this.lblStatus.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// timerStatus
|
||||
//
|
||||
this.timerStatus.Enabled = true;
|
||||
this.timerStatus.Interval = 1000;
|
||||
this.timerStatus.Tick += new System.EventHandler(this.timerStatus_Tick);
|
||||
//
|
||||
// lblRecipient
|
||||
//
|
||||
this.lblRecipient.AutoSize = true;
|
||||
this.lblRecipient.Dock = System.Windows.Forms.DockStyle.Left;
|
||||
this.lblRecipient.Font = new System.Drawing.Font("Malgun Gothic", 9F);
|
||||
this.lblRecipient.Location = new System.Drawing.Point(5, 5);
|
||||
this.lblRecipient.Name = "lblRecipient";
|
||||
this.lblRecipient.Padding = new System.Windows.Forms.Padding(0, 5, 5, 0);
|
||||
this.lblRecipient.Size = new System.Drawing.Size(45, 20);
|
||||
this.lblRecipient.TabIndex = 5;
|
||||
this.lblRecipient.Text = "To:";
|
||||
this.lblRecipient.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// cboRecipient
|
||||
//
|
||||
this.cboRecipient.Dock = System.Windows.Forms.DockStyle.Left;
|
||||
this.cboRecipient.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboRecipient.Font = new System.Drawing.Font("Malgun Gothic", 9F);
|
||||
this.cboRecipient.FormattingEnabled = true;
|
||||
this.cboRecipient.Location = new System.Drawing.Point(50, 5);
|
||||
this.cboRecipient.Name = "cboRecipient";
|
||||
this.cboRecipient.Size = new System.Drawing.Size(200, 23);
|
||||
this.cboRecipient.TabIndex = 6;
|
||||
//
|
||||
// panelTop
|
||||
//
|
||||
this.panelTop.Controls.Add(this.cboRecipient);
|
||||
this.panelTop.Controls.Add(this.lblRecipient);
|
||||
this.panelTop.Controls.Add(this.lblStatus);
|
||||
this.panelTop.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panelTop.Location = new System.Drawing.Point(0, 0);
|
||||
this.panelTop.Name = "panelTop";
|
||||
this.panelTop.Padding = new System.Windows.Forms.Padding(5);
|
||||
this.panelTop.Size = new System.Drawing.Size(500, 30);
|
||||
this.panelTop.TabIndex = 4;
|
||||
//
|
||||
// panelBottom
|
||||
//
|
||||
this.panelBottom.Controls.Add(this.txtInput);
|
||||
this.panelBottom.Controls.Add(this.btnSend);
|
||||
this.panelBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.panelBottom.Location = new System.Drawing.Point(0, 370);
|
||||
this.panelBottom.Name = "panelBottom";
|
||||
this.panelBottom.Size = new System.Drawing.Size(500, 30);
|
||||
this.panelBottom.TabIndex = 5;
|
||||
//
|
||||
// fChat
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(500, 400);
|
||||
this.Controls.Add(this.txtChatDisplay);
|
||||
this.Controls.Add(this.panelBottom);
|
||||
this.Controls.Add(this.panelTop);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
|
||||
this.KeyPreview = true;
|
||||
this.MaximizeBox = true;
|
||||
this.MinimizeBox = true;
|
||||
this.MinimumSize = new System.Drawing.Size(400, 300);
|
||||
this.Name = "fChat";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Chat";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.fChat_FormClosing);
|
||||
this.Load += new System.EventHandler(this.fChat_Load);
|
||||
this.panelTop.ResumeLayout(false);
|
||||
this.panelTop.PerformLayout();
|
||||
this.panelBottom.ResumeLayout(false);
|
||||
this.panelBottom.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox txtChatDisplay;
|
||||
private System.Windows.Forms.TextBox txtInput;
|
||||
private System.Windows.Forms.Button btnSend;
|
||||
private System.Windows.Forms.Label lblStatus;
|
||||
private System.Windows.Forms.Timer timerStatus;
|
||||
private System.Windows.Forms.Panel panelTop;
|
||||
private System.Windows.Forms.Panel panelBottom;
|
||||
private System.Windows.Forms.Label lblRecipient;
|
||||
private System.Windows.Forms.ComboBox cboRecipient;
|
||||
}
|
||||
}
|
||||
412
Project/Dialog/fChat.cs
Normal file
412
Project/Dialog/fChat.cs
Normal file
@@ -0,0 +1,412 @@
|
||||
using FCOMMON;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Project.Dialog
|
||||
{
|
||||
/// <summary>
|
||||
/// User info for recipient selection
|
||||
/// </summary>
|
||||
public class ChatUserInfo
|
||||
{
|
||||
public string EmployeeId { get; set; }
|
||||
public string NickName { get; set; }
|
||||
public string UserGroup { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{NickName} ({EmployeeId})";
|
||||
}
|
||||
}
|
||||
|
||||
public partial class fChat : fBase
|
||||
{
|
||||
private ChatClientService chatService;
|
||||
private string targetEmployeeId;
|
||||
private string targetNickName;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for new chat or specific recipient
|
||||
/// </summary>
|
||||
public fChat(ChatClientService service, string targetEmployeeId = null, string targetNickName = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.chatService = service;
|
||||
this.targetEmployeeId = targetEmployeeId;
|
||||
this.targetNickName = targetNickName;
|
||||
this.KeyDown += (s, e) => { if (e.KeyCode == Keys.Escape) this.Close(); };
|
||||
}
|
||||
|
||||
private void fChat_Load(object sender, EventArgs e)
|
||||
{
|
||||
// Subscribe to message received event
|
||||
if (chatService != null)
|
||||
{
|
||||
chatService.MessageReceived += OnMessageReceived;
|
||||
}
|
||||
|
||||
// Load user list for recipient selection
|
||||
LoadUserList();
|
||||
|
||||
// If target is specified, set it
|
||||
if (!string.IsNullOrEmpty(targetEmployeeId))
|
||||
{
|
||||
SetRecipient(targetEmployeeId, targetNickName);
|
||||
}
|
||||
|
||||
// Load recent messages (if any)
|
||||
RefreshConnectionStatus();
|
||||
|
||||
// Request user list from server
|
||||
if (chatService != null && chatService.IsConnected)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[DEBUG] Requesting user list from server...");
|
||||
chatService.RequestUserList();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Cannot request user list - Service: {chatService != null}, Connected: {chatService?.IsConnected}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load user list into combobox
|
||||
/// </summary>
|
||||
private void LoadUserList()
|
||||
{
|
||||
cboRecipient.Items.Clear();
|
||||
|
||||
// Add placeholder
|
||||
cboRecipient.Items.Add(new ChatUserInfo
|
||||
{
|
||||
EmployeeId = "",
|
||||
NickName = "Select recipient...",
|
||||
UserGroup = ""
|
||||
});
|
||||
|
||||
// In a real implementation, this would load from server
|
||||
// For now, user will need to type employee ID manually
|
||||
// The server's UserListResponse should populate this
|
||||
|
||||
cboRecipient.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set specific recipient
|
||||
/// </summary>
|
||||
private void SetRecipient(string employeeId, string nickName)
|
||||
{
|
||||
targetEmployeeId = employeeId;
|
||||
targetNickName = nickName;
|
||||
|
||||
// Try to find in combobox
|
||||
bool found = false;
|
||||
for (int i = 0; i < cboRecipient.Items.Count; i++)
|
||||
{
|
||||
var user = cboRecipient.Items[i] as ChatUserInfo;
|
||||
if (user != null && user.EmployeeId == employeeId)
|
||||
{
|
||||
cboRecipient.SelectedIndex = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not found, add it
|
||||
if (!found && !string.IsNullOrEmpty(employeeId))
|
||||
{
|
||||
var user = new ChatUserInfo
|
||||
{
|
||||
EmployeeId = employeeId,
|
||||
NickName = nickName ?? employeeId,
|
||||
UserGroup = ""
|
||||
};
|
||||
cboRecipient.Items.Add(user);
|
||||
cboRecipient.SelectedItem = user;
|
||||
}
|
||||
|
||||
// Update form title
|
||||
this.Text = $"Chat - {nickName ?? employeeId}";
|
||||
}
|
||||
|
||||
private void fChat_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
// Unsubscribe events
|
||||
if (chatService != null)
|
||||
{
|
||||
chatService.MessageReceived -= OnMessageReceived;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Message received event handler
|
||||
/// </summary>
|
||||
private void OnMessageReceived(object sender, ChatMessage message)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
BeginInvoke(new Action(() => OnMessageReceived(sender, message)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current recipient from combobox
|
||||
var selectedUser = cboRecipient.SelectedItem as ChatUserInfo;
|
||||
string currentTargetId = selectedUser?.EmployeeId ?? targetEmployeeId;
|
||||
|
||||
// Filter messages - only show messages between current user and target
|
||||
string myEmployeeId = chatService.EmployeeId;
|
||||
|
||||
// Show message if:
|
||||
// 1. It's from target to me
|
||||
// 2. It's from me to target (echo from server)
|
||||
// 3. It's a notice (broadcast)
|
||||
bool shouldDisplay = false;
|
||||
|
||||
if (message.Type == MessageType.Notice)
|
||||
{
|
||||
shouldDisplay = true;
|
||||
|
||||
// If it's a join/leave notice, refresh user list
|
||||
if (message.Content.Contains("has joined") || message.Content.Contains("has left"))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[DEBUG] User joined/left, refreshing user list...");
|
||||
if (chatService != null && chatService.IsConnected)
|
||||
{
|
||||
chatService.RequestUserList();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (message.Type == MessageType.UserListResponse)
|
||||
{
|
||||
// Handle user list response
|
||||
HandleUserListResponse(message);
|
||||
return;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(currentTargetId))
|
||||
{
|
||||
// From target to me
|
||||
if (message.EmployeeId == currentTargetId && message.TargetEmployeeId == myEmployeeId)
|
||||
{
|
||||
shouldDisplay = true;
|
||||
}
|
||||
// From me to target (echo)
|
||||
else if (message.EmployeeId == myEmployeeId && message.TargetEmployeeId == currentTargetId)
|
||||
{
|
||||
shouldDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDisplay)
|
||||
{
|
||||
AppendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle user list response from server
|
||||
/// </summary>
|
||||
private void HandleUserListResponse(ChatMessage message)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] UserListResponse received: {message.Content}");
|
||||
|
||||
// Parse user list from Content (format: "employeeId1:nickName1:userGroup1,employeeId2:nickName2:userGroup2,...")
|
||||
if (string.IsNullOrEmpty(message.Content))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[DEBUG] UserListResponse content is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
cboRecipient.Items.Clear();
|
||||
|
||||
// Add placeholder
|
||||
cboRecipient.Items.Add(new ChatUserInfo
|
||||
{
|
||||
EmployeeId = "",
|
||||
NickName = "Select recipient...",
|
||||
UserGroup = ""
|
||||
});
|
||||
|
||||
string[] users = message.Content.Split(',');
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Parsing {users.Length} users");
|
||||
|
||||
foreach (var userStr in users)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(userStr))
|
||||
continue;
|
||||
|
||||
string[] parts = userStr.Split(':');
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] User parts: {string.Join(", ", parts)}");
|
||||
|
||||
if (parts.Length >= 2)
|
||||
{
|
||||
string empId = parts[0].Trim();
|
||||
string nick = parts[1].Trim();
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Processing user: {empId} - {nick}, My ID: {chatService.EmployeeId}");
|
||||
|
||||
// Don't add myself
|
||||
if (empId != chatService.EmployeeId)
|
||||
{
|
||||
var user = new ChatUserInfo
|
||||
{
|
||||
EmployeeId = empId,
|
||||
NickName = nick,
|
||||
UserGroup = parts.Length > 2 ? parts[2].Trim() : ""
|
||||
};
|
||||
cboRecipient.Items.Add(user);
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Added user: {user}");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Skipped myself: {empId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"[DEBUG] Total items in combo: {cboRecipient.Items.Count}");
|
||||
|
||||
// Restore previous selection if exists
|
||||
if (!string.IsNullOrEmpty(targetEmployeeId))
|
||||
{
|
||||
SetRecipient(targetEmployeeId, targetNickName);
|
||||
}
|
||||
else
|
||||
{
|
||||
cboRecipient.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[ERROR] HandleUserListResponse: {ex.Message}");
|
||||
MessageBox.Show($"Error loading user list: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append message to chat display
|
||||
/// </summary>
|
||||
private void AppendMessage(ChatMessage message)
|
||||
{
|
||||
string timeStr = message.Timestamp.ToString("HH:mm:ss");
|
||||
string displayMsg = "";
|
||||
|
||||
switch (message.Type)
|
||||
{
|
||||
case MessageType.Chat:
|
||||
displayMsg = $"[{timeStr}] {message.NickName}: {message.Content}";
|
||||
break;
|
||||
|
||||
case MessageType.Notice:
|
||||
displayMsg = $"[{timeStr}] [NOTICE] {message.Content}";
|
||||
break;
|
||||
|
||||
case MessageType.Whisper:
|
||||
displayMsg = $"[{timeStr}] [WHISPER from {message.NickName}] {message.Content}";
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
txtChatDisplay.AppendText(displayMsg + Environment.NewLine);
|
||||
txtChatDisplay.ScrollToCaret();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send button click
|
||||
/// </summary>
|
||||
private void btnSend_Click(object sender, EventArgs e)
|
||||
{
|
||||
SendMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input text key down (Enter to send)
|
||||
/// </summary>
|
||||
private void txtInput_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter)
|
||||
{
|
||||
e.SuppressKeyPress = true;
|
||||
SendMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send chat message
|
||||
/// </summary>
|
||||
private void SendMessage()
|
||||
{
|
||||
string content = txtInput.Text.Trim();
|
||||
if (string.IsNullOrEmpty(content))
|
||||
return;
|
||||
|
||||
if (chatService == null || !chatService.IsConnected)
|
||||
{
|
||||
MessageBox.Show("Not connected to chat server.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get target from combobox
|
||||
var selectedUser = cboRecipient.SelectedItem as ChatUserInfo;
|
||||
string currentTargetId = selectedUser?.EmployeeId ?? targetEmployeeId;
|
||||
|
||||
if (string.IsNullOrEmpty(currentTargetId))
|
||||
{
|
||||
MessageBox.Show("Please select a recipient.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create message with target
|
||||
var message = new ChatMessage
|
||||
{
|
||||
Type = MessageType.Chat,
|
||||
Content = content,
|
||||
TargetEmployeeId = currentTargetId
|
||||
};
|
||||
|
||||
bool sent = chatService.SendMessage(message);
|
||||
if (sent)
|
||||
{
|
||||
// Note: Server will echo the message back, so we don't display it here
|
||||
// This prevents duplicate messages
|
||||
|
||||
// Clear input
|
||||
txtInput.Text = "";
|
||||
txtInput.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Failed to send message.", "Chat", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refresh connection status display
|
||||
/// </summary>
|
||||
private void RefreshConnectionStatus()
|
||||
{
|
||||
if (chatService != null && chatService.IsConnected)
|
||||
{
|
||||
lblStatus.Text = $"Connected - {chatService.NickName} ({chatService.UserGroup})";
|
||||
lblStatus.ForeColor = Color.Green;
|
||||
}
|
||||
else
|
||||
{
|
||||
lblStatus.Text = "Disconnected";
|
||||
lblStatus.ForeColor = Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Timer to update status periodically
|
||||
/// </summary>
|
||||
private void timerStatus_Tick(object sender, EventArgs e)
|
||||
{
|
||||
RefreshConnectionStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Project/Dialog/fChat.resx
Normal file
64
Project/Dialog/fChat.resx
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" msdata:Ordinal="5" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="timerStatus.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
Reference in New Issue
Block a user