Compare commits

..

20 Commits

Author SHA1 Message Date
zsyg
d454ac0fdc 允许自定义下载路径 2025-07-02 10:10:02 +08:00
zsyg
d5c83d854c 删除没有必要的文件 2025-07-02 09:17:44 +08:00
zsyg
1c2bc713be 提高代码质量 2025-07-02 09:16:18 +08:00
zsyg
1539c665f0 提供代码质量 2025-07-02 09:15:43 +08:00
zsyg
074e55fbbc Add files via upload 2025-07-02 09:14:43 +08:00
zsyg
334fa56070 修复代码潜在问题 2025-07-02 09:12:49 +08:00
zsyg
0268e13b56 Add files via upload 2025-07-01 19:02:06 +08:00
zsyg
cba6c9eeca Update README.md 2025-07-01 11:31:02 +08:00
zsyg
70a776125a 修改密码生成器代码位置 2025-07-01 10:34:32 +08:00
zsyg
f7250dae08 修复主题系统带来的颜色 2025-07-01 10:26:26 +08:00
zsyg
ac93c8418f Add files via upload 2025-06-30 20:25:25 +08:00
zsyg
5a49714ed7 Add files via upload 2025-06-30 20:22:07 +08:00
zsyg
19056a1a8c Add files via upload 2025-06-30 20:21:19 +08:00
zsyg
7c4250f912 Add files via upload 2025-06-30 20:20:48 +08:00
zsyg
d056c24a1b Add files via upload 2025-06-30 20:20:21 +08:00
zsyg
5651e944f9 Add files via upload 2025-06-30 15:46:54 +08:00
zsyg
1dbd9968c9 Add files via upload 2025-06-30 15:46:31 +08:00
zsyg
e387d22fee Add files via upload 2025-06-30 15:44:21 +08:00
zsyg
68bd471bd2 Add files via upload 2025-06-30 15:43:54 +08:00
zsyg
53392a2ce8 Add files via upload 2025-06-29 20:23:29 +08:00
28 changed files with 2475 additions and 1430 deletions

View File

@@ -17,12 +17,13 @@ namespace AppStore
private void InitializeComponent() private void InitializeComponent()
{ {
this.Dock = DockStyle.Fill; this.Dock = DockStyle.Fill;
this.BackColor = Color.White; this.BackColor = ThemeManager.BackgroundColor;
this.Padding = new Padding(20); this.Padding = new Padding(20);
// 创建主布局面板 // 创建主布局面板
TableLayoutPanel mainLayout = new TableLayoutPanel(); TableLayoutPanel mainLayout = new TableLayoutPanel();
mainLayout.Dock = DockStyle.Fill; mainLayout.Dock = DockStyle.Fill;
mainLayout.BackColor = ThemeManager.BackgroundColor;
mainLayout.ColumnCount = 1; mainLayout.ColumnCount = 1;
mainLayout.RowCount = 2; mainLayout.RowCount = 2;
mainLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); mainLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
@@ -50,7 +51,7 @@ namespace AppStore
// 初始化并添加应用信息 // 初始化并添加应用信息
infoLabel = new Label(); infoLabel = new Label();
infoLabel.Text = "kortapp-z\n版本: 1.0.9\n作者: zs-yg\n一个简单、开源的应用商店\nkortapp-z是完全免费\n基于.NET8和C/C++的软件"; infoLabel.Text = "kortapp-z\n版本: 1.1.3\n作者: zs-yg\n一个简单、开源的应用商店\nkortapp-z是完全免费\n基于.NET8和C/C++的软件";
infoLabel.Font = new Font("Microsoft YaHei", 12); infoLabel.Font = new Font("Microsoft YaHei", 12);
infoLabel.AutoSize = false; infoLabel.AutoSize = false;
infoLabel.Width = 300; infoLabel.Width = 300;
@@ -68,6 +69,7 @@ namespace AppStore
// 在底部添加GitHub链接区域 // 在底部添加GitHub链接区域
TableLayoutPanel githubPanel = new TableLayoutPanel(); TableLayoutPanel githubPanel = new TableLayoutPanel();
githubPanel.Dock = DockStyle.Bottom; githubPanel.Dock = DockStyle.Bottom;
githubPanel.BackColor = ThemeManager.BackgroundColor;
githubPanel.Height = 60; githubPanel.Height = 60;
githubPanel.ColumnCount = 3; githubPanel.ColumnCount = 3;
githubPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F)); githubPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
@@ -109,6 +111,7 @@ namespace AppStore
// 创建包含图标和文字的面板 // 创建包含图标和文字的面板
Panel linkPanel = new Panel(); Panel linkPanel = new Panel();
linkPanel.AutoSize = true; linkPanel.AutoSize = true;
linkPanel.BackColor = ThemeManager.BackgroundColor;
linkPanel.Controls.Add(githubIcon); linkPanel.Controls.Add(githubIcon);
linkPanel.Controls.Add(githubLabel); linkPanel.Controls.Add(githubLabel);
githubIcon.Location = new Point(0, 0); githubIcon.Location = new Point(0, 0);

View File

