Files
lserp_cs_6.0/插件库/Lskj.Main/FrmPersonalSetting.cs
T
2026-08-31 18:03:47 +08:00

252 lines
12 KiB
C#

using Lskj.Control;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace Lskj.Main
{
public partial class FrmPersonalSetting : BaseForm
{
private MainAppearanceSettings _settings;
public FrmPersonalSetting()
{
InitializeComponent();
BuildDesignerControls();
// 设计器只需要静态控件,不访问本地配置文件或运行时状态。
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) return;
_settings = MainAppearanceSettingsStore.Load();
LoadSettingsToControls();
}
private void LoadSettingsToControls()
{
txtTopColor.Text = _settings.TopMenuBackground;
txtLeftColor.Text = _settings.SidebarBackground;
txtLeftSelectColor.Text = _settings.SidebarSelectedBackground;
numTopFont.Value = Clamp(_settings.TopMenuFontSize, numTopFont.Minimum, numTopFont.Maximum);
numLeftFont.Value = Clamp(_settings.LeftMenuFontSize, numLeftFont.Minimum, numLeftFont.Maximum);
// An empty value means "use the program default". Keep the editor
// visually empty while MainPanelControlEx2 still uses its fallback.
if (!_settings.TopMenuFontConfigured) numTopFont.Text = string.Empty;
if (!_settings.LeftMenuFontConfigured) numLeftFont.Text = string.Empty;
UpdateColorPreview(txtTopColor, pnlTopPreview);
UpdateColorPreview(txtLeftColor, pnlLeftPreview);
UpdateColorPreview(txtLeftSelectColor, pnlLeftSelectPreview);
}
private void SaveSettings()
{
int ignoredTopFont;
int ignoredLeftFont;
MainAppearanceSettingsStore.Save(new MainAppearanceSettings
{
TopMenuBackground = MainAppearanceSettingsStore.NormalizeColor(txtTopColor.Text, _settings.TopMenuBackground),
SidebarBackground = MainAppearanceSettingsStore.NormalizeColor(txtLeftColor.Text, _settings.SidebarBackground),
SidebarSelectedBackground = MainAppearanceSettingsStore.NormalizeColor(txtLeftSelectColor.Text, _settings.SidebarSelectedBackground),
TopMenuFontSize = ParseFontEditorValue(numTopFont, MainAppearanceSettingsStore.DefaultTopMenuFontSize),
LeftMenuFontSize = ParseFontEditorValue(numLeftFont, MainAppearanceSettingsStore.DefaultLeftMenuFontSize),
TopMenuFontConfigured = TryParseFontEditorValue(numTopFont, out ignoredTopFont),
LeftMenuFontConfigured = TryParseFontEditorValue(numLeftFont, out ignoredLeftFont)
});
DialogResult = DialogResult.OK;
Close();
}
private void ChooseColor(TextBox textBox, Panel preview)
{
Color current = MainAppearanceSettingsStore.ParseColor(textBox.Text, Color.White);
using (ColorDialog dialog = new ColorDialog { Color = current, FullOpen = true })
{
if (dialog.ShowDialog(this) != DialogResult.OK) return;
textBox.Text = MainAppearanceSettingsStore.FormatColor(dialog.Color);
UpdateColorPreview(textBox, preview);
}
}
private static void UpdateColorPreview(TextBox textBox, Panel preview)
{
if (preview != null) preview.BackColor = MainAppearanceSettingsStore.ParseColor(textBox.Text, Color.White);
}
private static decimal Clamp(int value, decimal min, decimal max)
{
return Math.Min(max, Math.Max(min, value));
}
private static bool TryParseFontEditorValue(NumericUpDown editor, out int value)
{
value = 0;
int parsed;
if (!int.TryParse((editor == null ? string.Empty : editor.Text ?? string.Empty).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out parsed)) return false;
if (parsed < MainAppearanceSettingsStore.MinimumFontSize || parsed > MainAppearanceSettingsStore.MaximumFontSize) return false;
value = parsed;
return true;
}
private static int ParseFontEditorValue(NumericUpDown editor, int fallback)
{
int value;
return TryParseFontEditorValue(editor, out value) ? value : fallback;
}
private void txtColor_TextChanged(object sender, EventArgs e)
{
if (sender == txtTopColor) UpdateColorPreview(txtTopColor, pnlTopPreview);
else if (sender == txtLeftColor) UpdateColorPreview(txtLeftColor, pnlLeftPreview);
else if (sender == txtLeftSelectColor) UpdateColorPreview(txtLeftSelectColor, pnlLeftSelectPreview);
}
private void btnTopColor_Click(object sender, EventArgs e) { ChooseColor(txtTopColor, pnlTopPreview); }
private void btnLeftColor_Click(object sender, EventArgs e) { ChooseColor(txtLeftColor, pnlLeftPreview); }
private void btnLeftSelectColor_Click(object sender, EventArgs e) { ChooseColor(txtLeftSelectColor, pnlLeftSelectPreview); }
private void btnSave_Click(object sender, EventArgs e) { SaveSettings(); }
private void btnCancel_Click(object sender, EventArgs e) { DialogResult = DialogResult.Cancel; Close(); }
private void btnReset_Click(object sender, EventArgs e) { _settings = MainAppearanceSettingsStore.Defaults(); LoadSettingsToControls(); }
private void navAppearance_Click(object sender, EventArgs e) { ShowPage(pnlAppearance); }
private void navFonts_Click(object sender, EventArgs e) { ShowPage(pnlFonts); }
}
internal sealed class MainAppearanceSettings
{
public string TopMenuBackground;
public string SidebarBackground;
public string SidebarSelectedBackground;
public int TopMenuFontSize;
public int LeftMenuFontSize;
public bool TopMenuFontConfigured;
public bool LeftMenuFontConfigured;
}
internal static class MainAppearanceSettingsStore
{
internal const int DefaultTopMenuFontSize = 9;
internal const int DefaultLeftMenuFontSize = 12;
internal const int MinimumFontSize = 8;
internal const int MaximumFontSize = 24;
// WinForms uses a separate file so changing the WPF shell settings does not
// unexpectedly alter the transitional WinForms main panel.
private const string FileName = "WinFromShellAppearance.ini";
private const string TopColorKey = "TopMenuBackground=";
private const string LeftColorKey = "SidebarBackground=";
private const string LeftSelectedColorKey = "SidebarSelectedBackground=";
private const string TopFontKey = "TopMenuFontSize=";
private const string LeftFontKey = "LeftMenuFontSize=";
public static MainAppearanceSettings Defaults()
{
return new MainAppearanceSettings
{
TopMenuBackground = "#1F4B99",
SidebarBackground = "#272D51",
SidebarSelectedBackground = "#348ED8",
TopMenuFontSize = DefaultTopMenuFontSize,
LeftMenuFontSize = DefaultLeftMenuFontSize,
TopMenuFontConfigured = false,
LeftMenuFontConfigured = false
};
}
public static MainAppearanceSettings Load()
{
MainAppearanceSettings result = Defaults();
try
{
string path = GetPath();
if (!File.Exists(path))
{
// Create the WinForms-specific file on first run so the active
// values are visible and editable from the Debug\Config folder.
Save(result);
return result;
}
foreach (string raw in File.ReadAllLines(path))
{
string line = (raw ?? string.Empty).Trim();
if (line.StartsWith(TopColorKey, StringComparison.OrdinalIgnoreCase)) result.TopMenuBackground = NormalizeColor(line.Substring(TopColorKey.Length), result.TopMenuBackground);
else if (line.StartsWith(LeftColorKey, StringComparison.OrdinalIgnoreCase)) result.SidebarBackground = NormalizeColor(line.Substring(LeftColorKey.Length), result.SidebarBackground);
else if (line.StartsWith(LeftSelectedColorKey, StringComparison.OrdinalIgnoreCase)) result.SidebarSelectedBackground = NormalizeColor(line.Substring(LeftSelectedColorKey.Length), result.SidebarSelectedBackground);
else if (line.StartsWith(TopFontKey, StringComparison.OrdinalIgnoreCase))
{
int value;
if (TryParseFont(line.Substring(TopFontKey.Length), out value)) { result.TopMenuFontSize = value; result.TopMenuFontConfigured = true; }
}
else if (line.StartsWith(LeftFontKey, StringComparison.OrdinalIgnoreCase))
{
int value;
if (TryParseFont(line.Substring(LeftFontKey.Length), out value)) { result.LeftMenuFontSize = value; result.LeftMenuFontConfigured = true; }
}
}
}
catch (Exception) { }
return result;
}
public static void Save(MainAppearanceSettings settings)
{
if (settings == null) return;
string path = GetPath();
string[] oldLines = new string[0];
try { if (File.Exists(path)) oldLines = File.ReadAllLines(path); } catch (Exception) { }
string[] replacements =
{
TopColorKey + NormalizeColor(settings.TopMenuBackground, "#1F4B99"),
LeftColorKey + NormalizeColor(settings.SidebarBackground, "#272D51"),
LeftSelectedColorKey + NormalizeColor(settings.SidebarSelectedBackground, "#348ED8"),
TopFontKey + (settings.TopMenuFontConfigured ? settings.TopMenuFontSize.ToString(CultureInfo.InvariantCulture) : string.Empty),
LeftFontKey + (settings.LeftMenuFontConfigured ? settings.LeftMenuFontSize.ToString(CultureInfo.InvariantCulture) : string.Empty)
};
string[] keys = { TopColorKey, LeftColorKey, LeftSelectedColorKey, TopFontKey, LeftFontKey };
var output = oldLines.ToList();
for (int i = 0; i < keys.Length; i++)
{
int index = output.FindIndex(x => (x ?? string.Empty).Trim().StartsWith(keys[i], StringComparison.OrdinalIgnoreCase));
if (index >= 0) output[index] = replacements[i]; else output.Add(replacements[i]);
}
try
{
string dir = Path.GetDirectoryName(path);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
File.WriteAllLines(path, output.ToArray());
}
catch (Exception) { }
}
public static string NormalizeColor(string value, string fallback)
{
return FormatColor(ParseColor(value, ParseColor(fallback, Color.Black)));
}
public static Color ParseColor(string value, Color fallback)
{
if (string.IsNullOrWhiteSpace(value)) return fallback;
string text = value.Trim();
if (!text.StartsWith("#", StringComparison.Ordinal) || text.Length != 7) return fallback;
byte r, g, b;
if (!byte.TryParse(text.Substring(1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out r) || !byte.TryParse(text.Substring(3, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out g) || !byte.TryParse(text.Substring(5, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out b)) return fallback;
return Color.FromArgb(r, g, b);
}
public static string FormatColor(Color color)
{
return string.Format(CultureInfo.InvariantCulture, "#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
}
private static bool TryParseFont(string value, out int result)
{
result = 0;
return int.TryParse((value ?? string.Empty).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result)
&& result >= MinimumFontSize && result <= MaximumFontSize;
}
private static string GetPath()
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config", FileName);
}
}
}