@@ -13,7 +13,9 @@ namespace AppStore
{ {
private PictureBox iconBox; private PictureBox iconBox;
private Label nameLabel; private Label nameLabel;
private Panel namePanel;
private Button downloadBtn; private Button downloadBtn;
private Color borderColor = SystemColors.ControlDark;
private static readonly ConcurrentDictionary<string, System.Drawing.Drawing2D.GraphicsPath> PathCache = private static readonly ConcurrentDictionary<string, System.Drawing.Drawing2D.GraphicsPath> PathCache =
new ConcurrentDictionary<string, System.Drawing.Drawing2D.GraphicsPath>(); new ConcurrentDictionary<string, System.Drawing.Drawing2D.GraphicsPath>();
@@ -27,6 +29,7 @@ namespace AppStore
// 确保关键对象不为null // 确保关键对象不为null
iconBox = new PictureBox() { SizeMode = PictureBoxSizeMode.StretchImage }; iconBox = new PictureBox() { SizeMode = PictureBoxSizeMode.StretchImage };
nameLabel = new Label() { Text = string.Empty }; nameLabel = new Label() { Text = string.Empty };
namePanel = new Panel();
downloadBtn = new Button() { Text = "下载" }; downloadBtn = new Button() { Text = "下载" };
// 确保DownloadManager已初始化 // 确保DownloadManager已初始化
@@ -57,14 +60,29 @@ namespace AppStore
iconBox.SizeMode = PictureBoxSizeMode.StretchImage; iconBox.SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(iconBox); this.Controls.Add(iconBox);
// 应用名称 // 应用名称 - 使用Panel包裹Label实现边框颜色
// namePanel已在构造函数中初始化
namePanel.Size = new Size(Width - 20, 40);
namePanel.Location = new Point(10, 100);
namePanel.Paint += (sender, e) => {
ControlPaint.DrawBorder(e.Graphics, namePanel.ClientRectangle,
borderColor, ButtonBorderStyle.Solid);
};
nameLabel = new Label(); nameLabel = new Label();
nameLabel.AutoSize = false; nameLabel.Dock = DockStyle.Fill;
nameLabel.Size = new Size(Width - 20, 40);
nameLabel.Location = new Point(10, 100);
nameLabel.Font = new Font("Microsoft YaHei", 10, FontStyle.Bold); nameLabel.Font = new Font("Microsoft YaHei", 10, FontStyle.Bold);
nameLabel.TextAlign = ContentAlignment.MiddleCenter; nameLabel.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(nameLabel);
namePanel.Controls.Add(nameLabel);
// 初始主题设置
UpdateLabelTheme();
// 订阅主题变化事件
ThemeManager.ThemeChanged += (theme) => UpdateLabelTheme();
this.Controls.Add(namePanel);
// 下载按钮 // 下载按钮
downloadBtn = new Button(); downloadBtn = new Button();
@@ -92,6 +110,25 @@ namespace AppStore
downloadBtn.Visible = ShowDownloadButton; downloadBtn.Visible = ShowDownloadButton;
} }
private void UpdateLabelTheme()
{
if (ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Dark)
{
nameLabel.BackColor = Color.Black;
nameLabel.ForeColor = Color.White;
namePanel.BackColor = Color.Black;
borderColor = Color.White;
}
else
{
nameLabel.BackColor = Color.White;
nameLabel.ForeColor = Color.Black;
namePanel.BackColor = Color.White;
borderColor = SystemColors.ControlDark;
}
namePanel.Invalidate(); // 触发重绘
}
/// <summary> /// <summary>
/// 初始化卡片边框路径 /// 初始化卡片边框路径
/// 使用C++程序计算高性能边框路径并缓存结果 /// 使用C++程序计算高性能边框路径并缓存结果
@@ -309,10 +346,16 @@ namespace AppStore
} }
public void UpdateDisplay() public void UpdateDisplay()
{
if (nameLabel != null)
{ {
nameLabel.Text = AppName; nameLabel.Text = AppName;
}
if (iconBox != null && AppIcon != null)
{
iconBox.Image = AppIcon; iconBox.Image = AppIcon;
} }
}
private void DownloadBtn_Click(object sender, EventArgs e) private void DownloadBtn_Click(object sender, EventArgs e)
{ {

57
AppSearch.cs Normal file
View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace AppStore
{
public static class AppSearch
{
/// <summary>
/// 搜索应用卡片
/// </summary>
/// <param name="flowPanel">包含应用卡片的FlowLayoutPanel</param>
/// <param name="searchText">搜索文本</param>
public static void SearchApps(FlowLayoutPanel flowPanel, string searchText)
{
if (flowPanel == null || string.IsNullOrWhiteSpace(searchText))
{
ShowAllApps(flowPanel);
return;
}
foreach (Control control in flowPanel.Controls)
{
if (control is AppCard appCard)
{
bool isMatch = IsMatchSearch(appCard.AppName, searchText);
control.Visible = isMatch;
}
}
}
/// <summary>
/// 显示所有应用卡片
/// </summary>
public static void ShowAllApps(FlowLayoutPanel? flowPanel)
{
if (flowPanel == null) return;
foreach (Control control in flowPanel.Controls)
{
control.Visible = true;
}
}
/// <summary>
/// 检查应用名称是否匹配搜索文本
/// </summary>
private static bool IsMatchSearch(string appName, string searchText)
{
if (string.IsNullOrEmpty(appName)) return false;
// 不区分大小写比较
return appName.Contains(searchText, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@@ -33,4 +33,8 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="ZXing.Net" Version="0.16.9" />
</ItemGroup>
</Project> </Project>

View File

@@ -23,13 +23,40 @@ namespace AppStore
cancelBtn = new Button(); cancelBtn = new Button();
InitializeComponent(); InitializeComponent();
// 监听主题变化
ThemeManager.ThemeChanged += (theme) => {
this.Invoke((MethodInvoker)delegate {
ApplyTheme();
});
};
}
private void ApplyTheme()
{
this.BackColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? Color.White
: Color.Black;
this.ForeColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? Color.Black
: Color.White;
cancelBtn.BackColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? SystemColors.Control
: Color.FromArgb(70, 70, 70);
cancelBtn.ForeColor = ThemeManager.TextColor;
} }
private void InitializeComponent() private void InitializeComponent()
{ {
this.Size = new Size(400, 60); this.Size = new Size(400, 60);
this.BackColor = Color.White; this.BackColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? Color.White
: Color.Black;
this.BorderStyle = BorderStyle.FixedSingle; this.BorderStyle = BorderStyle.FixedSingle;
this.ForeColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? Color.Black
: Color.White;
// 文件名标签 // 文件名标签
nameLabel = new Label(); nameLabel = new Label();
@@ -56,6 +83,12 @@ namespace AppStore
cancelBtn.Text = "取消"; cancelBtn.Text = "取消";
cancelBtn.Size = new Size(60, 25); cancelBtn.Size = new Size(60, 25);
cancelBtn.Location = new Point(320, 30); cancelBtn.Location = new Point(320, 30);
cancelBtn.BackColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? SystemColors.Control
: Color.FromArgb(70, 70, 70);
cancelBtn.ForeColor = ThemeManager.TextColor;
cancelBtn.FlatStyle = FlatStyle.Flat;
cancelBtn.FlatAppearance.BorderSize = 0;
cancelBtn.Click += CancelBtn_Click; cancelBtn.Click += CancelBtn_Click;
this.Controls.Add(cancelBtn); this.Controls.Add(cancelBtn);
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@@ -85,37 +86,40 @@ namespace AppStore
private void DownloadFile(DownloadItem downloadItem, string fileName, string url) private void DownloadFile(DownloadItem downloadItem, string fileName, string url)
{ {
string downloadsDir = string.Empty;
try try
{ {
// 设置下载目录为用户文件夹中的Downloads // 获取并验证下载路径
// 获取系统下载文件夹路径 downloadsDir = GetDownloadPath();
// 获取系统下载文件夹路径
string downloadsDir;
IntPtr pathPtr = IntPtr.Zero;
try try
{ {
// 使用SHGetKnownFolderPath API获取下载文件夹 // 检查路径是否有效
var downloadsFolderGuid = new Guid("374DE290-123F-4565-9164-39C4925E467B"); if (string.IsNullOrWhiteSpace(downloadsDir))
if (SHGetKnownFolderPath(downloadsFolderGuid, 0, IntPtr.Zero, out pathPtr) != 0)
{ {
throw new Exception("无法获取下载文件夹路径"); throw new Exception("下载路径为空");
} }
downloadsDir = Marshal.PtrToStringUni(pathPtr); // 尝试创建目录(如果不存在)
}
catch
{
throw new Exception("无法确定下载文件夹位置,请手动指定下载路径");
}
finally
{
if (pathPtr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pathPtr);
}
}
Directory.CreateDirectory(downloadsDir); Directory.CreateDirectory(downloadsDir);
// 验证目录是否可写
string testFile = Path.Combine(downloadsDir, "write_test.tmp");
File.WriteAllText(testFile, "test");
File.Delete(testFile);
}
catch (Exception ex)
{
// 回退到默认下载路径
string defaultPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Downloads");
Logger.LogError($"下载路径{downloadsDir}不可用,将使用默认路径: {defaultPath}", ex);
downloadsDir = defaultPath;
Directory.CreateDirectory(downloadsDir);
}
// 构建aria2c路径 // 构建aria2c路径
@@ -311,9 +315,17 @@ namespace AppStore
} }
catch (Exception ex) catch (Exception ex)
{ {
downloadItem.Status = $"下载错误: {ex.Message}"; string errorDetails = $"下载错误: {ex.Message}\n";
DownloadCompleted?.Invoke(downloadItem); errorDetails += $"目标路径: {downloadsDir}\n";
errorDetails += $"URL: {url}";
downloadItem.Status = $"下载失败: {ex.Message}";
Logger.LogError(errorDetails, ex);
MessageBox.Show($"下载失败:\n{errorDetails}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
DownloadCompleted?.Invoke(downloadItem);
} }
} }
@@ -322,7 +334,7 @@ namespace AppStore
try try
{ {
var process = currentProcess; var process = currentProcess;
if (process == null || process.HasExited || process.StartInfo == null) if (process?.StartInfo == null || process.HasExited)
{ {
item.Status = "已取消"; item.Status = "已取消";
DownloadProgressChanged?.Invoke(item); DownloadProgressChanged?.Invoke(item);
@@ -342,5 +354,138 @@ namespace AppStore
DownloadProgressChanged?.Invoke(item); DownloadProgressChanged?.Invoke(item);
} }
} }
private string GetDownloadPath()
{
// 1. 优先读取用户设置的下载路径
try
{
string jsonPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".date", "dl_path", "download_path.json");
Logger.Log($"尝试读取下载路径配置文件: {jsonPath}");
if (File.Exists(jsonPath))
{
string jsonString = File.ReadAllText(jsonPath);
Logger.Log($"配置文件内容: {jsonString}");
var jsonData = JsonSerializer.Deserialize<JsonElement>(jsonString);
string customPath = jsonData.GetProperty("DownloadPath").GetString()?.Trim();
if (!string.IsNullOrWhiteSpace(customPath))
{
Logger.Log($"读取到自定义路径: {customPath}");
// 处理路径格式
customPath = customPath.Replace(@"\\", @"\");
try
{
// 处理路径中的环境变量和特殊字符
customPath = Environment.ExpandEnvironmentVariables(customPath);
customPath = Path.GetFullPath(customPath);
Logger.Log($"标准化后的路径: {customPath}");
// 确保路径以目录分隔符结尾
if (!customPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
customPath += Path.DirectorySeparatorChar;
}
// 验证驱动器是否存在
string drive = Path.GetPathRoot(customPath);
if (!Directory.Exists(drive))
{
Logger.LogError($"驱动器不存在: {drive}");
throw new Exception($"驱动器 {drive} 不存在");
}
// 验证路径
if (!Directory.Exists(customPath))
{
Logger.Log($"创建目录: {customPath}");
Directory.CreateDirectory(customPath);
}
// 更严格的路径可写性测试
string testFile = Path.Combine(customPath, $"write_test_{Guid.NewGuid()}.tmp");
Logger.Log($"测试路径可写性: {testFile}");
try
{
File.WriteAllText(testFile, DateTime.Now.ToString());
string content = File.ReadAllText(testFile);
File.Delete(testFile);
Logger.Log($"路径验证成功: {customPath}");
return customPath.TrimEnd(Path.DirectorySeparatorChar);
}
catch (Exception ex)
{
Logger.LogError($"路径不可写: {customPath}", ex);
throw new Exception($"路径不可写: {customPath}");
}
}
catch (Exception ex)
{
Logger.LogError($"路径处理失败: {customPath}", ex);
throw;
}
}
}
else
{
Logger.Log("未找到下载路径配置文件");
}
}
catch (Exception ex)
{
Logger.LogError("读取自定义下载路径失败", ex);
}
// 2. 回退到系统默认下载路径
IntPtr pathPtr = IntPtr.Zero;
try
{
var downloadsFolderGuid = new Guid("374DE290-123F-4565-9164-39C4925E467B");
if (SHGetKnownFolderPath(downloadsFolderGuid, 0, IntPtr.Zero, out pathPtr) == 0)
{
string defaultPath = Marshal.PtrToStringUni(pathPtr);
if (!string.IsNullOrEmpty(defaultPath))
{
Directory.CreateDirectory(defaultPath);
return defaultPath;
}
}
}
catch (Exception ex)
{
Logger.LogError("获取系统下载路径失败", ex);
}
finally
{
if (pathPtr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pathPtr);
}
}
// 3. 最终回退到相对路径 ~/Downloads
string relativePath = "~/Downloads";
string fallbackPath = relativePath.Replace("~",
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
fallbackPath = Path.GetFullPath(fallbackPath);
try {
Directory.CreateDirectory(fallbackPath);
// 测试路径可写性
string testFile = Path.Combine(fallbackPath, "write_test.tmp");
File.WriteAllText(testFile, "test");
File.Delete(testFile);
return fallbackPath;
}
catch {
throw new Exception($"无法使用默认下载路径: {fallbackPath}");
}
}
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 KiB

View File

@@ -140,11 +140,19 @@ namespace AppStore
this.StartPosition = FormStartPosition.CenterScreen; this.StartPosition = FormStartPosition.CenterScreen;
this.Icon = new Icon("img/ico/icon.ico"); // 设置窗体图标 this.Icon = new Icon("img/ico/icon.ico"); // 设置窗体图标
// 注册主题变更事件
ThemeManager.ThemeChanged += (theme) =>
{
this.Invoke((MethodInvoker)delegate {
AnimateThemeChange();
});
};
// 现代化顶部导航栏 // 现代化顶部导航栏
Panel buttonPanel = new Panel(); Panel buttonPanel = new Panel();
buttonPanel.Dock = DockStyle.Top; buttonPanel.Dock = DockStyle.Top;
buttonPanel.Height = 70; buttonPanel.Height = 70;
buttonPanel.BackColor = Color.FromArgb(240, 240, 240); buttonPanel.BackColor = ThemeManager.ControlBackgroundColor;
buttonPanel.Padding = new Padding(10, 15, 10, 0); buttonPanel.Padding = new Padding(10, 15, 10, 0);
buttonPanel.AutoScroll = true; buttonPanel.AutoScroll = true;
buttonPanel.AutoSize = true; buttonPanel.AutoSize = true;
@@ -154,11 +162,13 @@ namespace AppStore
Action<Button> styleButton = (Button btn) => { Action<Button> styleButton = (Button btn) => {
btn.FlatStyle = FlatStyle.Flat; btn.FlatStyle = FlatStyle.Flat;
btn.FlatAppearance.BorderSize = 0; btn.FlatAppearance.BorderSize = 0;
btn.BackColor = Color.Transparent; btn.BackColor = ThemeManager.ControlBackgroundColor;
btn.ForeColor = Color.FromArgb(64, 64, 64); btn.ForeColor = ThemeManager.TextColor;
btn.Font = new Font("Microsoft YaHei", 10, FontStyle.Regular); btn.Font = new Font("Microsoft YaHei", 10, FontStyle.Regular);
btn.Size = new Size(120, 40); btn.Size = new Size(120, 40);
btn.Cursor = Cursors.Hand; btn.Cursor = Cursors.Hand;
btn.FlatAppearance.MouseOverBackColor = ThemeManager.ButtonHoverColor;
btn.FlatAppearance.MouseDownBackColor = ThemeManager.ButtonActiveColor;
// 悬停效果 // 悬停效果
btn.MouseEnter += (s, e) => { btn.MouseEnter += (s, e) => {
@@ -167,7 +177,7 @@ namespace AppStore
}; };
btn.MouseLeave += (s, e) => { btn.MouseLeave += (s, e) => {
btn.ForeColor = Color.FromArgb(64, 64, 64); btn.ForeColor = ThemeManager.TextColor;
btn.Font = new Font(btn.Font, FontStyle.Regular); btn.Font = new Font(btn.Font, FontStyle.Regular);
}; };
}; };
@@ -230,7 +240,7 @@ namespace AppStore
// 现代化内容区域 // 现代化内容区域
contentPanel = new Panel(); contentPanel = new Panel();
contentPanel.Dock = DockStyle.Fill; contentPanel.Dock = DockStyle.Fill;
contentPanel.BackColor = Color.White; contentPanel.BackColor = ThemeManager.BackgroundColor;
contentPanel.Padding = new Padding(20); contentPanel.Padding = new Padding(20);
this.Controls.Add(contentPanel); this.Controls.Add(contentPanel);
@@ -238,11 +248,13 @@ namespace AppStore
Panel separator = new Panel(); Panel separator = new Panel();
separator.Dock = DockStyle.Top; separator.Dock = DockStyle.Top;
separator.Height = 1; separator.Height = 1;
separator.BackColor = Color.FromArgb(230, 230, 230); separator.BackColor = ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Light
? Color.FromArgb(230, 230, 230)
: Color.FromArgb(60, 60, 60);
contentPanel.Controls.Add(separator); contentPanel.Controls.Add(separator);
this.Controls.Add(buttonPanel); this.Controls.Add(buttonPanel);
this.BackColor = Color.White; this.BackColor = ThemeManager.BackgroundColor;
// 默认显示软件下载视图 // 默认显示软件下载视图
ShowAppsView(); ShowAppsView();
@@ -518,6 +530,42 @@ namespace AppStore
} }
flowPanel.Controls.Add(imageViewerCard); flowPanel.Controls.Add(imageViewerCard);
// 密码生成器工具卡片
var passwordGeneratorCard = new ToolCard();
passwordGeneratorCard.ToolName = "密码生成器";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "password_generator.png");
if (File.Exists(iconPath))
{
passwordGeneratorCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
passwordGeneratorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
}
catch
{
passwordGeneratorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
passwordGeneratorCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "password_generator.exe");
if (File.Exists(toolPath)) {
Process.Start(toolPath);
} else {
MessageBox.Show("密码生成器工具未找到,请确保已正确安装", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch (Exception ex) {
MessageBox.Show($"启动密码生成器失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
passwordGeneratorCard.UpdateDisplay();
flowPanel.Controls.Add(passwordGeneratorCard);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -667,7 +715,7 @@ namespace AppStore
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
"XDM", "XDM",
"https://github.com/subhra74/xdm/releases/download/7.2.11/xdm-setup.msi", "https://ghproxy.net/https://github.com/subhra74/xdm/releases/download/7.2.11/xdm-setup.msi",
"img/png/XDM.png")); "img/png/XDM.png"));
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
@@ -732,7 +780,7 @@ namespace AppStore
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
"Msys2", "Msys2",
"https://github.com/msys2/msys2-installer/releases/download/2025-02-21/msys2-x86_64-20250221.exe", "https://ghproxy.net/https://github.com/msys2/msys2-installer/releases/download/2025-02-21/msys2-x86_64-20250221.exe",
"img/png/MSYS2.png")); "img/png/MSYS2.png"));
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
@@ -832,7 +880,7 @@ namespace AppStore
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
"frp", "frp",
"https://github.com/fatedier/frp/releases/download/v0.62.1/frp_0.62.1_windows_amd64.zip", "https://ghproxy.net/https://github.com/fatedier/frp/releases/download/v0.62.1/frp_0.62.1_windows_amd64.zip",
"")); ""));
flowPanel.Controls.Add(CreateAppCard( flowPanel.Controls.Add(CreateAppCard(
@@ -1235,6 +1283,9 @@ namespace AppStore
// 初始化窗体组件 // 初始化窗体组件
InitializeComponent(); InitializeComponent();
// 应用主题
ThemeManager.ApplyTheme(this);
// 订阅下载管理器事件 // 订阅下载管理器事件
DownloadManager.Instance.DownloadAdded += OnDownloadAdded; // 下载添加事件 DownloadManager.Instance.DownloadAdded += OnDownloadAdded; // 下载添加事件
DownloadManager.Instance.DownloadProgressChanged += OnDownloadProgressChanged; // 下载进度变化事件 DownloadManager.Instance.DownloadProgressChanged += OnDownloadProgressChanged; // 下载进度变化事件
@@ -1316,5 +1367,69 @@ namespace AppStore
Logger.Log($"下载完成: {item.FileName}, 状态: {item.Status}"); // 记录日志 Logger.Log($"下载完成: {item.FileName}, 状态: {item.Status}"); // 记录日志
item.UpdateDisplay(); // 更新UI显示 item.UpdateDisplay(); // 更新UI显示
} }
/// <summary>
/// 主题切换动画效果
/// </summary>
private void AnimateThemeChange()
{
const int animationSteps = 10;
const int animationInterval = 30;
var timer = new System.Windows.Forms.Timer { Interval = animationInterval };
int step = 0;
// 保存当前和目标颜色
var originalBackColor = this.BackColor;
var targetBackColor = ThemeManager.BackgroundColor;
var originalForeColor = this.ForeColor;
var targetForeColor = ThemeManager.TextColor;
timer.Tick += (s, e) => {
if (step >= animationSteps)
{
timer.Stop();
timer.Dispose();
// 确保最终颜色准确
ThemeManager.ApplyTheme(this);
return;
}
// 计算插值比例
float ratio = (float)step / animationSteps;
step++;
// 插值计算新颜色
var newBackColor = Color.FromArgb(
(int)(originalBackColor.R + (targetBackColor.R - originalBackColor.R) * ratio),
(int)(originalBackColor.G + (targetBackColor.G - originalBackColor.G) * ratio),
(int)(originalBackColor.B + (targetBackColor.B - originalBackColor.B) * ratio));
var newForeColor = Color.FromArgb(
(int)(originalForeColor.R + (targetForeColor.R - originalForeColor.R) * ratio),
(int)(originalForeColor.G + (targetForeColor.G - originalForeColor.G) * ratio),
(int)(originalForeColor.B + (targetForeColor.B - originalForeColor.B) * ratio));
// 应用新颜色
this.Invoke((MethodInvoker)delegate {
this.BackColor = newBackColor;
this.ForeColor = newForeColor;
foreach (Control control in this.Controls)
{
control.BackColor = newBackColor;
control.ForeColor = newForeColor;
// 特殊处理按钮的悬停状态
if (control is Button button)
{
button.FlatAppearance.MouseOverBackColor = ThemeManager.ButtonHoverColor;
button.FlatAppearance.MouseDownBackColor = ThemeManager.ButtonActiveColor;
}
}
});
};
timer.Start();
}
} }
} }

View File

@@ -5,14 +5,12 @@
## 项目开源行为 ## 项目开源行为
1. 项目代码开源,允许任何人使用、修改、分发、商用,但必须注明原作者。 1. 项目代码开源,允许任何人使用、修改、分发、商用,但必须注明原作者。
2. 项目文档开源,允许任何人使用、修改、分发、商用,但必须注明原作者。 2. 项目图标、截图等资源开源,允许任何人使用、修改、分发、商用,但必须注明原作者。
3. 项目图标、截图等资源开源,允许任何人使用、修改、分发、商用,但必须注明原作者 3. 项目的任何衍生品包括但不限于网站、APP、插件等必须遵循以上开源协议
4. 项目的任何衍生品包括但不限于网站、APP、插件等必须遵循以上开源协议 4. 项目不接受任何形式的广告,不得在任何地方投放广告
5. 项目不接受任何形式的广告,不得在任何地方投放广告。 5. 项目不接受任何形式的捐赠、赞助
6. 项目不接受任何形式的捐赠。 6. 项目可以进行PR欢迎任何形式的PR不提交issue也可以
7. 项目不接受任何形式的赞助。 7. 项目可以PR一些你自己的项目如果star数量不到1k都会被删除
8. 项目可以进行PR欢迎任何形式的PR不提交issue也可以
9. 本项目可以PR一些你自己的项目如果star数量不到1k都会被删除
## 项目简介 ## 项目简介

View File

@@ -2,29 +2,101 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using System.Drawing;
using System.Text.Json;
namespace AppStore namespace AppStore
{ {
public class SettingsUserControl : UserControl public class SettingsUserControl : UserControl
{ {
private Button btnCleanLogs; private Button btnCleanLogs;
private Button btnLightTheme;
private Button btnDarkTheme;
public SettingsUserControl() public SettingsUserControl()
{ {
this.Dock = DockStyle.Fill; this.Dock = DockStyle.Fill;
this.BackColor = Color.White; ThemeManager.ApplyTheme(this);
// 设置顶部内边距 // 设置顶部内边距
this.Padding = new Padding(0, 30, 0, 0); this.Padding = new Padding(0, 30, 0, 0);
// 主题切换按钮
btnLightTheme = new Button();
btnLightTheme.Text = "浅色模式";
btnLightTheme.Size = new Size(150, 40);
btnLightTheme.Location = new Point((this.Width - 320) / 2, 50);
btnLightTheme.Font = new Font("Microsoft YaHei", 10);
btnLightTheme.Anchor = AnchorStyles.Top;
btnLightTheme.Click += (s, e) => SwitchTheme(ThemeManager.ThemeMode.Light);
this.Controls.Add(btnLightTheme);
btnDarkTheme = new Button();
btnDarkTheme.Text = "深色模式";
btnDarkTheme.Size = new Size(150, 40);
btnDarkTheme.Location = new Point(btnLightTheme.Right + 20, 50);
btnDarkTheme.Font = new Font("Microsoft YaHei", 10);
btnDarkTheme.Anchor = AnchorStyles.Top;
btnDarkTheme.Click += (s, e) => SwitchTheme(ThemeManager.ThemeMode.Dark);
this.Controls.Add(btnDarkTheme);
// 清理日志按钮
btnCleanLogs = new Button(); btnCleanLogs = new Button();
btnCleanLogs.Text = "清理日志"; btnCleanLogs.Text = "清理日志";
btnCleanLogs.Size = new Size(150, 40); btnCleanLogs.Size = new Size(150, 40);
btnCleanLogs.Location = new Point((this.Width - 150) / 2, 50); // 调整Y坐标为50靠近顶部 btnCleanLogs.Location = new Point((this.Width - 150) / 2, 110);
btnCleanLogs.Font = new Font("Microsoft YaHei", 10); btnCleanLogs.Font = new Font("Microsoft YaHei", 10);
btnCleanLogs.Anchor = AnchorStyles.Top; // 添加顶部锚点 btnCleanLogs.Anchor = AnchorStyles.Top;
btnCleanLogs.Click += (s, e) => CleanLogs(); btnCleanLogs.Click += (s, e) => CleanLogs();
this.Controls.Add(btnCleanLogs); this.Controls.Add(btnCleanLogs);
// 下载路径设置
Label lblDownloadPath = new Label();
lblDownloadPath.Text = "下载路径:";
lblDownloadPath.AutoSize = true;
lblDownloadPath.Location = new Point((this.Width - 300) / 2, 170);
lblDownloadPath.Font = new Font("Microsoft YaHei", 10);
lblDownloadPath.Anchor = AnchorStyles.Top;
this.Controls.Add(lblDownloadPath);
TextBox txtDownloadPath = new TextBox();
txtDownloadPath.Size = new Size(300, 30);
txtDownloadPath.Location = new Point((this.Width - 300) / 2, 200);
txtDownloadPath.Font = new Font("Microsoft YaHei", 10);
txtDownloadPath.Anchor = AnchorStyles.Top;
txtDownloadPath.ReadOnly = true;
this.Controls.Add(txtDownloadPath);
Button btnBrowse = new Button();
btnBrowse.Text = "浏览...";
btnBrowse.Size = new Size(80, 30);
btnBrowse.Location = new Point(txtDownloadPath.Right + 10, 200);
btnBrowse.Font = new Font("Microsoft YaHei", 10);
btnBrowse.Anchor = AnchorStyles.Top;
btnBrowse.Click += (s, e) => BrowseDownloadPath(txtDownloadPath);
this.Controls.Add(btnBrowse);
Button btnSavePath = new Button();
btnSavePath.Text = "保存路径";
btnSavePath.Size = new Size(100, 30);
btnSavePath.Location = new Point((this.Width - 100) / 2, 240);
btnSavePath.Font = new Font("Microsoft YaHei", 10);
btnSavePath.Anchor = AnchorStyles.Top;
btnSavePath.Click += (s, e) => SaveDownloadPath(txtDownloadPath.Text);
this.Controls.Add(btnSavePath);
ThemeManager.ThemeChanged += OnThemeChanged;
LoadDownloadPath(txtDownloadPath);
}
private void SwitchTheme(ThemeManager.ThemeMode theme)
{
ThemeManager.CurrentTheme = theme;
}
private void OnThemeChanged(ThemeManager.ThemeMode theme)
{
ThemeManager.ApplyTheme(this);
} }
private void CleanLogs() private void CleanLogs()
@@ -49,5 +121,103 @@ namespace AppStore
MessageBox.Show($"清理日志时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show($"清理日志时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
} }
} }
private void BrowseDownloadPath(TextBox txtBox)
{
using (FolderBrowserDialog dialog = new FolderBrowserDialog())
{
dialog.Description = "选择下载路径";
if (dialog.ShowDialog() == DialogResult.OK)
{
txtBox.Text = dialog.SelectedPath;
}
}
}
private void SaveDownloadPath(string path)
{
try
{
// 验证路径
if (string.IsNullOrWhiteSpace(path))
{
MessageBox.Show("下载路径不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 尝试创建目录(如果不存在)
try
{
Directory.CreateDirectory(path);
// 验证目录是否可写
string testFile = Path.Combine(path, "write_test.tmp");
File.WriteAllText(testFile, "test");
File.Delete(testFile);
}
catch
{
MessageBox.Show($"无法访问路径: {path}\n请确保路径存在且有写入权限", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 保存路径
string dlPathDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".date", "dl_path");
if (!Directory.Exists(dlPathDir))
{
Directory.CreateDirectory(dlPathDir);
}
string jsonPath = Path.Combine(dlPathDir, "download_path.json");
var jsonData = new { DownloadPath = path };
string jsonString = JsonSerializer.Serialize(jsonData);
File.WriteAllText(jsonPath, jsonString);
MessageBox.Show($"下载路径已保存到:\n{path}", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
Logger.LogError("保存下载路径时出错", ex);
MessageBox.Show($"保存下载路径时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadDownloadPath(TextBox txtBox)
{
// 默认下载路径为用户文件夹下的Downloads
string defaultPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Downloads");
try
{
string jsonPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".date", "dl_path", "download_path.json");
if (File.Exists(jsonPath))
{
string jsonString = File.ReadAllText(jsonPath);
var jsonData = JsonSerializer.Deserialize<JsonElement>(jsonString);
string customPath = jsonData.GetProperty("DownloadPath").GetString();
// 如果自定义路径有效则显示,否则显示默认路径
txtBox.Text = !string.IsNullOrWhiteSpace(customPath) ? customPath : defaultPath;
}
else
{
txtBox.Text = defaultPath;
}
}
catch (Exception ex)
{
Logger.LogError("加载下载路径时出错", ex);
txtBox.Text = defaultPath;
}
}
} }
} }

12
TXT/Build.txt Normal file
View File

@@ -0,0 +1,12 @@
首先,如果希望编译程序,那么必须安装.NET8.0 SDK
下载链接https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/sdk-8.0.411-windows-x64-installer
使用一下指令编译
x86:
dotnet publish AppStore.csproj -c Release -r win-x86 --self-contained false /p:Optimize=true /p:DebugType=None
x64:
dotnet publish AppStore.csproj -c Release -r win-x64 --self-contained false /p:Optimize=true /p:DebugType=None

7
TXT/Run.txt Normal file
View File

@@ -0,0 +1,7 @@
如果希望运行,那么必须安装.NET8.0 SDK
下载链接https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/sdk-8.0.411-windows-x64-installer
使用一下指令运行:
dotnet run

129
ThemeManager.cs Normal file
View File

@@ -0,0 +1,129 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text.Json;
using System.IO;
namespace AppStore
{
public static class ThemeManager
{
public enum ThemeMode
{
Light,
Dark
}
private static readonly string ThemeConfigPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".date", "theme.json");
private static ThemeMode _currentTheme = LoadTheme();
private static ThemeMode LoadTheme()
{
try
{
if (File.Exists(ThemeConfigPath))
{
var json = File.ReadAllText(ThemeConfigPath);
return JsonSerializer.Deserialize<ThemeMode>(json);
}
}
catch
{
// 忽略错误,使用默认主题
}
return ThemeMode.Light;
}
private static void SaveTheme(ThemeMode theme)
{
try
{
var dir = Path.GetDirectoryName(ThemeConfigPath);
if (dir == null) return;
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
var json = JsonSerializer.Serialize(theme);
File.WriteAllText(ThemeConfigPath, json);
}
catch
{
// 忽略错误
}
}
// 浅色主题颜色
private static readonly Color LightBackground = Color.FromArgb(255, 255, 255);
private static readonly Color LightControlBackground = Color.FromArgb(240, 240, 240);
private static readonly Color LightText = Color.FromArgb(30, 30, 30);
private static readonly Color LightButtonHover = Color.FromArgb(230, 230, 230);
private static readonly Color LightButtonActive = Color.FromArgb(220, 220, 220);
// 深色主题颜色
private static readonly Color DarkBackground = Color.FromArgb(30, 30, 30);
private static readonly Color DarkControlBackground = Color.FromArgb(45, 45, 45);
private static readonly Color DarkText = Color.FromArgb(240, 240, 240);
private static readonly Color DarkButtonHover = Color.FromArgb(60, 60, 60);
private static readonly Color DarkButtonActive = Color.FromArgb(70, 70, 70);
public static event Action<ThemeMode> ThemeChanged = delegate {};
public static ThemeMode CurrentTheme
{
get => _currentTheme;
set
{
if (_currentTheme != value)
{
_currentTheme = value;
ThemeChanged?.Invoke(value);
SaveTheme(value);
}
}
}
public static Color BackgroundColor =>
_currentTheme == ThemeMode.Light ? LightBackground : DarkBackground;
public static Color ControlBackgroundColor =>
_currentTheme == ThemeMode.Light ? LightControlBackground : DarkControlBackground;
public static Color TextColor =>
_currentTheme == ThemeMode.Light ? LightText : DarkText;
public static Color ButtonHoverColor =>
_currentTheme == ThemeMode.Light ? LightButtonHover : DarkButtonHover;
public static Color ButtonActiveColor =>
_currentTheme == ThemeMode.Light ? LightButtonActive : DarkButtonActive;
public static void ApplyTheme(Control control)
{
ApplyThemeToControl(control);
}
private static void ApplyThemeToControl(Control control)
{
control.BackColor = BackgroundColor;
control.ForeColor = TextColor;
if (control is Button button)
{
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderSize = 0;
button.FlatAppearance.MouseOverBackColor = ButtonHoverColor;
button.FlatAppearance.MouseDownBackColor = ButtonActiveColor;
}
foreach (Control childControl in control.Controls)
{
ApplyThemeToControl(childControl);
}
}
}
}

View File

@@ -8,6 +8,8 @@ namespace AppStore
{ {
private PictureBox iconBox = new PictureBox(); private PictureBox iconBox = new PictureBox();
private Label nameLabel = new Label(); private Label nameLabel = new Label();
private Panel namePanel = new Panel();
private Color borderColor = SystemColors.ControlDark;
public string ToolName { get; set; } = string.Empty; public string ToolName { get; set; } = string.Empty;
public Image ToolIcon { get; set; } = SystemIcons.Shield.ToBitmap(); public Image ToolIcon { get; set; } = SystemIcons.Shield.ToBitmap();
@@ -37,14 +39,28 @@ namespace AppStore
iconBox.SizeMode = PictureBoxSizeMode.StretchImage; iconBox.SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(iconBox); this.Controls.Add(iconBox);
// 工具名称 // 工具名称 - 使用Panel包裹Label实现边框颜色
namePanel = new Panel();
namePanel.Size = new Size(Width - 20, 30);
namePanel.Location = new Point(10, 100);
namePanel.Paint += (sender, e) => {
ControlPaint.DrawBorder(e.Graphics, namePanel.ClientRectangle,
borderColor, ButtonBorderStyle.Solid);
};
nameLabel = new Label(); nameLabel = new Label();
nameLabel.AutoSize = false; nameLabel.Dock = DockStyle.Fill;
nameLabel.Size = new Size(Width - 20, 30);
nameLabel.Location = new Point(10, 100);
nameLabel.Font = new Font("Microsoft YaHei", 10, FontStyle.Bold); nameLabel.Font = new Font("Microsoft YaHei", 10, FontStyle.Bold);
nameLabel.TextAlign = ContentAlignment.MiddleCenter; nameLabel.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(nameLabel); namePanel.Controls.Add(nameLabel);
// 初始主题设置
UpdateLabelTheme();
// 订阅主题变化事件
ThemeManager.ThemeChanged += (theme) => UpdateLabelTheme();
this.Controls.Add(namePanel);
// 打开按钮 // 打开按钮
var openButton = new Button(); var openButton = new Button();
@@ -68,10 +84,30 @@ namespace AppStore
openButton.FlatAppearance.MouseDownBackColor = Color.FromArgb(0, 80, 160); openButton.FlatAppearance.MouseDownBackColor = Color.FromArgb(0, 80, 160);
} }
private void UpdateLabelTheme()
{
if (ThemeManager.CurrentTheme == ThemeManager.ThemeMode.Dark)
{
nameLabel.BackColor = Color.Black;
nameLabel.ForeColor = Color.White;
namePanel.BackColor = Color.Black;
borderColor = Color.White;
}
else
{
nameLabel.BackColor = Color.White;
nameLabel.ForeColor = Color.Black;
namePanel.BackColor = Color.White;
borderColor = SystemColors.ControlDark;
}
namePanel.Invalidate(); // 触发重绘
}
public void UpdateDisplay() public void UpdateDisplay()
{ {
nameLabel.Text = ToolName; nameLabel.Text = ToolName;
iconBox.Image = ToolIcon; iconBox.Image = ToolIcon;
UpdateLabelTheme();
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

View File

@@ -2,7 +2,7 @@
; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档! ; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档!
#define MyAppName "kortapp-z" #define MyAppName "kortapp-z"
#define MyAppVersion "1.0.9" #define MyAppVersion "1.1.3"
#define MyAppPublisher "zsyg" #define MyAppPublisher "zsyg"
#define MyAppURL "https://github.com/zs-yg/kortapp-z" #define MyAppURL "https://github.com/zs-yg/kortapp-z"
#define MyAppExeName "kortapp.exe" #define MyAppExeName "kortapp.exe"

View File

@@ -2,7 +2,7 @@
; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档! ; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档!
#define MyAppName "kortapp-z" #define MyAppName "kortapp-z"
#define MyAppVersion "1.0.9" #define MyAppVersion "1.1.3"
#define MyAppPublisher "zsyg" #define MyAppPublisher "zsyg"
#define MyAppURL "https://github.com/zs-yg/kortapp-z" #define MyAppURL "https://github.com/zs-yg/kortapp-z"
#define MyAppExeName "kortapp.exe" #define MyAppExeName "kortapp.exe"

View File

@@ -0,0 +1,20 @@
CXX = g++
CXXFLAGS = -std=c++11 -Iinclude
LDFLAGS = -static -mwindows -lfltk -lole32 -luuid -lcomctl32 -lgdi32 -lwsock32 -lcomdlg32 -lwinspool
SRC = $(wildcard src/*.cpp)
OBJ = $(patsubst src/%.cpp,obj/%.o,$(SRC))
TARGET = password_generator
all: $(TARGET)
$(TARGET): $(OBJ)
$(CXX) $^ -o $@ $(LDFLAGS)
obj/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) $(TARGET)
.PHONY: all clean

View File

@@ -0,0 +1,27 @@
#ifndef PASSWORD_GENERATOR_HPP
#define PASSWORD_GENERATOR_HPP
#include "string.hpp"
class PasswordGenerator {
public:
enum Mode {
DIGITS, // 纯数字
ENGLISH, // 纯英文
SYMBOLS, // 纯符号
DIGITS_ENGLISH, // 数字+英文
DIGITS_SYMBOLS, // 数字+符号
ENGLISH_SYMBOLS // 英文+符号
};
PasswordGenerator();
String generate(int length, Mode mode = DIGITS);
private:
String generateDigits(int length);
String generateEnglish(int length);
String generateSymbols(int length);
String generateMixed(int length, const String& charSet);
};
#endif // PASSWORD_GENERATOR_HPP

View File

@@ -0,0 +1,28 @@
#ifndef PASSWORD_GUI_HPP
#define PASSWORD_GUI_HPP
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Output.H>
#include "password_generator.hpp"
class PasswordGUI {
public:
PasswordGUI();
void show();
private:
Fl_Window* window;
Fl_Input* lengthInput;
Fl_Choice* modeChoice;
Fl_Button* generateButton;
Fl_Output* passwordOutput;
PasswordGenerator generator;
static void onGenerate(Fl_Widget* widget, void* data);
};
#endif // PASSWORD_GUI_HPP

View File

@@ -0,0 +1,25 @@
#ifndef STRING_HPP
#define STRING_HPP
#include <cstddef>
class String {
public:
String();
String(const char* str);
String(const String& other);
~String();
size_t length() const;
const char* c_str() const;
String& operator=(const String& other);
String operator+(const String& other) const;
bool operator==(const String& other) const;
private:
char* data;
size_t len;
};
#endif // STRING_HPP

View File

@@ -0,0 +1,7 @@
#include "password_gui.hpp"
int main(int argc, char** argv) {
PasswordGUI gui;
gui.show();
return Fl::run();
}

View File

@@ -0,0 +1,96 @@
#include "password_generator.hpp"
#include <cstdlib>
#include <ctime>
PasswordGenerator::PasswordGenerator() {
srand(time(nullptr));
}
String PasswordGenerator::generate(int length, Mode mode) {
if (length < 1 || length > 100) {
return String("无效长度(1-100)");
}
switch (mode) {
case DIGITS:
return generateDigits(length);
case ENGLISH:
return generateEnglish(length);
case SYMBOLS:
return generateSymbols(length);
case DIGITS_ENGLISH: {
String charSet = String("0123456789") +
String("abcdefghijklmnopqrstuvwxyz") +
String("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
return generateMixed(length, charSet);
}
case DIGITS_SYMBOLS: {
String charSet = String("0123456789") + String("!@#$%^&*()_+-=[]{}|;:,.<>?");
return generateMixed(length, charSet);
}
case ENGLISH_SYMBOLS: {
String charSet = String("abcdefghijklmnopqrstuvwxyz") +
String("ABCDEFGHIJKLMNOPQRSTUVWXYZ") +
String("!@#$%^&*()_+-=[]{}|;:,.<>?");
return generateMixed(length, charSet);
}
default:
return String("不支持的模式");
}
}
String PasswordGenerator::generateDigits(int length) {
char* buffer = new char[length + 1];
for (int i = 0; i < length; ++i) {
buffer[i] = '0' + (rand() % 10);
}
buffer[length] = '\0';
String result(buffer);
delete[] buffer;
return result;
}
String PasswordGenerator::generateEnglish(int length) {
char* buffer = new char[length + 1];
for (int i = 0; i < length; ++i) {
int choice = rand() % 2;
if (choice == 0) {
buffer[i] = 'a' + (rand() % 26); // 小写字母
} else {
buffer[i] = 'A' + (rand() % 26); // 大写字母
}
}
buffer[length] = '\0';
String result(buffer);
delete[] buffer;
return result;
}
String PasswordGenerator::generateSymbols(int length) {
const char symbols[] = "!@#$%^&*()_+-=[]{}|;:,.<>?";
const int symbolCount = sizeof(symbols) - 1; // 减去末尾的\0
char* buffer = new char[length + 1];
for (int i = 0; i < length; ++i) {
buffer[i] = symbols[rand() % symbolCount];
}
buffer[length] = '\0';
String result(buffer);
delete[] buffer;
return result;
}
String PasswordGenerator::generateMixed(int length, const String& charSet) {
char* buffer = new char[length + 1];
for (int i = 0; i < length; ++i) {
buffer[i] = charSet.c_str()[rand() % charSet.length()];
}
buffer[length] = '\0';
String result(buffer);
delete[] buffer;
return result;
}

View File

@@ -0,0 +1,36 @@
#include "password_gui.hpp"
#include <cstdlib>
PasswordGUI::PasswordGUI() {
window = new Fl_Window(400, 350, "密码生成器");
lengthInput = new Fl_Input(150, 50, 200, 30, "密码长度:");
modeChoice = new Fl_Choice(150, 90, 200, 30, "密码模式:");
modeChoice->add("纯数字");
modeChoice->add("纯英文");
modeChoice->add("纯符号");
modeChoice->add("数字+英文");
modeChoice->add("数字+符号");
modeChoice->add("英文+符号");
modeChoice->value(0); // 默认选择纯数字模式
generateButton = new Fl_Button(150, 140, 100, 40, "生成密码");
passwordOutput = new Fl_Output(100, 210, 250, 40, "生成结果:");
generateButton->callback(onGenerate, this);
window->end();
}
void PasswordGUI::show() {
window->show();
}
void PasswordGUI::onGenerate(Fl_Widget* widget, void* data) {
PasswordGUI* gui = static_cast<PasswordGUI*>(data);
const char* lengthStr = gui->lengthInput->value();
int length = atoi(lengthStr);
PasswordGenerator::Mode mode = static_cast<PasswordGenerator::Mode>(gui->modeChoice->value());
String password = gui->generator.generate(length, mode);
gui->passwordOutput->value(password.c_str());
}

View File

@@ -0,0 +1,51 @@
#include "string.hpp"
#include <cstring>
String::String() : data(nullptr), len(0) {}
String::String(const char* str) {
len = strlen(str);
data = new char[len + 1];
strcpy(data, str);
}
String::String(const String& other) {
len = other.len;
data = new char[len + 1];
strcpy(data, other.data);
}
String::~String() {
delete[] data;
}
size_t String::length() const {
return len;
}
const char* String::c_str() const {
return data;
}
String& String::operator=(const String& other) {
if (this != &other) {
delete[] data;
len = other.len;
data = new char[len + 1];
strcpy(data, other.data);
}
return *this;
}
String String::operator+(const String& other) const {
String result;
result.len = len + other.len;
result.data = new char[result.len + 1];
strcpy(result.data, data);
strcat(result.data, other.data);
return result;
}
bool String::operator==(const String& other) const {
return strcmp(data, other.data) == 0;
}

View File

@@ -1,2 +1,2 @@
ren bin\Release\net8.0-windows\win-x86\publish\AppStore.exe kortapp.exe ren bin\Release\net8.0-windows\win-x86\publish\AppStore.exe kortapp-z.exe
ren bin\Release\net8.0-windows\win-x64\publish\AppStore.exe kortapp.exe ren bin\Release\net8.0-windows\win-x64\publish\AppStore.exe kortapp-z.exe

Binary file not shown.

View File

@@ -50,7 +50,10 @@ namespace KortAppZ.Tools.Viewer
} }
currentImage = ImageFileHandler.LoadImage(filePath); currentImage = ImageFileHandler.LoadImage(filePath);
if (pictureBox != null)
{
pictureBox.Image = currentImage; pictureBox.Image = currentImage;
}
this.Text = $"图片查看 - {Path.GetFileName(filePath)}"; this.Text = $"图片查看 - {Path.GetFileName(filePath)}";
} }
catch (Exception ex) catch (Exception ex)