Compare commits

..

59 Commits

Author SHA1 Message Date
zsyg
d54bd4c353 Add files via upload 2025-06-29 09:47:07 +08:00
zsyg
24198b2e09 Add files via upload 2025-06-29 09:46:39 +08:00
zsyg
0a0ef24497 Add files via upload 2025-06-29 09:46:05 +08:00
zsyg
96ab4bc726 添加innosetup脚本 2025-06-29 08:01:13 +08:00
zsyg
be87aaa0e6 Update README.md 2025-06-28 18:27:22 +08:00
zsyg
e8bef7e396 Update README.md 2025-06-28 18:23:41 +08:00
zsyg
7f06c9b6b1 Update README.md 2025-06-28 18:22:59 +08:00
zsyg
0137e43408 添加视频压缩代码 2025-06-28 16:10:13 +08:00
zsyg
3f88a5e5c7 上传视频压缩软件图标 2025-06-28 16:10:11 +08:00
zsyg
ba7ed20664 添加视频压缩程序 2025-06-28 16:09:12 +08:00
zsyg
336b3d3ed9 Add files via upload 2025-06-28 16:08:38 +08:00
zsyg
214a179923 Add files via upload 2025-06-28 13:23:21 +08:00
zsyg
fad8522b88 添加英文README.md 2025-06-28 12:11:31 +08:00
zsyg
337c1853c7 Create CODE_OF_CONDUCT.md 2025-06-28 12:07:38 +08:00
zsyg
cdb54b95c2 Update README.md 2025-06-28 12:04:37 +08:00
zsyg
021e89e3a4 添加系统信息查看器代码 2025-06-28 11:58:36 +08:00
zsyg
dcecf58f23 Add files via upload 2025-06-28 11:56:58 +08:00
zsyg
9b5257c67b Add files via upload 2025-06-28 11:56:26 +08:00
zsyg
90b191a939 Add files via upload 2025-06-28 11:56:04 +08:00
zsyg
4aedf9d97a Add files via upload 2025-06-28 09:05:46 +08:00
zsyg
d3667a2cc8 Add files via upload 2025-06-28 09:01:16 +08:00
zsyg
defd688323 Add files via upload 2025-06-28 09:00:49 +08:00
zsyg
6df4a9a534 添加内存锻炼器代码 2025-06-28 09:00:15 +08:00
zsyg
0efd3a9e32 Update README.md 2025-06-22 18:38:08 +08:00
zsyg
8efa2725aa Add files via upload 2025-06-22 17:46:21 +08:00
zsyg
6fc1ccc9a2 Add files via upload 2025-06-22 17:45:51 +08:00
zsyg
04b551c3c0 Add files via upload 2025-06-22 17:45:23 +08:00
zsyg
ef9a2df02c Add files via upload 2025-06-22 17:14:26 +08:00
zsyg
c25cd37755 Add files via upload 2025-06-22 12:10:39 +08:00
zsyg
6536e99eec Add files via upload 2025-06-22 12:10:19 +08:00
zsyg
0ac791653e Add files via upload 2025-06-22 12:09:14 +08:00
zsyg
45ca7909fd Add files via upload 2025-06-22 12:08:56 +08:00
zsyg
60b459c74a Create CONTRIBUTING.md 2025-06-22 11:20:48 +08:00
zsyg
295af72e4f Create SECURITY.md 2025-06-22 11:17:44 +08:00
zsyg
474f3ecfbc Update issue templates 2025-06-22 11:14:51 +08:00
zsyg
ab37a33443 Update README.md 2025-06-22 11:09:49 +08:00
zsyg
7f8a12c26a Update README.md 2025-06-22 11:03:21 +08:00
zsyg
0f50193705 Update README.md 2025-06-22 11:02:05 +08:00
zsyg
bc01dad692 Update README.md 2025-06-22 11:00:32 +08:00
zsyg
0b58ee3f2e Update README.md 2025-06-22 10:59:44 +08:00
zsyg
51974beaa8 Add files via upload 2025-06-22 10:41:46 +08:00
zsyg
9faa32e985 Add files via upload 2025-06-22 10:41:33 +08:00
zsyg
197f9ae76f Update README.md 2025-06-22 10:36:29 +08:00
zsyg
7d11096f8a Add files via upload 2025-06-22 10:35:17 +08:00
zsyg
f8d02d44c1 Add files via upload 2025-06-22 10:30:12 +08:00
zsyg
c22b653ce0 Add files via upload 2025-06-22 10:04:45 +08:00
zsyg
4b27d2e1dc 添加工具图标 2025-06-22 09:45:33 +08:00
zsyg
0f578d56d4 Add files via upload 2025-06-22 09:44:59 +08:00
zsyg
d36a367147 添加调用程序 2025-06-22 09:42:47 +08:00
zsyg
2c8ce29b3d 修改主要代码 2025-06-22 09:39:58 +08:00
zsyg
efe7d16f96 Add files via upload 2025-06-21 10:14:12 +08:00
zsyg
a5b60d7079 Add files via upload 2025-06-21 10:09:51 +08:00
zsyg
f8192063a4 Add files via upload 2025-06-21 10:08:50 +08:00
zsyg
cd1abd3e33 Add files via upload 2025-06-21 10:02:21 +08:00
zsyg
cc577948b7 Add files via upload 2025-06-21 10:00:38 +08:00
zsyg
0e550c746b Add files via upload 2025-06-20 21:02:53 +08:00
zsyg
7fb9b53e62 Add files via upload 2025-06-20 20:59:58 +08:00
zsyg
80ce2c6151 Add files via upload 2025-06-20 20:58:10 +08:00
zsyg
f2a2f48020 修复部分编译警告 2025-06-19 20:58:49 +08:00
132 changed files with 5962 additions and 326 deletions

38
.github/ISSUE_TEMPLATE/bug反馈.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug反馈
about: Create a report to help us improve
title: ''
labels: ''
assignees: zs-yg
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

10
.github/ISSUE_TEMPLATE/功能建议.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: 功能建议
about: 给我们一些修改建议
title: ''
labels: ''
assignees: ''
---

View File

@@ -0,0 +1,20 @@
---
name: "新功能添加请求\U0001F970\U0001F970\U0001F970"
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -4,14 +4,128 @@ using System.Windows.Forms;
namespace AppStore
{
public class AboutForm : Form
public class AboutUserControl : UserControl
{
public AboutForm()
private PictureBox logo = null!;
private Label infoLabel = null!;
public AboutUserControl()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.Dock = DockStyle.Fill;
this.BackColor = Color.White;
this.Padding = new Padding(20);
// 创建主布局面板
TableLayoutPanel mainLayout = new TableLayoutPanel();
mainLayout.Dock = DockStyle.Fill;
mainLayout.ColumnCount = 1;
mainLayout.RowCount = 2;
mainLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
mainLayout.Padding = new Padding(0, 20, 0, 20);
// 初始化并添加应用图标
logo = new PictureBox();
try
{
logo.Image = Image.FromFile("img/png/kortapp-z.png");
}
catch (Exception ex)
{
Logger.LogError($"无法加载应用图标: {ex.Message}");
logo.Image = SystemIcons.Application.ToBitmap();
}
logo.SizeMode = PictureBoxSizeMode.Zoom;
logo.Width = 200;
logo.Height = 200;
logo.Anchor = AnchorStyles.None;
logo.Margin = new Padding(0, 0, 0, 20);
mainLayout.Controls.Add(logo, 0, 0);
// 初始化并添加应用信息
infoLabel = new Label();
infoLabel.Text = "kortapp-z\n版本: 1.0.8\n作者: zs-yg\n一个简单、开源的应用商店\nkortapp-z是完全免费\n基于.NET8和C/C++的软件";
infoLabel.Font = new Font("Microsoft YaHei", 12);
infoLabel.AutoSize = false;
infoLabel.Width = 300;
infoLabel.Height = 130; // 增加高度确保文字完整显示
infoLabel.TextAlign = ContentAlignment.MiddleCenter;
infoLabel.Anchor = AnchorStyles.None;
mainLayout.Controls.Add(infoLabel, 0, 1);
// 调整主布局为3行
mainLayout.RowCount = 3;
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
mainLayout.RowStyles.Add(new RowStyle(SizeType.AutoSize));
mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
// 在底部添加GitHub链接区域
TableLayoutPanel githubPanel = new TableLayoutPanel();
githubPanel.Dock = DockStyle.Bottom;
githubPanel.Height = 60;
githubPanel.ColumnCount = 3;
githubPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
githubPanel.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
githubPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
githubPanel.RowCount = 1;
githubPanel.Padding = new Padding(10);
// 添加GitHub图标
PictureBox githubIcon = new PictureBox();
try
{
githubIcon.Image = Image.FromFile("img/jpg/github.jpg");
}
catch (Exception ex)
{
Logger.LogError($"无法加载GitHub图标: {ex.Message}");
githubIcon.Image = SystemIcons.Application.ToBitmap();
}
githubIcon.SizeMode = PictureBoxSizeMode.Zoom;
githubIcon.Width = 30;
githubIcon.Height = 30;
githubIcon.Cursor = Cursors.Hand;
githubIcon.Click += (s, e) => {
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = "https://github.com/zs-yg/kortapp-z",
UseShellExecute = true
});
};
// 添加文字说明
Label githubLabel = new Label();
githubLabel.Text = "🤗🤗🤗开源地址 🌟 欢迎点star和提交pr 🚀";
githubLabel.Font = new Font("Microsoft YaHei", 10);
githubLabel.AutoSize = true;
githubLabel.Margin = new Padding(10, 0, 0, 0);
// 创建包含图标和文字的面板
Panel linkPanel = new Panel();
linkPanel.AutoSize = true;
linkPanel.Controls.Add(githubIcon);
linkPanel.Controls.Add(githubLabel);
githubIcon.Location = new Point(0, 0);
githubLabel.Location = new Point(githubIcon.Width + 10, 5);
// 将链接面板添加到中间列
githubPanel.Controls.Add(linkPanel, 1, 0);
this.Controls.Add(mainLayout);
this.Controls.Add(githubPanel);
}
}
// 保留原AboutForm作为容器(可选)
public class AboutForm : Form
{
public AboutForm()
{
this.Text = "关于 kortapp-z";
this.Size = new Size(500, 400);
@@ -20,47 +134,8 @@ namespace AppStore
this.MaximizeBox = false;
this.MinimizeBox = false;
// 添加应用图标
PictureBox logo = new PictureBox();
try
{
logo.Image = Image.FromFile("img/png/kortapp-z.png");
logo.SizeMode = PictureBoxSizeMode.Zoom;
logo.Width = 200;
logo.Height = 200;
logo.Location = new Point((this.Width - logo.Width) / 2, 30);
this.Controls.Add(logo);
}
catch (Exception ex)
{
MessageBox.Show($"无法加载应用图标: {ex.Message}");
}
// 添加应用信息
Label infoLabel = new Label();
infoLabel.Text = "kortapp-z\n版本: 0.9.5\n一个简单、开源的应用商店\nkortapp-z是完全免费的基于.NET8和C++的软件";
infoLabel.Font = new Font("Microsoft YaHei", 12);
infoLabel.AutoSize = false;
infoLabel.Width = this.ClientSize.Width - 40;
infoLabel.Height = 100;
infoLabel.TextAlign = ContentAlignment.MiddleCenter;
infoLabel.Location = new Point(
20,
logo.Bottom + 20
);
this.Controls.Add(infoLabel);
// 添加关闭按钮
Button closeButton = new Button();
closeButton.Text = "关闭";
closeButton.Width = 100;
closeButton.Height = 40;
closeButton.Location = new Point(
(this.Width - closeButton.Width) / 2,
infoLabel.Bottom + 30
);
closeButton.Click += (s, e) => this.Close();
this.Controls.Add(closeButton);
var aboutControl = new AboutUserControl();
this.Controls.Add(aboutControl);
}
}
}

View File

@@ -20,12 +20,18 @@ namespace AppStore
public string AppName { get; set; } = string.Empty;
public Image AppIcon { get; set; } = SystemIcons.Application.ToBitmap();
public string DownloadUrl { get; set; } = string.Empty;
public bool ShowDownloadButton { get; set; } = true;
public AppCard()
{
iconBox = new PictureBox();
nameLabel = new Label();
downloadBtn = new Button();
// 确保关键对象不为null
iconBox = new PictureBox() { SizeMode = PictureBoxSizeMode.StretchImage };
nameLabel = new Label() { Text = string.Empty };
downloadBtn = new Button() { Text = "下载" };
// 确保DownloadManager已初始化
var _ = DownloadManager.Instance;
InitializeComponent();
}
@@ -83,6 +89,7 @@ namespace AppStore
downloadBtn.Click += DownloadBtn_Click;
this.Controls.Add(downloadBtn);
downloadBtn.Visible = ShowDownloadButton;
}
/// <summary>
@@ -241,17 +248,48 @@ namespace AppStore
}
}
// 应用计算好的路径
if (path != null)
// 应用计算好的路径 - 更严格的null检查和异常处理
try
{
var safePath = path ?? CalculatePathFallback(Width, Height, 10);
// 更严格的null检查包括路径和控件状态
if (safePath != null &&
safePath.PointCount > 0 &&
this.IsHandleCreated &&
!this.IsDisposed)
{
this.Invoke((MethodInvoker)delegate {
this.Region = new Region(path); // 设置控件区域
this.Refresh(); // 重绘控件
try
{
// 委托内部再次验证safePath
if (safePath != null && safePath.PointCount > 0)
{
var validPath = safePath; // 确保非null
using (var region = new Region(validPath))
{
this.Region = region;
this.Refresh();
}
}
}
catch (Exception ex)
{
Debug.WriteLine($"创建Region失败: {ex.Message}");
this.Region = null;
this.Refresh();
}
});
}
}
catch (Exception ex)
{
Debug.WriteLine($"初始化卡片路径失败: {ex.Message}");
}
}
private System.Drawing.Drawing2D.GraphicsPath CalculatePathFallback(int width, int height, int radius)
{
try
{
var path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddArc(0, 0, radius * 2, radius * 2, 180, 90);
@@ -261,6 +299,14 @@ namespace AppStore
path.CloseFigure();
return path;
}
catch
{
// 绝对回退方案 - 返回最小有效路径
var path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddRectangle(new Rectangle(0, 0, width, height));
return path;
}
}
public void UpdateDisplay()
{
@@ -269,20 +315,40 @@ namespace AppStore
}
private void DownloadBtn_Click(object sender, EventArgs e)
{
if (sender == null || e == null) return;
if (!string.IsNullOrEmpty(DownloadUrl))
{
try
{
string fileName = $"{AppName.Replace(" ", "_")}.exe";
// 更严格的null检查
// 更严格的null检查包括DownloadManager.Instance和其方法
// 全面的null和状态检查
if (sender == null || e == null ||
string.IsNullOrWhiteSpace(DownloadUrl) ||
string.IsNullOrWhiteSpace(AppName) ||
!this.IsHandleCreated ||
this.IsDisposed ||
DownloadManager.Instance == null ||
DownloadManager.Instance.DownloadItems == null ||
DownloadManager.Instance.StartDownload == null)
{
return;
}
string safeAppName = AppName ?? "未知应用";
string fileName = $"{safeAppName.Replace(" ", "_")}.exe";
DownloadManager.Instance.StartDownload(fileName, DownloadUrl);
MessageBox.Show($"已开始下载: {AppName}", "下载中", MessageBoxButtons.OK, MessageBoxIcon.Information);
string message = $"已开始下载: {safeAppName}";
this.Invoke((MethodInvoker)delegate {
MessageBox.Show(this, message, "下载中", MessageBoxButtons.OK, MessageBoxIcon.Information);
});
}
catch (Exception ex)
{
MessageBox.Show($"下载失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Debug.WriteLine($"下载按钮点击处理失败: {ex.Message}");
this.Invoke((MethodInvoker)delegate {
MessageBox.Show(this, "下载处理发生错误", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
});
}
}
}

View File

@@ -25,7 +25,10 @@
<None Include="img\jpg\*.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="img\ico\icon.ico">
<None Include="img\resource\png\*.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="img\ico\*.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, 和 experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, 和 sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, 和 personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
3872006562.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

12
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,12 @@
# 贡献准则
你可以进行任何(确保安全的前提下)的修改
我会对贡献进行审核,速度很快的
我会定时查看PR
你可以通过Fork到自己的仓库
然后上传软件图标,修改代码
然后提PR
你就可以做出贡献了
当然你也可以进行其他形式的修改
Remeber it!整个世界都在为你而闪耀

BIN
ImageCompressor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

190
ImageCompressorForm.cs Normal file
View File

@@ -0,0 +1,190 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace AppStore
{
public class ImageCompressorForm : Form
{
private Button btnSelectInput = new Button();
private Button btnSelectOutput = new Button();
private Button btnCompress = new Button();
private TextBox txtInput = new TextBox();
private TextBox txtOutput = new TextBox();
private RadioButton rbLossy = new RadioButton();
private RadioButton rbLossless = new RadioButton();
private TrackBar tbQuality = new TrackBar();
private Label lblQuality = new Label();
private CheckBox cbKeepExif = new CheckBox();
private ProgressBar progressBar = new ProgressBar();
public ImageCompressorForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.Text = "图片压缩工具";
this.Size = new Size(500, 350);
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
// 输入文件选择
btnSelectInput.Text = "选择...";
btnSelectInput.Location = new Point(400, 20);
btnSelectInput.Click += (s, e) => SelectFile(txtInput);
this.Controls.Add(btnSelectInput);
txtInput.Location = new Point(20, 20);
txtInput.Size = new Size(370, 20);
txtInput.ReadOnly = true;
this.Controls.Add(txtInput);
Label lblInput = new Label();
lblInput.Text = "输入文件:";
lblInput.Location = new Point(20, 0);
this.Controls.Add(lblInput);
// 输出文件选择
btnSelectOutput.Text = "选择...";
btnSelectOutput.Location = new Point(400, 70);
btnSelectOutput.Click += (s, e) => SelectFile(txtOutput, true);
this.Controls.Add(btnSelectOutput);
txtOutput.Location = new Point(20, 70);
txtOutput.Size = new Size(370, 20);
this.Controls.Add(txtOutput);
Label lblOutput = new Label();
lblOutput.Text = "输出文件:";
lblOutput.Location = new Point(20, 50);
this.Controls.Add(lblOutput);
// 压缩类型
rbLossy.Text = "有损压缩 (JPEG)";
rbLossy.Location = new Point(20, 110);
rbLossy.Checked = true;
this.Controls.Add(rbLossy);
rbLossless.Text = "无损压缩 (PNG)";
rbLossless.Location = new Point(20, 135);
this.Controls.Add(rbLossless);
// 质量设置
tbQuality.Minimum = 1;
tbQuality.Maximum = 1000;
tbQuality.Value = 800;
tbQuality.Location = new Point(20, 190);
tbQuality.Size = new Size(300, 50);
tbQuality.Scroll += (s, e) => lblQuality.Text = $"压缩质量: {tbQuality.Value}";
this.Controls.Add(tbQuality);
lblQuality.Text = $"压缩质量: {tbQuality.Value}";
lblQuality.Location = new Point(20, 170);
this.Controls.Add(lblQuality);
// EXIF选项
cbKeepExif.Text = "保留EXIF信息";
cbKeepExif.Location = new Point(20, 240);
this.Controls.Add(cbKeepExif);
// 压缩按钮
btnCompress.Text = "开始压缩";
btnCompress.Location = new Point(20, 280);
btnCompress.Size = new Size(460, 30);
btnCompress.Click += BtnCompress_Click;
this.Controls.Add(btnCompress);
// 调整窗体大小
this.Size = new Size(500, 370);
}
private void SelectFile(TextBox target, bool isSave = false)
{
var dialog = isSave ? new SaveFileDialog() : new OpenFileDialog() as FileDialog;
dialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp|所有文件|*.*";
if (dialog.ShowDialog() == DialogResult.OK)
{
target.Text = dialog.FileName;
}
}
private void BtnCompress_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtInput.Text) || !File.Exists(txtInput.Text))
{
MessageBox.Show("请选择有效的输入文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (string.IsNullOrEmpty(txtOutput.Text))
{
MessageBox.Show("请指定输出文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
btnCompress.Enabled = false;
try
{
string toolPath = Path.Combine(Application.StartupPath, "resource", "image_compressor.exe");
if (!File.Exists(toolPath))
{
MessageBox.Show("图片压缩工具未找到", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string args = $"\"{txtInput.Text}\" \"{txtOutput.Text}\"";
args += $" -t {(rbLossy.Checked ? "lossy" : "lossless")}";
args += $" -q {tbQuality.Value}";
if (cbKeepExif.Checked) args += " -e";
var process = new Process();
process.StartInfo.FileName = toolPath;
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += (s, ev) => {
if (!string.IsNullOrEmpty(ev.Data))
Console.WriteLine(ev.Data);
};
process.ErrorDataReceived += (s, ev) => {
if (!string.IsNullOrEmpty(ev.Data))
Console.Error.WriteLine(ev.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
if (process.ExitCode == 0)
{
MessageBox.Show("图片压缩完成", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("图片压缩失败", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception ex)
{
MessageBox.Show($"压缩过程中发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
btnCompress.Enabled = true;
progressBar.Visible = false;
}
}
}
}

View File

@@ -2,6 +2,11 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Diagnostics;
using AppStore;
namespace AppStore
@@ -11,6 +16,106 @@ namespace AppStore
/// </summary>
public class MainForm : Form
{
private static readonly string CacheDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".cache");
private class AppPositionCache
{
public string AppName { get; set; } = string.Empty;
public int X { get; set; }
public int Y { get; set; }
public DateTime LastUpdated { get; set; } = DateTime.Now;
}
private static string GetPositionCacheFilePath(string appName)
{
using var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(appName));
var fileName = BitConverter.ToString(hash).Replace("-", "").ToLower() + ".json";
return Path.Combine(CacheDir, fileName);
}
private static void EnsureCacheDirectory()
{
try
{
if (!Directory.Exists(CacheDir))
{
Directory.CreateDirectory(CacheDir);
Logger.Log($"已创建缓存目录: {CacheDir}");
}
}
catch (Exception ex)
{
Logger.LogError($"创建缓存目录失败: {CacheDir}", ex);
throw;
}
}
private static bool TryReadPositionCache(string appName, out AppPositionCache? cacheData)
{
cacheData = null;
var cacheFile = GetPositionCacheFilePath(appName);
if (!File.Exists(cacheFile))
return false;
try
{
var json = File.ReadAllText(cacheFile);
cacheData = JsonSerializer.Deserialize<AppPositionCache>(json);
return cacheData != null;
}
catch
{
return false;
}
}
private static void WritePositionCache(string appName, Point position)
{
try
{
EnsureCacheDirectory();
var cacheFile = GetPositionCacheFilePath(appName);
var cacheData = new AppPositionCache
{
AppName = appName,
X = position.X,
Y = position.Y,
LastUpdated = DateTime.Now
};
var json = JsonSerializer.Serialize(cacheData);
File.WriteAllText(cacheFile, json);
Logger.Log($"已保存位置缓存: {appName} ({position.X}, {position.Y})");
}
catch (Exception ex)
{
Logger.LogError($"保存位置缓存失败: {appName}", ex);
throw;
}
}
private static bool IsPositionCacheValid(AppPositionCache cacheData)
{
// 缓存有效期设为7天
return (DateTime.Now - cacheData.LastUpdated).TotalDays <= 7;
}
private static void SaveAllCardPositions(FlowLayoutPanel flowPanel)
{
foreach (Control control in flowPanel.Controls)
{
if (control is AppCard card)
{
WritePositionCache(card.AppName, control.Location);
}
}
}
// 软件下载按钮
private Button btnApps = null!;
// 下载进度按钮
@@ -41,6 +146,9 @@ namespace AppStore
buttonPanel.Height = 70;
buttonPanel.BackColor = Color.FromArgb(240, 240, 240);
buttonPanel.Padding = new Padding(10, 15, 10, 0);
buttonPanel.AutoScroll = true;
buttonPanel.AutoSize = true;
buttonPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
// 导航按钮样式
Action<Button> styleButton = (Button btn) => {
@@ -104,11 +212,21 @@ namespace AppStore
styleButton(btnAbout);
btnAbout.Click += (s, e) => {
Logger.Log("用户点击了'关于'按钮");
var aboutForm = new AboutForm();
aboutForm.ShowDialog();
ShowAboutView();
};
buttonPanel.Controls.Add(btnAbout);
// 内置工具按钮
var btnTools = new Button();
btnTools.Text = "内置工具";
btnTools.Location = new Point(590, 0);
styleButton(btnTools);
btnTools.Click += (s, e) => {
Logger.Log("用户点击了'内置工具'按钮");
ShowToolsView();
};
buttonPanel.Controls.Add(btnTools);
// 现代化内容区域
contentPanel = new Panel();
contentPanel.Dock = DockStyle.Fill;
@@ -135,8 +253,269 @@ namespace AppStore
/// </summary>
private void ShowSettingsView()
{
var settingsForm = new SettingsForm();
settingsForm.ShowDialog(); // 以模态对话框形式显示设置窗口
contentPanel.Controls.Clear();
var settingsControl = new SettingsUserControl();
contentPanel.Controls.Add(settingsControl);
}
private void ShowToolsView()
{
try
{
contentPanel.Controls.Clear();
var flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.AutoScroll = true;
flowPanel.WrapContents = true;
flowPanel.FlowDirection = FlowDirection.LeftToRight;
flowPanel.Padding = new Padding(15, 50, 15, 15);
flowPanel.Margin = new Padding(0);
flowPanel.AutoSize = true;
flowPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
flowPanel.AutoScrollMinSize = new Size(0, 3350);
contentPanel.Controls.Add(flowPanel);
// 系统清理卡片
var cleanerCard = new ToolCard();
cleanerCard.ToolName = "系统清理";
try
{
cleanerCard.ToolIcon = Image.FromFile("img/resource/png/system_cleaner.png");
}
catch
{
cleanerCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
cleanerCard.UpdateDisplay();
cleanerCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "system_cleaner.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);
}
};
flowPanel.Controls.Add(cleanerCard);
// 二维码生成卡片
var qrCard = new ToolCard();
qrCard.ToolName = "二维码生成";
try
{
qrCard.ToolIcon = Image.FromFile("img/resource/png/QRcode.png");
}
catch
{
qrCard.ToolIcon = SystemIcons.Application.ToBitmap();
}
qrCard.UpdateDisplay();
qrCard.ToolCardClicked += (s, e) => {
try {
var qrForm = new QrCodeGeneratorForm();
qrForm.ShowDialog();
} catch (Exception ex) {
MessageBox.Show($"启动二维码生成工具失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
flowPanel.Controls.Add(qrCard);
// 图片压缩卡片
var imageCompressorCard = new ToolCard();
imageCompressorCard.ToolName = "图片压缩";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png","ImageCompressor.png");
if (File.Exists(iconPath))
{
imageCompressorCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
imageCompressorCard.ToolIcon = SystemIcons.Application.ToBitmap();
}
}
catch
{
imageCompressorCard.ToolIcon = SystemIcons.Application.ToBitmap();
}
imageCompressorCard.UpdateDisplay();
imageCompressorCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "image_compressor.exe");
if (File.Exists(toolPath)) {
var form = new ImageCompressorForm();
form.ShowDialog();
} else {
MessageBox.Show("图片压缩工具未找到,请确保已正确安装", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch (Exception ex) {
MessageBox.Show($"启动图片压缩工具失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
flowPanel.Controls.Add(imageCompressorCard);
// 内存锻炼器卡片
var memoryTrainerCard = new ToolCard();
memoryTrainerCard.ToolName = "内存锻炼器";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "memory_trainer.png");
if (File.Exists(iconPath))
{
memoryTrainerCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
memoryTrainerCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
}
catch
{
memoryTrainerCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
memoryTrainerCard.UpdateDisplay();
memoryTrainerCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "memory_trainer.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);
}
};
flowPanel.Controls.Add(memoryTrainerCard);
// 系统信息查看器卡片
var systemInfoCard = new ToolCard();
systemInfoCard.ToolName = "系统信息查看器";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "system_info.png");
if (File.Exists(iconPath))
{
systemInfoCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
systemInfoCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
}
catch
{
systemInfoCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
systemInfoCard.UpdateDisplay();
systemInfoCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "system_info.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);
}
};
flowPanel.Controls.Add(systemInfoCard);
// 视频压缩工具卡片
var videoCompressorCard = new ToolCard();
videoCompressorCard.ToolName = "视频压缩工具";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "video_compressor.png");
if (File.Exists(iconPath))
{
videoCompressorCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
videoCompressorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
}
catch
{
videoCompressorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
videoCompressorCard.UpdateDisplay();
videoCompressorCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "video_compressor.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);
}
};
flowPanel.Controls.Add(videoCompressorCard);
// 计算器工具卡片
var calculatorCard = new CalculatorToolCard();
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "Calculator.png");
if (File.Exists(iconPath))
{
calculatorCard.ToolIcon = Image.FromFile(iconPath);
}
calculatorCard.UpdateDisplay();
}
catch (Exception ex)
{
Logger.LogError("加载计算器图标失败", ex);
}
flowPanel.Controls.Add(calculatorCard);
}
catch (Exception ex)
{
Logger.LogError("显示内置工具视图时出错", ex);
MessageBox.Show("加载内置工具时发生错误,请重试", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
ShowAppsView(); // 回退到默认视图
}
}
private void ShowAboutView()
{
contentPanel.Controls.Clear();
var aboutControl = new AboutUserControl();
contentPanel.Controls.Add(aboutControl);
}
/// <summary>
@@ -157,10 +536,8 @@ namespace AppStore
{
// 创建新的应用卡片实例
AppCard card = new AppCard();
// 设置卡片基本属性
card.AppName = appName; // 设置显示的应用名称
card.DownloadUrl = downloadUrl; // 设置下载链接地址
card.AppName = appName;
card.DownloadUrl = downloadUrl;
try
{
@@ -182,35 +559,195 @@ namespace AppStore
return card;
}
private void ShowAppsView()
private async void ShowAppsView()
{
contentPanel.Controls.Clear();
// 使用FlowLayoutPanel来组织应用卡片
// 创建应用卡片面板
FlowLayoutPanel flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.AutoScroll = true;
flowPanel.Padding = new Padding(15, 50, 15, 15); // 恢复原有内边距
flowPanel.Padding = new Padding(15, 15, 15, 15);
flowPanel.WrapContents = true;
flowPanel.Margin = new Padding(0);
flowPanel.AutoSize = true;
flowPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
flowPanel.AutoScrollMinSize = new Size(0, 999999); // 增加滑动距离
flowPanel.AutoScrollMinSize = new Size(0, 3350);
// 创建搜索框
TextBox searchBox = new TextBox();
searchBox.Width = 300;
searchBox.Height = 32;
searchBox.Font = new Font("Microsoft YaHei", 10);
searchBox.PlaceholderText = "搜索应用...";
searchBox.BorderStyle = BorderStyle.FixedSingle;
searchBox.BackColor = Color.White;
searchBox.ForeColor = Color.FromArgb(64, 64, 64);
searchBox.Location = new Point((contentPanel.Width - searchBox.Width) / 2, 20);
// 响应窗体大小变化
contentPanel.Resize += (s, e) => {
searchBox.Location = new Point((contentPanel.Width - searchBox.Width) / 2, 20);
};
// 搜索框事件
searchBox.TextChanged += (s, e) => {
AppSearch.SearchApps(flowPanel, searchBox.Text);
};
contentPanel.Controls.Add(searchBox);
contentPanel.Controls.Add(flowPanel);
flowPanel.Dock = DockStyle.Fill;
flowPanel.AutoScroll = true;
flowPanel.Padding = new Padding(15, 60, 15, 15);
flowPanel.WrapContents = true;
flowPanel.Margin = new Padding(0);
flowPanel.AutoSize = true;
flowPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
flowPanel.AutoScrollMinSize = new Size(0, 3350);
contentPanel.Controls.Add(flowPanel);
// 添加所有应用卡片
// 添加窗体关闭事件处理
this.FormClosing += (sender, e) => {
SaveAllCardPositions(flowPanel);
};
// 确保控件已创建
await Task.Delay(100);
try
{
// 异步添加卡片
await Task.Run(() => {
if (flowPanel.IsHandleCreated)
{
flowPanel.Invoke((MethodInvoker)delegate {
AddAllAppCards(flowPanel);
});
}
});
}
catch (Exception ex)
{
Logger.LogError("渲染应用卡片时出错", ex);
}
}
private void AddAllAppCards(FlowLayoutPanel flowPanel)
{
flowPanel.Dock = DockStyle.Fill;
flowPanel.AutoScroll = true;
flowPanel.Padding = new Padding(15, 50, 15, 15);
flowPanel.WrapContents = true;
flowPanel.Margin = new Padding(0);
flowPanel.AutoSize = true;
flowPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
flowPanel.AutoScrollMinSize = new Size(0, 3350);
contentPanel.Controls.Add(flowPanel);
// 添加所有应用卡片并恢复位置
flowPanel.Controls.Add(CreateAppCard(
"XDM",
"https://github.com/subhra74/xdm/releases/download/7.2.11/xdm-setup.msi",
"img/png/XDM.png"));
flowPanel.Controls.Add(CreateAppCard(
"FDM",
"https://files2.freedownloadmanager.org/6/latest/fdm_x64_setup.exe",
"img/png/FDM.png"));
flowPanel.Controls.Add(CreateAppCard(
"ABDM",
"https://ghproxy.net/https://github.com/amir1376/ab-download-manager/releases/download/v1.6.4/ABDownloadManager_1.6.4_windows_x64.exe",
"img/png/ABDM.png"));
flowPanel.Controls.Add(CreateAppCard(
"NDM",
"https://ghproxy.net/https://github.com/zs-yg/package/releases/download/v0.7/NeatDM_setup.exe",
"img/jpg/NDM.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"youtube-dl",
"https://ghproxy.net/https://github.com/ytdl-org/youtube-dl/releases/download/2021.12.17/youtube-dl.exe",
""));
flowPanel.Controls.Add(CreateAppCard(
"python3.8",
"https://www.python.org/ftp/python/3.8.0/python-3.8.0-amd64.exe",
"img/png/python.png"));
flowPanel.Controls.Add(CreateAppCard(
"Oracle Java8",
"https://sdlc-esd.oracle.com/ESD6/JSCDL/jdk/8u451-b10/8a1589aa0fe24566b4337beee47c2d29/jre-8u451-windows-x64.exe?GroupName=JSC&FilePath=/ESD6/JSCDL/jdk/8u451-b10/8a1589aa0fe24566b4337beee47c2d29/jre-8u451-windows-x64.exe&BHost=javadl.sun.com&File=jre-8u451-windows-x64.exe&AuthParam=1750252610_4d0f61835e3392b8f0158398fd5ebd90&ext=.exe",
"img/png/java.png"));
flowPanel.Controls.Add(CreateAppCard(
"Rust",
"https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe",
"img/png/rust.png"));
flowPanel.Controls.Add(CreateAppCard(
"Ruby",
"https://mirror.sjtu.edu.cn/github-release/oneclick/rubyinstaller2/releases/download/RubyInstaller-3.4.4-2/rubyinstaller-devkit-3.4.4-2-x64.exe",
"img/png/ruby.png"));
flowPanel.Controls.Add(CreateAppCard(
"D",
"https://downloads.dlang.org/releases/2.x/2.111.0/dmd-2.111.0.exe",
"img/jpg/D.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Go",
"https://golang.google.cn/dl/go1.24.4.windows-amd64.msi",
"img/png/Go.png"));
flowPanel.Controls.Add(CreateAppCard(
"Node.js",
"https://nodejs.org/dist/v22.16.0/node-v22.16.0-x64.msi",
"img/png/nodejs.png"));
flowPanel.Controls.Add(CreateAppCard(
"mingw-64",
"https://ghproxy.net/https://github.com/niXman/mingw-builds-binaries/releases/download/15.1.0-rt_v12-rev0/x86_64-15.1.0-release-posix-seh-ucrt-rt_v12-rev0.7z",
"img/png/mingw-64.png"));
flowPanel.Controls.Add(CreateAppCard(
"Msys2",
"https://github.com/msys2/msys2-installer/releases/download/2025-02-21/msys2-x86_64-20250221.exe",
"img/png/MSYS2.png"));
flowPanel.Controls.Add(CreateAppCard(
".NET SDK 8.0",
"https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/sdk-8.0.411-windows-x64-installer",
"img/png/.NET.png"));
flowPanel.Controls.Add(CreateAppCard(
"ASP.NET Core 运行时 8.0",
"https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-aspnetcore-8.0.17-windows-x64-installer",
"img/png/.NET.png"));
flowPanel.Controls.Add(CreateAppCard(
".NET 桌面运行时 8.0",
"https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-8.0.17-windows-x64-installer",
"img/png/.NET.png"));
flowPanel.Controls.Add(CreateAppCard(
".NET 运行时 8.0",
"https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-8.0.17-windows-x64-installer",
"img/png/.NET.png"));
flowPanel.Controls.Add(CreateAppCard(
"openlist",
"https://ghproxy.net/https://github.com/OpenListTeam/OpenList/releases/download/beta/openlist-windows-amd64.zip",
"img/png/openlist.png"));
flowPanel.Controls.Add(CreateAppCard(
"SpaceSniffer",
"https://ghproxy.net/https://github.com/zs-yg/package/releases/download/v0.8/SpaceSniffer.exe",
"img/png/SpaceSniffer.png"));
flowPanel.Controls.Add(CreateAppCard(
"OpenSpeedy",
"https://ghproxy.net/https://github.com/game1024/OpenSpeedy/releases/download/v1.7.1/OpenSpeedy-v1.7.1.zip",
@@ -226,6 +763,16 @@ namespace AppStore
"https://vscode.download.prss.microsoft.com/dbazure/download/stable/dfaf44141ea9deb3b4096f7cd6d24e00c147a4b1/VSCodeSetup-x64-1.101.0.exe",
"img/png/vscode.png"));
flowPanel.Controls.Add(CreateAppCard(
"vs community 2022",
"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false",
"img/jpg/vs.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"VSCodium",
"https://visualstudio.microsoft.com/zh-hans/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false",
"img/png/codium_cnl.png"));
flowPanel.Controls.Add(CreateAppCard(
"7-Zip",
"https://objects.githubusercontent.com/github-production-release-asset-2e65be/466446150/1645817e-3677-4207-93ff-e62de7e147be?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20250613%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250613T035936Z&X-Amz-Expires=300&X-Amz-Signature=5e02d5fc34f45bd8308029c9fc78052007e9475ce0e32775619921cb8f3b83ea&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3D7z2409-x64.exe&response-content-type=application%2Foctet-stream",
@@ -236,11 +783,41 @@ namespace AppStore
"https://ghproxy.net/https://github.com/zs-yg/package/releases/download/v0.1/7-Zip.7z",
"img/png/7ziplogo.png"));
flowPanel.Controls.Add(CreateAppCard(
"peazip",
"https://ghproxy.net/https://github.com/peazip/PeaZip/releases/download/10.4.0/peazip-10.4.0.WIN64.exe",
"img/jpg/peazip.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"nanazip",
"https://ghproxy.net/https://github.com/M2Team/NanaZip/releases/download/5.0.1263.0/NanaZip_5.0.1263.0_DebugSymbols.zip",
"img/png/nanazip.png"));
flowPanel.Controls.Add(CreateAppCard(
"PCL2",
"https://ghproxy.net/https://github.com/zs-yg/package/releases/download/v0.9/Plain.Craft.Launcher.2.exe",
"img/jpg/pcl2.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"GreenShot",
"https://objects.githubusercontent.com/github-production-release-asset-2e65be/36756917/239aedb0-7d29-11e7-9f9c-d36ec4466ade?X-Amz-Algorithm=AWS4-HMAC-SSHA256&X-Amz-Credential=releaseassetproduction%2F20250613%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250613T041723Z&X-Amz-Expires=300&X-Amz-Signature=be1ef88a68bbc7065af5111809d11de881022933b44f6d961eb6bd6e6b7e60a8&X-Amz-SignedHeaders=host&response-content-disposition=attachment%3B%20filename%3DGreenshot-INSTALLER-1.2.10.6-RELEASE.exe&response-content-type=application%2Foctet-stream",
"img/png/greenshot-logo.png"));
flowPanel.Controls.Add(CreateAppCard(
"DWMBlurGlass",
"https://ghproxy.net/https://github.com/Maplespe/DWMBlurGlass/releases/download/2.3.1r/DWMBlurGlass_2.3.1_x64.zip",
"img/png/DWMBlurGlass.png"));
flowPanel.Controls.Add(CreateAppCard(
"Umi-OCR",
"https://ghproxy.net/https://github.com/hiroi-sora/Umi-OCR/releases/download/v2.1.5/Umi-OCR_Paddle_v2.1.5.7z.exe",
"img/png/Umi-OCR.png"));
flowPanel.Controls.Add(CreateAppCard(
"frp",
"https://github.com/fatedier/frp/releases/download/v0.62.1/frp_0.62.1_windows_amd64.zip",
""));
flowPanel.Controls.Add(CreateAppCard(
"VLC Media Player",
"https://mirrors.ustc.edu.cn/videolan-ftp/vlc/3.0.21/win64/vlc-3.0.21-win64.exe",
@@ -276,25 +853,31 @@ namespace AppStore
"https://ghproxy.net/https://github.com/mifi/lossless-cut/releases/download/v3.64.0/LosslessCut-win-x64.7z",
"img/png/LosslessCut.png"));
flowPanel.Controls.Add(CreateAppCard(
"mingw-64",
"https://ghproxy.net/https://github.com/niXman/mingw-builds-binaries/releases/download/15.1.0-rt_v12-rev0/x86_64-15.1.0-release-posix-seh-ucrt-rt_v12-rev0.7z",
"img/png/mingw-64.png"));
flowPanel.Controls.Add(CreateAppCard(
"Edge",
"https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/cb21e6b5-3f63-4df2-bec3-a2015b80dc56/MicrosoftEdgeEnterpriseX64.msi",
"img/jpg/edge.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Min",
"https://ghproxy.net/https://github.com/minbrowser/min/releases/download/v1.35.0/min-1.35.0-setup.exe",
"img/jpg/Min.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Brave",
"https://ghproxy.net/https://github.com/brave/brave-browser/releases/download/v1.79.126/BraveBrowserSetup.exe",
"img/png/brave.png"));
flowPanel.Controls.Add(CreateAppCard(
"Firefox",
"https://download-ssl.firefox.com.cn/releases-sha2/full/116.0/zh-CN/Firefox-full-latest-win64.exe",
"img/jpg/firefox.jpg"));
//这应该是为数不多的国产软件了
flowPanel.Controls.Add(CreateAppCard(
"Msys2",
"https://github.com/msys2/msys2-installer/releases/download/2025-02-21/msys2-x86_64-20250221.exe",
"img/png/MSYS2.png"));
"星愿浏览器",
"https://d1.twinkstar.com/win/Twinkstar_v10.7.1000.2505_Release.exe",
"img/jpg/Twinkstar.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Mem Reduct",
@@ -371,11 +954,6 @@ namespace AppStore
"https://ghproxy.net/https://github.com/microsoft/TypeScript/releases/download/v5.8.3/typescript-5.8.3.tgz",
""));
flowPanel.Controls.Add(CreateAppCard(
"peazip",
"https://ghproxy.net/https://github.com/peazip/PeaZip/releases/download/10.4.0/peazip-10.4.0.WIN64.exe",
"img/jpg/peazip.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Gimp",
"https://mirror.nju.edu.cn/gimp/gimp/v3.0/windows/gimp-3.0.4-setup.exe",
@@ -625,21 +1203,6 @@ namespace AppStore
"Ditto",
"https://ghproxy.net/https://github.com/sabrogden/Ditto/releases/download/3.24.246.0/DittoSetup_64bit_3_24_246_0.exe",
"img/png/Ditto.png"));
flowPanel.Controls.Add(CreateAppCard(
"XDM",
"https://github.com/subhra74/xdm/releases/download/7.2.11/xdm-setup.msi",
"img/png/XDM.png"));
flowPanel.Controls.Add(CreateAppCard(
"FDM",
"https://files2.freedownloadmanager.org/6/latest/fdm_x64_setup.exe",
"img/png/FDM.png"));
flowPanel.Controls.Add(CreateAppCard(
"ABDM",
"https://ghproxy.net/https://github.com/amir1376/ab-download-manager/releases/download/v1.6.4/ABDownloadManager_1.6.4_windows_x64.exe",
"img/png/ABDM.png"));
}
private FlowLayoutPanel downloadsFlowPanel = new FlowLayoutPanel();

View File

@@ -16,13 +16,8 @@
## 项目简介
![image](https://gitee.com/chr_super/kortapp-z/raw/master/img/pngimage.png)
这个图片可能有点问题因为它是gitee仓库中的图片
这是为了加快图片渲染速度但是它好像只能渲染一半在gitee是正常的
这个我没什么办法了
一个简单的Windows应用商店应用提供软件下载和管理功能。
提供软件管理、下载管理、内置工具使用等功能
## 功能特点
@@ -30,6 +25,7 @@
- 下载进度管理
- 支持后台下载
- 美观的应用卡片展示
- 功能化、结构化的代码处理
## 构建与打包
@@ -61,7 +57,7 @@ bin\Release\net8.0-windows\[platform]\publish
## 项目结构
```
AppStore/
kortapp-z/
├── MainForm.cs # 主窗体逻辑
├── DownloadManager.cs # 下载管理
├── AppCard.cs # 应用卡片控件
@@ -82,16 +78,30 @@ AppStore/
MIT License
Copyright (c) 2025 kortapp-z项目组
Copyright (c) 2025 zsyg
## 其他网站
gitee镜像仓库:https://gitee.com/chr_super/kortapp-z
gitee镜像仓库:https://gitee.com/chr_super/kortapp-z (目前已经停止维护)
## 维护
由于gitee我没怎么用而且操作麻烦gitee镜像将不会继续同步有懂得人可以帮我搞下镜像吗qq 3872006562也可以b站直接私信我会在readme中鸣谢的谢谢各位
由于和Daye发生了矛盾所以windowscleaner将永远不上架我要自己努力
提示由于github上传文件的限制img/png/NET.png请改名为.NET.png否则程序可能出现无法预料的问题
每一个人都可以通过PR添加属于自己的合法软件
作者邮箱:
```
3872006562@qq.com
```
作者qq号:
```
3872006562
```
qq群
```
1043867176

135
README/de-DE_README.md Normal file
View File

@@ -0,0 +1,135 @@
# Kortapp-z - Windows App Store
**Open-Source, kostenlos, werbefrei**
Grundsatz: Keine Werbung, kontinuierliche Updates
## Open-Source-Richtlinien
1. **Open-Source-Code**: Nutzung, Modifikation, Verbreitung und kommerzielle Nutzung erlaubt, mit Pflicht zur Nennung des Originalautors.
2. **Open-Source-Dokumentation**: Gleiche Bedingungen wie für Code.
3. **Open-Source-Ressourcen** (Icons, Screenshots): Gleiche Bedingungen.
4. Alle abgeleiteten Produkte (Websites, Apps, Erweiterungen etc.) müssen diese Lizenz einhalten.
5. **Keine Werbung** in keiner Form.
6. **Keine Spenden** werden angenommen.
7. **Keine Sponsoring** wird angenommen.
8. **Pull Requests (PR) sind willkommen**, auch ohne vorheriges Issue.
9. Eigene Projekte können per PR eingereicht werden, aber solche mit unter **1000 Stars** werden gelöscht.
## Projektbeschreibung
Eine einfache Windows-App zum Herunterladen und Verwalten von Software.
**Hauptfunktionen:**
- Softwareverwaltung
- Download-Manager
- Integrierte Tools
## Hauptmerkmale
- Minimalistische Download-Oberfläche
- Download-Fortschrittsverfolgung
- Hintergrund-Downloads
- Visuell ansprechende App-Karten
- Sauberer und strukturierter Code
## Build und Packaging
### Systemanforderungen
- **.NET 8.0 SDK**
- **Windows 10/11**
### Build-Befehle
#### 32-Bit-Version
```bash
dotnet publish -c Release -r win-x86 -p:PublishSingleFile=true
```
#### 64-Bit-Version
```bash
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true
```
Erstellte Dateien werden unter folgendem Pfad abgelegt:
```
bin\Release\net8.0-windows\[Plattform]\publish
```
### Zusätzliche Optionen
- `--self-contained true` eigenständige Builds (größere Dateien)
- `-p:PublishTrimmed=true` Größenreduzierung (experimentell)
## Projektstruktur
```
kortapp-z/
├── MainForm.cs # Hauptfenster-Logik
├── DownloadManager.cs # Download-Manager
├── AppCard.cs # App-Karte
├── DownloadItem.cs # Download-Element
├── img/ # Grafiken
│ ├── ico/ # Icons
│ └── png/ # Screenshots
└── resource/ # Ressourcen
└── aria2c.exe # Download-Tool
```
## Laufzeitanforderungen
- **.NET 8.0 Runtime** (bei Framework-abhängiger Build)
- **Windows 10 oder neuer**
## Lizenz
**MIT License**
Copyright (c) 2025 zsyg
## Andere Plattformen
**Gitee-Mirror**: [https://gitee.com/chr_super/kortapp-z](https://gitee.com/chr_super/kortapp-z) (nicht mehr gewartet)
## Wartung
Der Gitee-Repository wird nicht mehr synchronisiert. Hilfe beim Mirroring ist willkommen:
- **QQ**: 3872006562
- **Bilibili (Direktnachricht)**: Zayisynth
**Wichtig:**
- Aufgrund eines Konflikts mit Daye wird **windowscleaner** nie hinzugefügt.
- Benennen Sie `img/png/NET.png` in `.NET.png` um, um Fehler zu vermeiden (GitHub-Beschränkungen).
## Mitwirken
Jeder kann legale Software per Pull Request vorschlagen.
## Kontakt
📧 **Email**:
```
3872006562@qq.com
```
📱 **QQ**:
```
3872006562
```
👥 **QQ-Gruppe**:
```
1043867176
```
🎥 **Bilibili**:
```
Zayisynth
```
---
### Wie sollte die deutsche README benannt werden?
Empfohlene Optionen:
1. **de-DE_README.md** (IETF-Standard)
2. **README_de.md** (kürzere Variante)
3. **DE_README.md** (explizite Sprachkennung)
Am besten halten Sie sich an das Format `[Sprachcode]_README.md`, wie bei anderen Übersetzungen.

123
README/fr-FR_README.md Normal file
View File

@@ -0,0 +1,123 @@
# Kortapp-z - Microsoft Store -- Logiciel open source, gratuit et sans publicité
Engagement : aucune publicité acceptée, mises à jour continues
## Politique open source
1. Code open source : utilisation, modification, distribution et usage commercial autorisés, avec mention de l'auteur original obligatoire.
2. Documentation open source : mêmes conditions que le code.
3. Ressources graphiques (icônes, captures d'écran) open source : mêmes conditions.
4. Tout produit dérivé (sites web, apps, extensions...) doit respecter cette licence.
5. Aucune publicité n'est acceptée, sous aucune forme.
6. Aucun don n'est accepté.
7. Aucun sponsoring n'est accepté.
8. Les Pull Requests (PR) sont bienvenues, même sans issue préalable.
9. Vous pouvez soumettre vos projets via PR, mais ceux avec moins de 1k stars seront supprimés.
## Présentation
Une application simple de boutique Windows pour télécharger et gérer des logiciels.
Fonctionnalités :
- Gestion de logiciels
- Gestion de téléchargements
- Outils intégrés
## Fonctionnalités clés
- Interface épurée pour le téléchargement
- Gestion de la progression des téléchargements
- Téléchargements en arrière-plan
- Présentation sous forme de cartes visuelles
- Code structuré et modulaire
## Compilation et packaging
### Prérequis
- SDK .NET 8.0
- Windows 10/11
### Commandes
#### Version 32-bit
```bash
dotnet publish -c Release -r win-x86 -p:PublishSingleFile=true
```
#### Version 64-bit
```bash
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true
```
Fichiers générés :
```
bin\Release\net8.0-windows\[platform]\publish
```
### Options avancées
- `--self-contained true` : package autonome (taille plus importante)
- `-p:PublishTrimmed=true` : réduction de taille (expérimental)
## Structure du projet
```
kortapp-z/
├── MainForm.cs # Logique de la fenêtre principale
├── DownloadManager.cs # Gestion des téléchargements
├── AppCard.cs # Contrôle des cartes d'applications
├── DownloadItem.cs # Contrôle des éléments de téléchargement
├── img/ # Ressources visuelles
│ ├── ico/ # Icônes
│ └── png/ # Captures d'écran
└── resource/ # Fichiers ressources
└── aria2c.exe # Outil de téléchargement
```
## Prérequis d'exécution
- Runtime .NET 8.0 (si version dépendante du framework)
- Windows 10 ou supérieur
## Licence
MIT License
Copyright (c) 2025 zsyg
## Autres plateformes
Dépôt miroir Gitee : https://gitee.com/chr_super/kortapp-z (maintenance arrêtée)
## Maintenance
Le dépôt Gitee n'étant plus maintenu par manque d'utilisation, toute aide pour la synchronisation est bienvenue.
Contact : QQ 3872006562 ou message privé sur Bilibili (mention dans le README en remerciement).
Note : Suite à un conflit avec Daye, l'application windowscleaner ne sera jamais publiée ici.
Important : Renommez `img/png/NET.png` en `.NET.png` pour éviter des problèmes (limitations GitHub).
## Contributions
Tout utilisateur peut ajouter des logiciels légaux via PR.
## Contacts
Email :
```
3872006562@qq.com
```
QQ :
```
3872006562
```
Groupe QQ :
```
1043867176
```
Compte Bilibili :
```
Zayisynth
```

135
README/ru-RU_README.md Normal file
View File

@@ -0,0 +1,135 @@
# Kortapp-z — Магазин приложений Windows
**Открытое ПО, бесплатно, без рекламы**
Обещание: никакой рекламы, постоянные обновления
## Политика открытого кода
1. **Открытый исходный код**: можно использовать, изменять, распространять и применять в коммерческих целях с обязательным указанием автора.
2. **Открытая документация**: те же условия, что и для кода.
3. **Открытые ресурсы** (иконки, скриншоты): те же условия.
4. Все производные продукты (сайты, приложения, расширения и т. д.) должны соблюдать эту лицензию.
5. **Никакой рекламы** — ни в какой форме.
6. **Не принимаются пожертвования**.
7. **Не принимается спонсорская поддержка**.
8. **Pull Requests (PR) приветствуются**, даже без предварительного issue.
9. Можно предлагать свои проекты через PR, но те, у которых меньше **1000 звёзд**, будут удалены.
## Описание проекта
Простое приложение для Windows, позволяющее скачивать и управлять программами.
**Основные функции:**
- Управление установленными приложениями
- Менеджер загрузок
- Встроенные инструменты
## Ключевые особенности
- Минималистичный интерфейс загрузки
- Отслеживание прогресса загрузки
- Фоновые загрузки
- Красивые карточки приложений
- Чистый и структурированный код
## Сборка и упаковка
### Системные требования
- **.NET 8.0 SDK**
- **Windows 10/11**
### Команды сборки
#### 32-битная версия
```bash
dotnet publish -c Release -r win-x86 -p:PublishSingleFile=true
```
#### 64-битная версия
```bash
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true
```
Собранные файлы появятся в:
```
bin\Release\net8.0-windows\[платформа]\publish
```
### Дополнительные опции
- `--self-contained true` — автономная сборка (больший размер)
- `-p:PublishTrimmed=true` — уменьшение размера (экспериментально)
## Структура проекта
```
kortapp-z/
├── MainForm.cs # Логика главного окна
├── DownloadManager.cs # Менеджер загрузок
├── AppCard.cs # Карточка приложения
├── DownloadItem.cs # Элемент загрузки
├── img/ # Графика
│ ├── ico/ # Иконки
│ └── png/ # Скриншоты
└── resource/ # Ресурсы
└── aria2c.exe # Утилита загрузки
```
## Требования для запуска
- **.NET 8.0 Runtime** (если используется зависимая сборка)
- **Windows 10 или новее**
## Лицензия
**MIT License**
Copyright (c) 2025 zsyg
## Другие платформы
**Зеркало на Gitee**: [https://gitee.com/chr_super/kortapp-z](https://gitee.com/chr_super/kortapp-z) (поддержка прекращена)
## Поддержка
Репозиторий на Gitee больше не синхронизируется. Если кто-то может помочь с зеркалированием — пишите:
- **QQ**: 3872006562
- **Bilibili (личные сообщения)**: Zayisynth
**Важно**:
- Из-за конфликта с Daye приложение **windowscleaner** никогда не будет добавлено.
- Переименуйте `img/png/NET.png` в `.NET.png`, иначе возможны ошибки (ограничения GitHub).
## Участие
Любой может предложить легальное ПО через Pull Request.
## Контакты
📧 **Email**:
```
3872006562@qq.com
```
📱 **QQ**:
```
3872006562
```
👥 **QQ-группа**:
```
1043867176
```
🎥 **Bilibili**:
```
Zayisynth
```
---
### Как назвать файл README на русском?
Рекомендуемые варианты:
1. **ru-RU_README.md** (стандартный IETF-код)
2. **README_ru.md** (более короткий вариант)
3. **RUS_README.md** (если предпочитаете явное обозначение)
Лучше всего придерживаться формата `[язык]_README.md`, как в других переводах.

7
SECURITY.md Normal file
View File

@@ -0,0 +1,7 @@
# 安全准则
# 安全提醒
应用商店的软件我们无法保证绝对性的安全
在下载和使用、安装之前请为该软件做足充足的功课
如果出现系统无法打开,我们无法负责,只能悲哀

View File

@@ -5,21 +5,24 @@ using System.Windows.Forms;
namespace AppStore
{
public class SettingsForm : Form
public class SettingsUserControl : UserControl
{
private Button btnCleanLogs;
public SettingsForm()
public SettingsUserControl()
{
this.Text = "设置";
this.Size = new Size(400, 300);
this.StartPosition = FormStartPosition.CenterParent;
this.Dock = DockStyle.Fill;
this.BackColor = Color.White;
// 设置顶部内边距
this.Padding = new Padding(0, 30, 0, 0);
btnCleanLogs = new Button();
btnCleanLogs.Text = "清理日志";
btnCleanLogs.Size = new Size(150, 40);
btnCleanLogs.Location = new Point(120, 100);
btnCleanLogs.Location = new Point((this.Width - 150) / 2, 50); // 调整Y坐标为50靠近顶部
btnCleanLogs.Font = new Font("Microsoft YaHei", 10);
btnCleanLogs.Anchor = AnchorStyles.Top; // 添加顶部锚点
btnCleanLogs.Click += (s, e) => CleanLogs();
this.Controls.Add(btnCleanLogs);
}

77
ToolCard.cs Normal file
View File

@@ -0,0 +1,77 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace AppStore
{
public class ToolCard : UserControl
{
private PictureBox iconBox = new PictureBox();
private Label nameLabel = new Label();
public string ToolName { get; set; } = string.Empty;
public Image ToolIcon { get; set; } = SystemIcons.Shield.ToBitmap();
// 自定义点击事件初始化为空委托
public event EventHandler ToolCardClicked = delegate {};
public ToolCard()
{
// 启用双缓冲
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw, true);
InitializeComponent();
}
private void InitializeComponent()
{
this.Size = new Size(240, 220);
this.BackColor = Color.White;
this.Padding = new Padding(5);
this.BorderStyle = BorderStyle.FixedSingle;
// 工具图标
iconBox = new PictureBox();
iconBox.Size = new Size(80, 80);
iconBox.Location = new Point((Width - 80) / 2, 15);
iconBox.SizeMode = PictureBoxSizeMode.StretchImage;
this.Controls.Add(iconBox);
// 工具名称
nameLabel = new Label();
nameLabel.AutoSize = false;
nameLabel.Size = new Size(Width - 20, 30);
nameLabel.Location = new Point(10, 100);
nameLabel.Font = new Font("Microsoft YaHei", 10, FontStyle.Bold);
nameLabel.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(nameLabel);
// 打开按钮
var openButton = new Button();
openButton.Text = "打开工具";
openButton.Size = new Size(100, 30);
openButton.Location = new Point((Width - 100) / 2, 140);
openButton.BackColor = Color.FromArgb(0, 120, 215);
openButton.ForeColor = Color.White;
openButton.FlatStyle = FlatStyle.Flat;
openButton.FlatAppearance.BorderSize = 0;
openButton.Cursor = Cursors.Hand;
// 按钮点击直接触发ToolCardClicked事件
openButton.Click += (s, e) => {
ToolCardClicked?.Invoke(this, e);
};
this.Controls.Add(openButton);
// 设置按钮悬停效果
openButton.BackColor = Color.FromArgb(0, 120, 215);
openButton.FlatAppearance.MouseOverBackColor = Color.FromArgb(0, 100, 180);
openButton.FlatAppearance.MouseDownBackColor = Color.FromArgb(0, 80, 160);
}
public void UpdateDisplay()
{
nameLabel.Text = ToolName;
iconBox.Image = ToolIcon;
}
}
}

View File

@@ -1,4 +1,2 @@
rmdir bin /s /q
rmdir obj /s /q
rmdir logs /s /q
mkdir logs

49
docs/about.html Normal file
View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>关于kortapp-z</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>关于kortapp-z</h1>
<p>了解我们的项目和团队</p>
</header>
<main>
<section class="about-project">
<h2>项目简介</h2>
<p>kortapp-z是一个专为Windows系统设计的实用工具集合旨在提供一站式的系统优化和管理解决方案。</p>
<p>项目始于2025年由热爱效率工具的开发者创建。</p>
</section>
<section class="team">
<h2>开发团队</h2>
<p>我们的团队由经验丰富的开发人员组成,专注于创建高质量的系统工具。</p>
<ul>
<li>核心开发者: 1人</li>
<li>UI设计师: 1人</li>
<li>测试工程师: 1人</li>
</ul>
</section>
<section class="contact">
<h2>联系我们</h2>
<p>如有任何问题或建议欢迎通过GitHub提交issue或pull request。</p>
<a href="https://github.com/zs-yg/kortapp-z/issues" target="_blank">提交反馈</a>
</section>
</main>
<footer>
<nav>
<a href="index.html">首页</a>
<a href="features.html">功能</a>
</nav>
<p>&copy; 2025 kortapp-z 团队</p>
</footer>
<script src="script.js"></script>
</body>
</html>

49
docs/features.html Normal file
View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>kortapp-z功能详情</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>kortapp-z功能详情</h1>
<p>探索我们强大的工具集</p>
</header>
<main>
<section class="feature-list">
<h2>核心功能</h2>
<article class="feature">
<h3>应用程序管理</h3>
<p>批量安装、卸载(目前没有)和更新应用程序(目前没有),管理启动项(目前没有)。</p>
<p>优势:集中管理所有应用,节省时间,避免系统臃肿。</p>
</article>
<article class="feature">
<h3>资源监控(之后可能在内置工具里有)</h3>
<p>实时监控CPU、内存、磁盘和网络使用情况。</p>
<p>优势:直观的图表展示,及时发现资源瓶颈。</p>
</article>
<article class="feature">
<h3>文件管理(之后可能在内置工具里有)</h3>
<p>高级文件搜索、批量重命名和快速文件分类。</p>
<p>优势:提升文件管理效率,支持正则表达式搜索。</p>
</article>
</section>
</main>
<footer>
<nav>
<a href="index.html">首页</a>
<a href="about.html">关于</a>
</nav>
<p>&copy; 2025 kortapp-z 团队</p>
</footer>
<script src="script.js"></script>
</body>
</html>

42
docs/index.html Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>kortapp-z - Windows实用工具</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>欢迎使用kortapp-z</h1>
<p>您的一站式Windows实用工具</p>
</header>
<main>
<section class="features">
<h2>主要功能</h2>
<ul>
<li>内置工具</li>
<li>应用程序下载</li>
<li>更多实用功能</li>
</ul>
</section>
<section class="github">
<h2>项目GitHub地址</h2>
<p>查看源代码并参与贡献:</p>
<a href="https://github.com/zs-yg/kortapp-z" target="_blank">GitHub仓库</a>
</section>
</main>
<footer>
<nav>
<a href="about.html">关于</a>
<a href="features.html">功能</a>
</nav>
<p>&copy; 2025 zsyg</p>
</footer>
<script src="script.js"></script>
</body>
</html>

31
docs/script.js Normal file
View File

@@ -0,0 +1,31 @@
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 获取当前年份并更新页脚版权信息
const yearElement = document.querySelector('footer p');
if (yearElement) {
const currentYear = new Date().getFullYear();
yearElement.textContent = yearElement.textContent.replace('2025', currentYear);
}
// 为所有导航链接添加点击效果
const navLinks = document.querySelectorAll('nav a');
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
// 可以在这里添加页面切换动画或其他效果
console.log('导航到: ' + this.getAttribute('href'));
});
});
// 功能列表项悬停效果
const featureItems = document.querySelectorAll('.features li');
featureItems.forEach(item => {
item.addEventListener('mouseover', function() {
this.style.transform = 'translateX(5px)';
this.style.transition = 'transform 0.3s ease';
});
item.addEventListener('mouseout', function() {
this.style.transform = '';
});
});
});

71
docs/style.css Normal file
View File

@@ -0,0 +1,71 @@
/* 全局样式 */
body {
font-family: 'Microsoft YaHei', sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
color: #333;
background-color: #f5f5f5;
}
/* 页眉样式 */
header {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 2rem 0;
}
header h1 {
margin: 0;
font-size: 2.5rem;
}
header p {
margin: 0.5rem 0 0;
font-size: 1.2rem;
}
/* 主体内容样式 */
main {
max-width: 1200px;
margin: 2rem auto;
padding: 0 1rem;
}
section {
background: white;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
padding: 2rem;
margin-bottom: 2rem;
}
h2 {
color: #2c3e50;
border-bottom: 2px solid #eee;
padding-bottom: 0.5rem;
}
/* 链接样式 */
a {
color: #3498db;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* 页脚样式 */
footer {
text-align: center;
padding: 1rem 0;
background-color: #2c3e50;
color: white;
}
footer nav a {
color: white;
margin: 0 1rem;
}

115
en-US_README.md Normal file
View File

@@ -0,0 +1,115 @@
# Kortapp-z - Windows App Store -- Advocating for Open Source, Free Software, and No Ads
Setting a small flag: Never accept ads, continuously update.
## Open Source Practices
1. The project code is open source, allowing anyone to use, modify, distribute, or commercialize it, but the original author must be credited.
2. The project documentation is open source, allowing anyone to use, modify, distribute, or commercialize it, but the original author must be credited.
3. Project resources such as icons and screenshots are open source, allowing anyone to use, modify, distribute, or commercialize them, but the original author must be credited.
4. Any derivatives of the project (including but not limited to websites, apps, plugins, etc.) must adhere to the above open-source license.
5. The project does not accept any form of advertising, and ads must not be placed anywhere.
6. The project does not accept any form of donations.
7. The project does not accept any form of sponsorship.
8. The project welcomes PRs (Pull Requests) in any form. Submitting issues is not required.
9. You can submit PRs for your own projects. However, if the star count is below 1k, they will be deleted.
## Project Overview
A simple Windows app store application that provides software download and management features.
Offers software management, download management, built-in tools, and more.
## Features
- Clean software download interface
- Download progress management
- Supports background downloads
- Beautiful app card display
- Functional and structured code handling
## Build and Packaging
### System Requirements
- .NET 8.0 SDK
- Windows 10/11
### Packaging Commands
#### 32-bit Version
```bash
dotnet publish -c Release -r win-x86 -p:PublishSingleFile=true
```
#### 64-bit Version
```bash
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true
```
The packaged executable will include the specified application icon and be output to:
```
bin\Release\net8.0-windows\[platform]\publish
```
### Advanced Options
- Add `--self-contained true` to generate a standalone package (larger size).
- Add `-p:PublishTrimmed=true` to reduce package size (experimental).
## Project Structure
```
kortapp-z/
├── MainForm.cs # Main form logic
├── DownloadManager.cs # Download management
├── AppCard.cs # App card control
├── DownloadItem.cs # Download item control
├── img/ # Image resources
│ ├── ico/ # Icon files
│ └── png/ # App screenshots
└── resource/ # Resource files
└── aria2c.exe # Download tool
```
## Runtime Requirements
- .NET 8.0 runtime (if using framework-dependent deployment)
- Windows 10 or later
## License
MIT License
Copyright (c) 2025 zsyg
## Other Websites
Gitee Mirror Repository: https://gitee.com/chr_super/kortapp-z (Currently no longer maintained)
## Maintenance
Since I rarely use Gitee and find it cumbersome to operate, the Gitee mirror will no longer be synced. If anyone knows how to set up a mirror, please help. Contact me via QQ: 3872006562 or DM me on Bilibili. I will acknowledge your help in the README. Thank you!
Due to a conflict with Daye, Windowscleaner will never be listed. I will strive on my own.
Note: Due to GitHub file upload restrictions, rename `img/png/NET.png` to `.NET.png`; otherwise, the program may encounter unexpected issues.
Anyone can add their own legal software via PR.
Author's Email:
```
3872006562@qq.com
```
Author's QQ:
```
3872006562
```
QQ Group:
```
1043867176
```
Bilibili Account:
```
Zayisynth
```

BIN
img/jpg/D.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/jpg/Min.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
img/jpg/NDM.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
img/jpg/Twinkstar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
img/jpg/github.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
img/jpg/pcl2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
img/jpg/vs.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
img/png/DWMBlurGlass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

BIN
img/png/Ditto.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
img/png/Go.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
img/png/NET.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

BIN
img/png/SSM.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
img/png/SpaceSniffer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
img/png/Umi-OCR.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
img/png/brave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
img/png/codium_cnl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
img/png/java.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
img/png/nanazip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
img/png/nodejs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
img/png/openark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
img/png/ruby.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
img/png/rust.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

BIN
img/resource/png/QRcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 KiB

64
inno/innosetup_x64.iss Normal file
View File

@@ -0,0 +1,64 @@
; 脚本由 Inno Setup 脚本向导生成。
; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档!
#define MyAppName "kortapp-z"
#define MyAppVersion "1.0.8"
#define MyAppPublisher "zsyg"
#define MyAppURL "https://github.com/zs-yg/kortapp-z"
#define MyAppExeName "kortapp.exe"
#define MyAppAssocName MyAppName + ""
#define MyAppAssocExt ".exe"
#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt
[Setup]
; 注意AppId 的值唯一标识此应用程序。不要在其他应用程序的安装程序中使用相同的 AppId 值。
; (若要生成新的 GUID请在 IDE 中单击 "工具|生成 GUID"。)
AppId={{8020EC01-6133-40BB-8B8B-0EB71E49696C}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
; "ArchitecturesAllowed=x64compatible" 指定安装程序无法运行
; 除 Arm 上的 x64 和 Windows 11 之外的任何平台上。
ArchitecturesAllowed=x64compatible
; "ArchitecturesInstallIn64BitMode=x64compatible" 要求
; 安装可以在 x64 或 Arm 上的 Windows 11 上以“64 位模式”完成,
; 这意味着它应该使用本机 64 位 Program Files 目录和
; 注册表的 64 位视图。
ArchitecturesInstallIn64BitMode=x64compatible
ChangesAssociations=yes
DisableProgramGroupPage=yes
LicenseFile=C:\Users\Administrator\Downloads\LICENSE.txt
; 取消注释以下行以在非管理安装模式下运行 (仅为当前用户安装)。
;PrivilegesRequired=lowest
OutputDir=D:\C#\kortapp-z_Release\setup
OutputBaseFilename=kortapp-z_setup_x64
SolidCompression=yes
WizardStyle=modern
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "D:\C#\kortapp-z_Release\x64_inno\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "D:\C#\kortapp-z_Release\x64_inno\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; 注意:不要在任何共享系统文件上使用 "Flags: ignoreversion"
[Registry]
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

56
inno/innosetup_x86.iss Normal file
View File

@@ -0,0 +1,56 @@
; 脚本由 Inno Setup 脚本向导生成。
; 有关创建 Inno Setup 脚本文件的详细信息,请参阅帮助文档!
#define MyAppName "kortapp-z"
#define MyAppVersion "1.0.8"
#define MyAppPublisher "zsyg"
#define MyAppURL "https://github.com/zs-yg/kortapp-z"
#define MyAppExeName "kortapp.exe"
#define MyAppAssocName MyAppName + ""
#define MyAppAssocExt ".exe"
#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt
[Setup]
; 注意AppId 的值唯一标识此应用程序。不要在其他应用程序的安装程序中使用相同的 AppId 值。
; (若要生成新的 GUID请在 IDE 中单击 "工具|生成 GUID"。)
AppId={{BF1944C3-CD0C-4119-A340-49C54961D48B}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
ChangesAssociations=yes
DisableProgramGroupPage=yes
LicenseFile=C:\Users\Administrator\Downloads\LICENSE.txt
; 取消注释以下行以在非管理安装模式下运行 (仅为当前用户安装)。
;PrivilegesRequired=lowest
OutputDir=D:\C#\kortapp-z_Release\setup
OutputBaseFilename=kortapp-z_setup_x86
SolidCompression=yes
WizardStyle=modern
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "D:\C#\kortapp-z_Release\x86_inno\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "D:\C#\kortapp-z_Release\x86_inno\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; 注意:不要在任何共享系统文件上使用 "Flags: ignoreversion"
[Registry]
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"
Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

View File

@@ -9,7 +9,23 @@ int main() {
auto start = std::chrono::high_resolution_clock::now();
// 定义日志目录路径
fs::path logDir = "logs";
fs::path logDir;
#ifdef _WIN32
// Windows系统获取AppData路径
char* appData = nullptr;
size_t len = 0;
if (_dupenv_s(&appData, &len, "APPDATA") == 0 && appData != nullptr) {
logDir = fs::path(appData) / "zsyg" / "kortapp-z" / ".logs";
free(appData);
} else {
std::cerr << "无法获取APPDATA环境变量" << std::endl;
return 1;
}
#else
// 非Windows系统使用默认路径
logDir = fs::path(getenv("HOME")) / ".zsyg" / "kortapp-z" / ".logs";
#endif
size_t deletedCount = 0;
size_t errorCount = 0;

View File

@@ -1,13 +1,19 @@
using System;
using System.IO;
using System.Text;
namespace AppStore
{
public static class Logger
{
private static readonly string LogsDirectory = "logs";
private static readonly string LogsDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"zsyg", "kortapp-z", ".logs");
private static readonly object LockObject = new object();
static Logger()
{
try
{
// 确保logs目录存在
if (!Directory.Exists(LogsDirectory))
@@ -15,6 +21,13 @@ namespace AppStore
Directory.CreateDirectory(LogsDirectory);
}
}
catch (Exception ex)
{
Console.WriteLine($"无法创建日志目录: {LogsDirectory}, 错误: {ex.Message}");
throw;
}
}
public static void Log(string message)
{
lock (LockObject)
@@ -23,6 +36,7 @@ namespace AppStore
{
string fileName = $"{DateTime.Now:yyyyMMddHHmmss}.log";
string filePath = Path.Combine(LogsDirectory, fileName);
using (StreamWriter writer = new StreamWriter(filePath, true, Encoding.UTF8))
{
writer.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}");
@@ -35,6 +49,7 @@ namespace AppStore
}
}
}
public static void LogError(string message, Exception? ex = null)
{
string errorMessage = $"ERROR: {message}";

View File

@@ -0,0 +1,43 @@
# 编译器设置
CC = gcc
CFLAGS = -Wall -Wextra -Iinclude -static
LDFLAGS = -static -mwindows -Wl,--subsystem,windows \
-L"C:/msys64/ucrt64/lib" \
-L"C:/msys64/ucrt64/x86_64-w64-mingw32/lib" \
-lws2_32 -lole32 -loleaut32 -luuid \
-Wl,-Bstatic -lstdc++ -lgcc -lwinpthread
# 目录设置
SRC_DIR = src
OBJ_DIR = obj
BUILD_DIR = build
INCLUDE_DIR = include
# 源文件和目标文件
SRCS = $(wildcard $(SRC_DIR)/*.c)
OBJS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS))
EXEC = $(BUILD_DIR)/system_info.exe
# 默认目标
all: $(EXEC)
# 链接目标文件生成可执行文件
$(EXEC): $(OBJS) | $(BUILD_DIR)
$(CC) $(LDFLAGS) -o $@ $^
# 编译源文件生成目标文件
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@
# 创建必要的目录
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
# 清理生成的文件
clean:
rm -rf $(OBJ_DIR) $(BUILD_DIR)
.PHONY: all clean

View File

@@ -0,0 +1,8 @@
#ifndef ABOUT_DIALOG_H
#define ABOUT_DIALOG_H
#include <windows.h>
void show_about_dialog(HWND hParent);
#endif // ABOUT_DIALOG_H

View File

@@ -0,0 +1,10 @@
#ifndef CONFIG_H
#define CONFIG_H
#define APP_NAME "系统信息查看器"
#define APP_VERSION "1.0"
#define MAX_DISKS 26
#define MAX_ADAPTERS 10
#define UPDATE_INTERVAL 5000 // 5秒
#endif // CONFIG_H

View File

@@ -0,0 +1,15 @@
#ifndef DISK_INFO_H
#define DISK_INFO_H
#include <windows.h>
typedef struct {
char driveLetter;
DWORD64 totalBytes;
DWORD64 freeBytes;
char fileSystem[32];
} DiskInfo;
void get_disk_info(DiskInfo* disks, int* count);
#endif // DISK_INFO_H

View File

@@ -0,0 +1,15 @@
#ifndef LOGGING_H
#define LOGGING_H
#include <windows.h>
typedef enum {
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
void log_message(LogLevel level, const char* format, ...);
#endif // LOGGING_H

View File

@@ -0,0 +1,9 @@
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <windows.h>
#include "system_info.h"
void update_main_window(HWND hWnd, SystemInfo* sysInfo);
#endif // MAIN_WINDOW_H

View File

@@ -0,0 +1,23 @@
#ifndef NETWORK_INFO_H
#define NETWORK_INFO_H
#include <windows.h>
#include <iphlpapi.h>
// 确保GetAdaptersInfo函数声明
#ifndef _IPHLPAPI_
#define _IPHLPAPI_
DWORD GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen);
#endif
typedef struct {
char adapterName[MAX_ADAPTER_NAME_LENGTH + 4];
char description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
char ipAddress[16];
char macAddress[18];
ULONG speed; // in Mbps
} NetworkAdapterInfo;
void get_network_adapters(NetworkAdapterInfo* adapters, int* count);
#endif // NETWORK_INFO_H

View File

@@ -0,0 +1,26 @@
#ifndef PERFORMANCE_INFO_H
#define PERFORMANCE_INFO_H
#include <windows.h>
#include <pdh.h>
// 确保PDH函数声明
#ifndef _PDH_H_
#define _PDH_H_
PDH_STATUS PdhOpenQueryA(LPCSTR szDataSource, DWORD_PTR dwUserData, PDH_HQUERY* phQuery);
PDH_STATUS PdhAddCounterA(PDH_HQUERY hQuery, LPCSTR szFullCounterPath, DWORD_PTR dwUserData, PDH_HCOUNTER* phCounter);
PDH_STATUS PdhCollectQueryData(PDH_HQUERY hQuery);
PDH_STATUS PdhGetFormattedCounterValue(PDH_HCOUNTER hCounter, DWORD dwFormat, LPDWORD lpdwType, PPDH_FMT_COUNTERVALUE pValue);
#endif
typedef struct {
DWORD cpuUsage; // CPU使用率百分比
DWORD memoryUsage; // 内存使用率百分比
DWORD processesCount; // 进程数量
DWORD threadsCount; // 线程数量
DWORD handlesCount; // 句柄数量
} PerformanceInfo;
void get_performance_info(PerformanceInfo* perfInfo);
#endif // PERFORMANCE_INFO_H

View File

@@ -0,0 +1,11 @@
#ifndef RESOURCE_H
#define RESOURCE_H
#define IDI_MAIN_ICON 101
#define IDR_MAIN_MENU 102
#define IDM_EXIT 1001
#define IDM_ABOUT 1002
#define IDM_SHOW_INFO 1003
#endif // RESOURCE_H

View File

@@ -0,0 +1,21 @@
#ifndef SYSTEM_INFO_H
#define SYSTEM_INFO_H
#include <windows.h>
typedef struct {
char cpuName[256];
DWORD cpuCores;
DWORD cpuThreads;
MEMORYSTATUSEX memoryStatus;
SYSTEM_INFO systemInfo;
OSVERSIONINFOEX osVersion;
} SystemInfo;
// 初始化系统信息
void init_system_info(SystemInfo* sysInfo);
// 创建主窗口
int create_main_window(HINSTANCE hInstance, SystemInfo* sysInfo, UINT codePage);
#endif // SYSTEM_INFO_H

View File

@@ -0,0 +1,13 @@
#ifndef SYSTEM_TRAY_H
#define SYSTEM_TRAY_H
#include <windows.h>
#define WM_TRAYICON (WM_USER + 1)
#define ID_TRAYICON 100
void create_tray_icon(HWND hWnd, HICON hIcon);
void update_tray_icon(HWND hWnd, HICON hIcon, LPCTSTR tooltip);
void remove_tray_icon(HWND hWnd);
#endif // SYSTEM_TRAY_H

View File

@@ -0,0 +1,18 @@
#ifndef UTILS_H
#define UTILS_H
#include <windows.h>
// 安全释放内存
#define SAFE_FREE(ptr) if (ptr) { free(ptr); ptr = NULL; }
// 宽字符转多字节字符串
char* wchar_to_mb(const wchar_t* wstr);
// 多字节字符串转宽字符
wchar_t* mb_to_wchar(const char* str);
// 获取当前时间字符串
char* get_current_time_string();
#endif // UTILS_H

View File

@@ -0,0 +1,16 @@
#ifndef WINDOW_UTILS_H
#define WINDOW_UTILS_H
#include <windows.h>
#include "system_info.h"
// 窗口过程函数
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// 创建主窗口
int create_main_window(HINSTANCE hInstance, SystemInfo* sysInfo, UINT codePage);
// 注册窗口类
BOOL register_window_class(HINSTANCE hInstance);
#endif // WINDOW_UTILS_H

View File

@@ -0,0 +1,9 @@
#include "about_dialog.h"
#include <tchar.h>
void show_about_dialog(HWND hParent) {
MessageBox(hParent,
_T("系统信息查看器\n版本 1.0\n\n一个简单的Windows系统信息工具"),
_T("关于"),
MB_OK | MB_ICONINFORMATION);
}

View File

@@ -0,0 +1,40 @@
#include "disk_info.h"
#include <tchar.h>
void get_disk_info(DiskInfo* disks, int* count) {
DWORD drives = GetLogicalDrives();
*count = 0;
for (char drive = 'A'; drive <= 'Z'; drive++) {
if (drives & (1 << (drive - 'A'))) {
TCHAR rootPath[4] = {drive, ':', '\\', '\0'};
TCHAR fileSystem[32];
DWORD serialNumber, maxComponentLength, fileSystemFlags;
if (GetVolumeInformation(
rootPath,
NULL, 0,
&serialNumber,
&maxComponentLength,
&fileSystemFlags,
fileSystem, sizeof(fileSystem))) {
DiskInfo* disk = &disks[(*count)++];
disk->driveLetter = drive;
ULARGE_INTEGER freeBytes, totalBytes, totalFreeBytes;
if (GetDiskFreeSpaceEx(
rootPath,
&freeBytes,
&totalBytes,
&totalFreeBytes)) {
disk->totalBytes = totalBytes.QuadPart;
disk->freeBytes = freeBytes.QuadPart;
}
strncpy(disk->fileSystem, fileSystem, sizeof(disk->fileSystem) - 1);
disk->fileSystem[sizeof(disk->fileSystem) - 1] = '\0';
}
}
}
}

View File

@@ -0,0 +1,41 @@
#include "logging.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
static const char* level_strings[] = {
"DEBUG",
"INFO",
"WARNING",
"ERROR"
};
void log_message(LogLevel level, const char* format, ...) {
va_list args;
va_start(args, format);
// 获取当前时间
time_t now;
time(&now);
struct tm* timeinfo = localtime(&now);
char time_str[20];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo);
// 格式化日志消息
char message[1024];
vsnprintf(message, sizeof(message), format, args);
// 输出到调试控制台
char output[2048];
snprintf(output, sizeof(output), "[%s] [%s] %s\n", time_str, level_strings[level], message);
OutputDebugStringA(output);
// 输出到文件
FILE* log_file = fopen("system_info.log", "a");
if (log_file) {
fprintf(log_file, "%s", output);
fclose(log_file);
}
va_end(args);
}

View File

@@ -0,0 +1,29 @@
#include <windows.h>
#include <tchar.h>
#include <locale.h>
#include "system_info.h"
#include "window_utils.h"
#include "logging.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
// 设置控制台编码为UTF-8
SetConsoleOutputCP(65001);
setlocale(LC_ALL, "chs");
// 初始化日志系统
log_message(LOG_INFO, "应用程序启动");
// 初始化系统信息收集
SystemInfo sysInfo;
init_system_info(&sysInfo);
// 创建并显示主窗口传递UTF-8编码标识
int result = create_main_window(hInstance, &sysInfo, 65001);
log_message(LOG_INFO, "应用程序退出");
return result;
}

View File

@@ -0,0 +1,55 @@
#include "main_window.h"
#include <tchar.h>
#include <commctrl.h>
#include <wchar.h>
#include <stdio.h>
#define IDC_INFO_TEXT 1002
void update_main_window(HWND hWnd, SystemInfo* sysInfo) {
HWND hInfoText = GetDlgItem(hWnd, IDC_INFO_TEXT);
if (!hInfoText) {
// 创建信息显示控件
hInfoText = CreateWindow(
_T("EDIT"),
_T(""),
WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_READONLY,
20, 50, 800, 550,
hWnd,
(HMENU)IDC_INFO_TEXT,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
SendMessage(hInfoText, WM_SETFONT,
(WPARAM)GetStockObject(DEFAULT_GUI_FONT), TRUE);
}
// 使用宽字符处理所有文本
wchar_t infoText[2048];
wchar_t cpuNameW[256];
MultiByteToWideChar(CP_UTF8, 0, sysInfo->cpuName, -1, cpuNameW, 256);
// 格式化系统信息,确保每个部分正确换行
swprintf(infoText, 2048,
L"===== 系统信息 =====\r\n\r\n"
L"[处理器信息]\r\n"
L"型号: %s\r\n"
L"物理核心数: %d\r\n"
L"逻辑核心数: %d\r\n\r\n"
L"[内存信息]\r\n"
L"总内存: %.2f GB\r\n"
L"可用内存: %.2f GB\r\n\r\n"
L"[操作系统]\r\n"
L"版本: Windows %d.%d\r\n"
L"构建版本号: %d\r\n",
cpuNameW,
sysInfo->cpuCores,
sysInfo->cpuThreads,
(float)sysInfo->memoryStatus.ullTotalPhys / (1024 * 1024 * 1024),
(float)sysInfo->memoryStatus.ullAvailPhys / (1024 * 1024 * 1024),
sysInfo->osVersion.dwMajorVersion,
sysInfo->osVersion.dwMinorVersion,
sysInfo->osVersion.dwBuildNumber);
SetWindowTextW(hInfoText, infoText);
}

View File

@@ -0,0 +1,85 @@
#include "network_info.h"
#include "config.h"
#include <stdio.h>
// 定义函数指针类型
typedef DWORD (WINAPI *GetAdaptersInfoFunc)(_Out_ PIP_ADAPTER_INFO, _Inout_ PULONG);
// 安全的函数指针转换函数
static FARPROC safe_get_proc_address(HMODULE module, const char* name) {
FARPROC proc = GetProcAddress(module, name);
if (!proc) {
return NULL;
}
return proc;
}
// 辅助宏用于安全的函数指针转换
#define GET_PROC_ADDRESS(module, name, type) \
((type)(void*)safe_get_proc_address(module, name))
void get_network_adapters(NetworkAdapterInfo* adapters, int* count) {
HMODULE hModule = LoadLibrary("iphlpapi.dll");
if (!hModule) return;
// 使用类型安全的函数指针转换
GetAdaptersInfoFunc pGetAdaptersInfo = GET_PROC_ADDRESS(hModule, "GetAdaptersInfo", GetAdaptersInfoFunc);
if (!pGetAdaptersInfo) {
FreeLibrary(hModule);
return;
}
PIP_ADAPTER_INFO pAdapterInfo = NULL;
PIP_ADAPTER_INFO pAdapter = NULL;
DWORD dwRetVal = 0;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
*count = 0;
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
FreeLibrary(hModule);
return;
}
// 第一次调用获取缓冲区大小
if (pGetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
if (pAdapterInfo == NULL) {
FreeLibrary(hModule);
return;
}
}
if ((dwRetVal = pGetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {
pAdapter = pAdapterInfo;
while (pAdapter && *count < MAX_ADAPTERS) {
NetworkAdapterInfo* adapter = &adapters[(*count)++];
// 复制适配器名称和描述
strncpy(adapter->adapterName, pAdapter->AdapterName, MAX_ADAPTER_NAME_LENGTH);
strncpy(adapter->description, pAdapter->Description, MAX_ADAPTER_DESCRIPTION_LENGTH);
// 格式化IP地址
if (pAdapter->IpAddressList.IpAddress.String[0] != '\0') {
strncpy(adapter->ipAddress, pAdapter->IpAddressList.IpAddress.String, 15);
adapter->ipAddress[15] = '\0';
} else {
strcpy(adapter->ipAddress, "N/A");
}
// 格式化MAC地址
sprintf(adapter->macAddress, "%02X:%02X:%02X:%02X:%02X:%02X",
pAdapter->Address[0], pAdapter->Address[1],
pAdapter->Address[2], pAdapter->Address[3],
pAdapter->Address[4], pAdapter->Address[5]);
adapter->speed = pAdapter->DhcpEnabled ? 100 : 10; // 简化处理,实际项目中应使用更精确的方法
pAdapter = pAdapter->Next;
}
}
free(pAdapterInfo);
}

View File

@@ -0,0 +1,137 @@
#include "performance_info.h"
#include <pdh.h>
#include <psapi.h>
#include "performance_info.h"
#include <windows.h>
#include <psapi.h>
// 定义函数指针类型
typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)(_In_opt_ LPCSTR, _In_ DWORD_PTR, _Out_ PDH_HQUERY*);
typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)(_In_ PDH_HQUERY, _In_ LPCSTR, _In_ DWORD_PTR, _Out_ PDH_HCOUNTER*);
typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)(_In_ PDH_HQUERY);
typedef PDH_STATUS (WINAPI *PdhGetFormattedCounterValueFunc)(_In_ PDH_HCOUNTER, _In_ DWORD, _Out_opt_ LPDWORD, _Out_ PPDH_FMT_COUNTERVALUE);
// 安全的函数指针转换函数
static FARPROC safe_get_proc_address(HMODULE module, const char* name) {
FARPROC proc = GetProcAddress(module, name);
if (!proc) {
return NULL;
}
return proc;
}
// 辅助宏用于安全的函数指针转换
#define GET_PROC_ADDRESS(module, name, type) \
((type)(void*)safe_get_proc_address(module, name))
static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal;
static HMODULE hPdhModule = NULL;
static PdhOpenQueryFunc pPdhOpenQuery = NULL;
static PdhAddCounterFunc pPdhAddCounter = NULL;
static PdhCollectQueryDataFunc pPdhCollectQueryData = NULL;
static PdhGetFormattedCounterValueFunc pPdhGetFormattedCounterValue = NULL;
void init_performance_counters() {
hPdhModule = LoadLibrary("pdh.dll");
if (!hPdhModule) {
return;
}
pPdhOpenQuery = GET_PROC_ADDRESS(hPdhModule, "PdhOpenQueryA", PdhOpenQueryFunc);
pPdhAddCounter = GET_PROC_ADDRESS(hPdhModule, "PdhAddCounterA", PdhAddCounterFunc);
pPdhCollectQueryData = GET_PROC_ADDRESS(hPdhModule, "PdhCollectQueryData", PdhCollectQueryDataFunc);
pPdhGetFormattedCounterValue = GET_PROC_ADDRESS(hPdhModule, "PdhGetFormattedCounterValue", PdhGetFormattedCounterValueFunc);
if (pPdhOpenQuery && pPdhAddCounter && pPdhCollectQueryData) {
// 初始化性能计数器
if (pPdhOpenQuery(NULL, 0, &cpuQuery) != ERROR_SUCCESS) {
return;
}
// 添加CPU计数器
if (pPdhAddCounter(cpuQuery, "\\Processor(_Total)\\% Processor Time", 0, &cpuTotal) != ERROR_SUCCESS) {
return;
}
// 第一次收集数据,用于初始化
pPdhCollectQueryData(cpuQuery);
Sleep(1000); // 等待1秒获取基准数据
pPdhCollectQueryData(cpuQuery);
}
}
void get_performance_info(PerformanceInfo* perfInfo) {
static BOOL initialized = FALSE;
if (!initialized) {
init_performance_counters();
initialized = TRUE;
}
// 获取CPU使用率
if (pPdhCollectQueryData && pPdhGetFormattedCounterValue) {
// 第一次收集数据作为基准
pPdhCollectQueryData(cpuQuery);
Sleep(1000); // 等待1秒
pPdhCollectQueryData(cpuQuery); // 第二次收集数据
PDH_FMT_COUNTERVALUE counterVal;
if (pPdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal) == ERROR_SUCCESS) {
perfInfo->cpuUsage = (DWORD)counterVal.doubleValue;
} else {
perfInfo->cpuUsage = 0;
}
} else {
// 如果PDH不可用使用GetSystemTimes作为备用方案
FILETIME idleTime, kernelTime, userTime;
if (GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
ULONGLONG idle = ((ULONGLONG)idleTime.dwHighDateTime << 32) | idleTime.dwLowDateTime;
ULONGLONG kernel = ((ULONGLONG)kernelTime.dwHighDateTime << 32) | kernelTime.dwLowDateTime;
ULONGLONG user = ((ULONGLONG)userTime.dwHighDateTime << 32) | userTime.dwLowDateTime;
static ULONGLONG prevIdle = 0, prevKernel = 0, prevUser = 0;
ULONGLONG idleDiff = idle - prevIdle;
ULONGLONG kernelDiff = kernel - prevKernel;
ULONGLONG userDiff = user - prevUser;
if (prevIdle != 0 && (kernelDiff + userDiff) > 0) {
perfInfo->cpuUsage = (DWORD)(100.0 - (100.0 * idleDiff) / (kernelDiff + userDiff));
} else {
perfInfo->cpuUsage = 0;
}
prevIdle = idle;
prevKernel = kernel;
prevUser = user;
} else {
perfInfo->cpuUsage = 0;
}
}
// 获取内存使用率
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
// 使用GlobalMemoryStatusEx获取更精确的内存使用率
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
perfInfo->memoryUsage = memStatus.dwMemoryLoad;
// 获取进程和线程数量
PERFORMANCE_INFORMATION perfInfoStruct;
GetPerformanceInfo(&perfInfoStruct, sizeof(perfInfoStruct));
perfInfo->processesCount = perfInfoStruct.ProcessCount;
perfInfo->threadsCount = perfInfoStruct.ThreadCount;
perfInfo->handlesCount = perfInfoStruct.HandleCount;
}
void cleanup_performance_counters() {
if (hPdhModule) {
FreeLibrary(hPdhModule);
hPdhModule = NULL;
}
}

View File

@@ -0,0 +1,26 @@
#include "system_info.h"
#include <intrin.h>
void init_system_info(SystemInfo* sysInfo) {
// 获取CPU信息
int cpuInfo[4] = {0};
__cpuid(cpuInfo, 0x80000002);
memcpy(sysInfo->cpuName, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000003);
memcpy(sysInfo->cpuName + 16, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000004);
memcpy(sysInfo->cpuName + 32, cpuInfo, sizeof(cpuInfo));
// 获取系统信息
GetSystemInfo(&sysInfo->systemInfo);
sysInfo->cpuCores = sysInfo->systemInfo.dwNumberOfProcessors;
sysInfo->cpuThreads = sysInfo->cpuCores; // 简化处理
// 获取内存信息
sysInfo->memoryStatus.dwLength = sizeof(sysInfo->memoryStatus);
GlobalMemoryStatusEx(&sysInfo->memoryStatus);
// 获取操作系统版本
sysInfo->osVersion.dwOSVersionInfoSize = sizeof(sysInfo->osVersion);
GetVersionEx((LPOSVERSIONINFO)&sysInfo->osVersion);
}

View File

@@ -0,0 +1,45 @@
#include "system_tray.h"
#include <shellapi.h>
#include <strsafe.h>
void create_tray_icon(HWND hWnd, HICON hIcon) {
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = ID_TRAYICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = hIcon;
#if defined(UNICODE) || defined(_UNICODE)
StringCbCopyW(nid.szTip, sizeof(nid.szTip), L"系统信息查看器");
#else
StringCbCopyA(nid.szTip, sizeof(nid.szTip), "系统信息查看器");
#endif
Shell_NotifyIcon(NIM_ADD, &nid);
}
void update_tray_icon(HWND hWnd, HICON hIcon, LPCTSTR tooltip) {
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = ID_TRAYICON;
nid.uFlags = NIF_ICON | NIF_TIP;
nid.hIcon = hIcon;
#if defined(UNICODE) || defined(_UNICODE)
StringCbCopyW(nid.szTip, sizeof(nid.szTip), tooltip);
#else
StringCbCopyA(nid.szTip, sizeof(nid.szTip), tooltip);
#endif
Shell_NotifyIcon(NIM_MODIFY, &nid);
}
void remove_tray_icon(HWND hWnd) {
NOTIFYICONDATA nid = {0};
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = ID_TRAYICON;
Shell_NotifyIcon(NIM_DELETE, &nid);
}

View File

@@ -0,0 +1,38 @@
#include "utils.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
char* wchar_to_mb(const wchar_t* wstr) {
if (!wstr) return NULL;
int size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* mbstr = (char*)malloc(size);
if (mbstr) {
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, mbstr, size, NULL, NULL);
}
return mbstr;
}
wchar_t* mb_to_wchar(const char* str) {
if (!str) return NULL;
int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
wchar_t* wstr = (wchar_t*)malloc(size * sizeof(wchar_t));
if (wstr) {
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, size);
}
return wstr;
}
char* get_current_time_string() {
time_t now;
time(&now);
struct tm* timeinfo = localtime(&now);
char* time_str = (char*)malloc(20);
if (time_str) {
strftime(time_str, 20, "%Y-%m-%d %H:%M:%S", timeinfo);
}
return time_str;
}

View File

@@ -0,0 +1,102 @@
#include "window_utils.h"
#include "main_window.h"
#include <tchar.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define IDC_MAIN_BUTTON 1001
// 全局变量存储系统信息
static SystemInfo* g_sysInfo = NULL;
BOOL register_window_class(HINSTANCE hInstance) {
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = MainWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("SystemInfoWindowClass");
wcex.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
return RegisterClassEx(&wcex);
}
int create_main_window(HINSTANCE hInstance, SystemInfo* sysInfo, UINT codePage) {
// 设置控制台编码
if (codePage == 65001) {
SetConsoleOutputCP(65001);
_setmode(_fileno(stdout), _O_U16TEXT);
}
// 设置窗口标题为宽字符
LPCWSTR windowTitle = L"系统信息查看器";
g_sysInfo = sysInfo;
if (!register_window_class(hInstance)) {
return 0;
}
HWND hWnd = CreateWindowW(
L"SystemInfoWindowClass",
windowTitle,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
450, 300,
NULL, NULL, hInstance, NULL);
if (!hWnd) {
return 0;
}
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
// 初始更新窗口内容
update_main_window(hWnd, sysInfo);
// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
// 创建显示系统信息的按钮
CreateWindowW(L"BUTTON", L"刷新信息",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10, 10, 150, 30,
hWnd, (HMENU)IDC_MAIN_BUTTON,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), NULL);
break;
}
case WM_COMMAND: {
if (LOWORD(wParam) == IDC_MAIN_BUTTON) {
// 刷新系统信息
init_system_info(g_sysInfo);
update_main_window(hWnd, g_sysInfo);
}
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

22
others/C/memory/Makefile Normal file
View File

@@ -0,0 +1,22 @@
CC = gcc
CFLAGS = -Wall -Wextra -I./include
LDFLAGS = -Wl,-subsystem,windows -municode -luser32 -lgdi32 -lcomctl32 -lpsapi
SRC = src/main.c src/memory_ops.c src/ui.c src/init.c \
src/utils.c src/config.c src/benchmark.c src/log.c \
src/error.c src/version.c
OBJ = $(SRC:.c=.o)
TARGET = memory_trainer.exe
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ) $(LDFLAGS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
del /Q $(subst /,\,$(OBJ)) $(TARGET)
.PHONY: all clean

View File

@@ -0,0 +1,19 @@
#ifndef BENCHMARK_H
#define BENCHMARK_H
#include <stddef.h>
// 内存性能测试结果
typedef struct {
double allocation_time; // 分配时间(ms)
double fill_time; // 填充时间(ms)
double free_time; // 释放时间(ms)
} BenchmarkResult;
// 运行内存性能测试
BenchmarkResult run_memory_benchmark(size_t size_mb);
// 打印测试结果(支持中文)
void print_benchmark_result(const BenchmarkResult* result);
#endif // BENCHMARK_H

View File

@@ -0,0 +1,22 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stddef.h>
// 内存训练器配置
typedef struct {
size_t default_memory_size; // 默认内存大小(MB)
size_t max_memory_size; // 最大内存大小(MB)
int fill_mode; // 默认填充模式
} Config;
// 初始化配置
void init_config();
// 获取当前配置
Config* get_config();
// 保存配置到文件
void save_config();
#endif // CONFIG_H

View File

@@ -0,0 +1,9 @@
#ifndef ERROR_H
#define ERROR_H
#include "../include/memory_trainer.h"
// 获取错误描述
const wchar_t* get_error_message(ErrorCode code);
#endif // ERROR_H

View File

@@ -0,0 +1,21 @@
#ifndef LOG_H
#define LOG_H
#include <stdarg.h>
#include <stddef.h>
// 日志级别
typedef enum {
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
// 初始化日志系统
void init_logger();
// 记录日志(支持中文)
void log_message(LogLevel level, const wchar_t* format, ...);
#endif // LOG_H

View File

@@ -0,0 +1,54 @@
#ifndef MEMORY_TRAINER_H
#define MEMORY_TRAINER_H
#include <stddef.h>
#include <windows.h>
// 错误代码定义
typedef enum {
ERR_SUCCESS = 0,
ERR_ALLOCATION,
ERR_INVALID_PARAM,
ERR_SYSTEM
} ErrorCode;
// 进度回调函数类型
typedef void (*ProgressCallback)(int percent);
// 内存操作函数声明
void* allocate_memory(size_t size);
void fill_memory(void* ptr, size_t size, int mode, ProgressCallback callback);
void free_memory(void* ptr, size_t size);
// 错误处理函数
void report_error(ErrorCode code, const wchar_t* message);
// 全局窗口句柄(外部声明)
extern HWND g_hMainWnd;
// 进度回调函数
void update_progress(int percent);
// UI控件ID定义
#define IDC_RUN_TEST 1001
#define IDC_PROGRESS 1002
#define IDC_RETAIN_MEM 1003
#define IDC_FILL_ZERO 1004
#define IDC_FILL_RANDOM 1005
// 窗口过程函数声明
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// UI函数声明
void init_main_window_ui(HWND hWnd);
LRESULT handle_ui_message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// 初始化函数声明
void initialize_application(HINSTANCE hInstance);
HINSTANCE get_app_instance(void);
// 版本信息函数
const wchar_t* get_version_string(void);
const wchar_t* get_build_date(void);
#endif // MEMORY_TRAINER_H

View File

@@ -0,0 +1,15 @@
#ifndef UTILS_H
#define UTILS_H
#include <stddef.h>
// 字节转换工具MB转字节
size_t mb_to_bytes(size_t mb);
// 获取当前时间戳(毫秒)
long long get_timestamp();
// 打印调试信息(支持中文)
void debug_print(const wchar_t* message);
#endif // UTILS_H

Binary file not shown.

View File

@@ -0,0 +1,40 @@
#include "../include/benchmark.h"
#include "../include/utils.h"
#include "../include/memory_trainer.h"
#include <windows.h>
#include <stdio.h>
// 运行内存性能测试
BenchmarkResult run_memory_benchmark(size_t size_mb) {
BenchmarkResult result = {0};
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
// 测试内存分配
QueryPerformanceCounter(&start);
void* ptr = allocate_memory(size_mb);
QueryPerformanceCounter(&end);
result.allocation_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
// 测试内存填充
QueryPerformanceCounter(&start);
fill_memory(ptr, mb_to_bytes(size_mb), 0, NULL);
QueryPerformanceCounter(&end);
result.fill_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
// 测试内存释放
QueryPerformanceCounter(&start);
free_memory(ptr, size_mb);
QueryPerformanceCounter(&end);
result.free_time = (end.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
return result;
}
// 打印测试结果(支持中文)
void print_benchmark_result(const BenchmarkResult* result) {
wprintf(L"=== 内存性能测试结果 ===\n");
wprintf(L"分配时间: %.2f 毫秒\n", result->allocation_time);
wprintf(L"填充时间: %.2f 毫秒\n", result->fill_time);
wprintf(L"释放时间: %.2f 毫秒\n", result->free_time);
}

View File

@@ -0,0 +1,29 @@
#include "../include/config.h"
#include <stdio.h>
#include <stdlib.h>
// 全局配置实例
static Config app_config = {
.default_memory_size = 100, // 默认100MB
.max_memory_size = 8192, // 最大8GB
.fill_mode = 0 // 默认填充0
};
// 初始化配置
void init_config() {
// TODO: 从文件加载配置
}
// 获取当前配置
Config* get_config() {
return &app_config;
}
// 保存配置到文件
void save_config() {
FILE* fp = fopen("config.bin", "wb");
if (fp) {
fwrite(&app_config, sizeof(Config), 1, fp);
fclose(fp);
}
}

View File

@@ -0,0 +1,21 @@
#include "../include/memory_trainer.h"
#include "../include/log.h"
#include <windows.h>
// 错误代码定义
const wchar_t* error_messages[] = {
L"操作成功",
L"内存分配失败",
L"无效参数",
L"系统错误"
};
// 获取错误描述
const wchar_t* get_error_message(ErrorCode code) {
if (code < 0 || code >= sizeof(error_messages)/sizeof(error_messages[0])) {
return L"未知错误";
}
return error_messages[code];
}

View File

@@ -0,0 +1,24 @@
#include "../include/memory_trainer.h"
#include "../include/log.h"
#include <windows.h>
// 初始化应用程序
void initialize_application(HINSTANCE hInstance) {
// 初始化日志系统
init_logger();
// 注册窗口类(Unicode版本)
WNDCLASSW wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"MemoryTrainer";
RegisterClassW(&wc);
// 记录初始化完成
log_message(LOG_INFO, L"应用程序初始化完成");
}
// 获取应用程序实例句柄
HINSTANCE get_app_instance(void) {
return GetModuleHandleW(NULL);
}

59
others/C/memory/src/log.c Normal file
View File

@@ -0,0 +1,59 @@
#include "../include/log.h"
#include "../include/memory_trainer.h"
#include "../include/error.h"
#include <windows.h>
#include <stdio.h>
#include <time.h>
static FILE* log_file = NULL;
static LogLevel current_level = LOG_INFO;
// 初始化日志系统
void init_logger() {
log_file = _wfopen(L"memory_trainer.log", L"a, ccs=UTF-8");
if (!log_file) {
log_file = stdout;
}
}
// 记录日志(支持中文)
void log_message(LogLevel level, const wchar_t* format, ...) {
if (level < current_level) return;
// 获取当前时间
time_t now;
time(&now);
struct tm* tm_info = localtime(&now);
wchar_t time_buf[20];
wcsftime(time_buf, 20, L"%Y-%m-%d %H:%M:%S", tm_info);
// 格式化日志消息
va_list args;
va_start(args, format);
fwprintf(log_file, L"[%s] ", time_buf);
vfwprintf(log_file, format, args);
fwprintf(log_file, L"\n");
va_end(args);
fflush(log_file);
}
// 报告错误并显示给用户
void report_error(ErrorCode code, const wchar_t* message) {
// 获取标准错误描述
const wchar_t* error_desc = get_error_message(code);
// 构建完整错误消息
wchar_t full_msg[512];
wsprintfW(full_msg, L"%s: %s", error_desc, message);
// 记录到日志
log_message(LOG_ERROR, L"错误代码 %d: %s", code, full_msg);
// 显示给用户
if (g_hMainWnd) {
MessageBoxW(g_hMainWnd, full_msg, L"内存锻炼器 - 错误", MB_ICONERROR);
} else {
OutputDebugStringW(full_msg);
}
}

219
others/C/memory/src/main.c Normal file
View File

@@ -0,0 +1,219 @@
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
#include <stdint.h>
#include <psapi.h>
#include "../include/memory_trainer.h"
// 全局变量
HWND g_hMainWnd;
HWND hSizeEdit, hProgressBar, hRetainCheck, hRunButton;
HFONT hFont;
// 初始化现代UI
void InitModernUI(HWND hWnd) {
// 创建字体
hFont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY, DEFAULT_PITCH, L"微软雅黑");
// 内存大小输入
CreateWindowW(L"STATIC", L"内存大小 (MB):",
WS_VISIBLE | WS_CHILD | SS_CENTERIMAGE,
20, 20, 120, 30, hWnd, NULL, NULL, NULL);
hSizeEdit = CreateWindowW(L"EDIT", L"100",
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER,
150, 20, 120, 30, hWnd, NULL, NULL, NULL);
// 填充模式选择
CreateWindowW(L"STATIC", L"填充模式:",
WS_VISIBLE | WS_CHILD | SS_CENTERIMAGE,
20, 70, 120, 30, hWnd, NULL, NULL, NULL);
HWND hFillZero = CreateWindowW(L"BUTTON", L"填充0",
WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_GROUP,
150, 70, 80, 30, hWnd, (HMENU)IDC_FILL_ZERO, NULL, NULL);
CreateWindowW(L"BUTTON", L"随机填充",
WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
240, 70, 100, 30, hWnd, (HMENU)IDC_FILL_RANDOM, NULL, NULL);
SendMessage(hFillZero, BM_SETCHECK, BST_CHECKED, 0);
// 进度条
hProgressBar = CreateWindowW(PROGRESS_CLASSW, NULL,
WS_VISIBLE | WS_CHILD | PBS_SMOOTH,
20, 120, 360, 30, hWnd, NULL, NULL, NULL);
SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
// 保持内存选项
hRetainCheck = CreateWindowW(L"BUTTON", L"保持内存内容",
WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
20, 170, 150, 30, hWnd, NULL, NULL, NULL);
// 执行按钮
hRunButton = CreateWindowW(L"BUTTON", L"开始测试",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
200, 170, 180, 40, hWnd, (HMENU)IDC_RUN_TEST, NULL, NULL);
// 设置字体
SendMessage(hSizeEdit, WM_SETFONT, (WPARAM)hFont, TRUE);
SendMessage(hRetainCheck, WM_SETFONT, (WPARAM)hFont, TRUE);
SendMessage(hRunButton, WM_SETFONT, (WPARAM)hFont, TRUE);
}
// 主窗口过程
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
InitModernUI(hWnd);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_RUN_TEST) {
wchar_t sizeText[32];
GetWindowTextW(hSizeEdit, sizeText, 32);
int sizeMB = _wtoi(sizeText);
// 获取系统内存信息
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
// 验证输入
if (sizeMB <= 0) {
MessageBoxW(hWnd, L"请输入有效的内存大小(大于0)", L"错误", MB_ICONERROR);
return 0;
}
// 检查是否超过系统可用内存的75%
DWORDLONG maxRecommended = memStatus.ullAvailPhys * 3 / 4;
if ((DWORDLONG)sizeMB * 1024 * 1024 > maxRecommended) {
wchar_t warning[256];
wsprintfW(warning, L"请求的内存大小(%dMB)超过推荐值(%.1fMB)\n可能造成系统不稳定,是否继续?",
sizeMB, (float)maxRecommended/1024/1024);
if (MessageBoxW(hWnd, warning, L"警告", MB_YESNO | MB_ICONWARNING) != IDYES) {
return 0;
}
}
// 获取填充模式
int mode = 0;
if (SendMessage(GetDlgItem(hWnd, IDC_FILL_RANDOM), BM_GETCHECK, 0, 0) == BST_CHECKED) {
mode = 1;
}
// MB转字节
size_t bytes = 0;
if (sizeMB > 0 && sizeMB < 1024*1024) { // 限制最大1TB
bytes = (size_t)sizeMB * 1024 * 1024;
void* ptr = allocate_memory(bytes);
if (!ptr) {
// 错误信息已由report_error记录直接返回
return 0;
}
// 显示分配成功
SendMessage(hProgressBar, PBM_SETPOS, 10, 0);
// 进度回调函数
void progress_callback(int percent) {
PostMessage(g_hMainWnd, WM_APP, percent, 0);
}
// 填充内存
fill_memory(ptr, bytes, mode, progress_callback);
// 检查填充是否完成
if (SendMessage(hProgressBar, PBM_GETPOS, 0, 0) < 100) {
// 错误信息已由fill_memory中的report_error记录
}
// 确保完成
SendMessage(hProgressBar, PBM_SETPOS, 100, 0);
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
wchar_t msg[256];
wsprintfW(msg, L"成功填充 %d MB 内存\n实际使用: %.1f GB",
sizeMB,
(float)pmc.PrivateUsage / 1024.0f / 1024.0f / 1024.0f);
MessageBoxW(hWnd, msg, L"操作成功", MB_OK);
if (SendMessage(hRetainCheck, BM_GETCHECK, 0, 0) != BST_CHECKED) {
free_memory(ptr, sizeMB);
}
} else {
MessageBoxW(hWnd, L"请输入有效的内存大小", L"错误", MB_ICONERROR);
}
}
break;
case WM_APP:
SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)wParam, 0);
break;
case WM_DESTROY:
DeleteObject(hFont);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
// 应用程序入口
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR pCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(pCmdLine);
// 调试输出
OutputDebugStringW(L"内存锻炼器启动...\n");
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
wchar_t debugMsg[256];
wsprintfW(debugMsg, L"处理器数量: %lu\n", (unsigned long)sysInfo.dwNumberOfProcessors);
OutputDebugStringW(debugMsg);
wsprintfW(debugMsg, L"页面大小: %lu\n", (unsigned long)sysInfo.dwPageSize);
OutputDebugStringW(debugMsg);
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
wsprintfW(debugMsg, L"总物理内存: %.1f GB\n", (float)memStatus.ullTotalPhys/1024/1024/1024);
OutputDebugStringW(debugMsg);
// 注册窗口类
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = L"MemoryTrainerModern";
RegisterClassEx(&wc);
// 创建主窗口
g_hMainWnd = CreateWindowEx(0, L"MemoryTrainerModern", L"内存锻炼器",
WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 450, 300,
NULL, NULL, hInstance, NULL);
ShowWindow(g_hMainWnd, nCmdShow);
UpdateWindow(g_hMainWnd);
// 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}

View File

@@ -0,0 +1,145 @@
#include "../include/memory_trainer.h"
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
// 分配指定大小的内存
void* allocate_memory(size_t size_bytes) {
if (size_bytes == 0) {
report_error(ERR_INVALID_PARAM, L"无效的内存大小");
return NULL;
}
// 获取系统内存状态
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
GlobalMemoryStatusEx(&memStatus);
// 统一debugMsg变量声明
wchar_t debugMsg[512];
// 详细调试输出
wsprintfW(debugMsg, L"开始内存分配...\n请求大小: %zu bytes (%.2f MB)\n系统总内存: %.2f GB\n可用内存: %.2f GB\n",
size_bytes,
(double)size_bytes / (1024 * 1024),
(double)memStatus.ullTotalPhys / (1024 * 1024 * 1024),
(double)memStatus.ullAvailPhys / (1024 * 1024 * 1024));
OutputDebugStringW(debugMsg);
// 分配并锁定内存(调整为系统页面大小的整数倍)
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
size_t actual_size = ((size_bytes + sysInfo.dwPageSize - 1) / sysInfo.dwPageSize) * sysInfo.dwPageSize;
wsprintfW(debugMsg, L"实际分配大小: %zu bytes (%.2f MB), 页面大小: %lu\n",
actual_size,
(double)actual_size / (1024 * 1024),
sysInfo.dwPageSize);
OutputDebugStringW(debugMsg);
void* ptr = VirtualAlloc(NULL, actual_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ptr) {
DWORD err = GetLastError();
wsprintfW(debugMsg, L"内存分配失败,错误代码: %lu, 请求大小: %zu\n", err, actual_size);
OutputDebugStringW(debugMsg);
LPWSTR errMsg = NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, err, 0, (LPWSTR)&errMsg, 0, NULL);
wchar_t userMsg[512];
wsprintfW(userMsg, L"内存分配失败(错误 %lu): %s", err, errMsg ? errMsg : L"未知错误");
report_error(ERR_ALLOCATION, userMsg);
if (errMsg) LocalFree(errMsg);
return NULL;
}
wsprintfW(debugMsg, L"成功分配 %zu 字节内存,地址: %p\n", actual_size, ptr);
OutputDebugStringW(debugMsg);
// 检查系统内存锁定限制
SIZE_T minLock, maxLock;
GetProcessWorkingSetSize(GetCurrentProcess(), &minLock, &maxLock);
wsprintfW(debugMsg, L"进程工作集大小: 最小=%zu KB, 最大=%zu KB\n",
minLock/1024, maxLock/1024);
OutputDebugStringW(debugMsg);
// 尝试锁定内存(限制锁定大小为工作集最大值的50%)
size_t lock_size = min(actual_size, maxLock/2);
if (!VirtualLock(ptr, lock_size)) {
DWORD err = GetLastError();
wsprintfW(debugMsg, L"内存锁定失败,错误代码: %lu, 锁定大小: %zu MB\n",
err, lock_size/1024/1024);
OutputDebugStringW(debugMsg);
// 使用系统错误代码继续执行
report_error(ERR_SYSTEM, L"内存锁定部分失败,继续运行");
} else {
wsprintfW(debugMsg, L"成功锁定 %zu MB 内存\n", lock_size/1024/1024);
OutputDebugStringW(debugMsg);
}
OutputDebugStringW(L"内存锁定成功\n");
// 写入所有页确保实际分配
memset(ptr, 0, actual_size);
return ptr;
}
// 填充内存(带进度回调)
void fill_memory(void* ptr, size_t size_bytes, int mode,
ProgressCallback progress_callback) {
if (!ptr) {
report_error(ERR_INVALID_PARAM, L"空指针");
return;
}
// 验证内存范围
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(ptr, &mbi, sizeof(mbi)) == 0) {
report_error(ERR_SYSTEM, L"内存查询失败");
return;
}
const size_t block_size = 1024 * 1024; // 1MB块
size_t filled = 0;
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
if (mode == 0) { // 填充0
memset(ptr, 0, size_bytes);
if (progress_callback) progress_callback(100);
} else { // 填充随机值
srand((unsigned)time(NULL));
uint32_t* block = (uint32_t*)malloc(block_size);
while (filled < size_bytes) {
size_t remaining = size_bytes - filled;
size_t current_block = remaining > block_size ? block_size : remaining;
// 批量填充随机值
for (size_t i = 0; i < current_block/sizeof(uint32_t); i++) {
block[i] = rand();
}
memcpy((char*)ptr + filled, block, current_block);
filled += current_block;
if (progress_callback) {
int percent = (int)(filled * 100 / size_bytes);
progress_callback(percent);
}
}
free(block);
}
}
// 释放内存
void free_memory(void* ptr, size_t size_bytes) {
if (ptr) {
size_t actual_size = size_bytes + 4096;
VirtualUnlock(ptr, actual_size);
VirtualFree(ptr, 0, MEM_RELEASE);
}
}

67
others/C/memory/src/ui.c Normal file
View File

@@ -0,0 +1,67 @@
#include "../include/memory_trainer.h"
#include <windows.h>
#include <commctrl.h>
// 进度回调函数
void update_progress(int percent) {
HWND hProgress = GetDlgItem(g_hMainWnd, IDC_PROGRESS);
if (hProgress) {
SendMessage(hProgress, PBM_SETPOS, percent, 0);
}
}
// 初始化主窗口UI
void init_main_window_ui(HWND hWnd) {
g_hMainWnd = hWnd;
// 创建内存大小输入框
CreateWindowW(L"STATIC", L"内存大小(MB):",
WS_VISIBLE | WS_CHILD,
20, 20, 100, 20, hWnd, NULL, NULL, NULL);
CreateWindowW(L"EDIT", L"100",
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER,
130, 20, 80, 20, hWnd, NULL, NULL, NULL);
// 创建填充模式单选按钮
CreateWindowW(L"STATIC", L"填充模式:",
WS_VISIBLE | WS_CHILD,
20, 50, 100, 20, hWnd, NULL, NULL, NULL);
CreateWindowW(L"BUTTON", L"填充0",
WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_GROUP,
130, 50, 80, 20, hWnd, NULL, NULL, NULL);
CreateWindowW(L"BUTTON", L"填充随机",
WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
220, 50, 80, 20, hWnd, NULL, NULL, NULL);
// 创建内存保持选项(更显眼的位置)
CreateWindowW(L"BUTTON", L"✔ 保持内存",
WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
130, 80, 100, 20, hWnd, (HMENU)IDC_RETAIN_MEM, NULL, NULL);
// 创建进度条(更显眼的位置和大小)
CreateWindowW(PROGRESS_CLASSW, NULL,
WS_VISIBLE | WS_CHILD | PBS_SMOOTH,
20, 110, 360, 25, hWnd, (HMENU)IDC_PROGRESS, NULL, NULL);
SendDlgItemMessage(hWnd, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
// 创建操作按钮
CreateWindowW(L"BUTTON", L"执行内存测试",
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
20, 140, 280, 30, hWnd, (HMENU)IDC_RUN_TEST, NULL, NULL);
}
// 处理UI消息
LRESULT handle_ui_message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE:
init_main_window_ui(hWnd);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}

View File

@@ -0,0 +1,23 @@
#include "../include/utils.h"
#include <windows.h>
#include <stdio.h>
// MB转字节
size_t mb_to_bytes(size_t mb) {
return mb * 1024 * 1024;
}
// 获取当前时间戳(毫秒)
long long get_timestamp() {
SYSTEMTIME st;
GetSystemTime(&st);
return (long long)st.wMilliseconds +
st.wSecond * 1000LL +
st.wMinute * 60000LL +
st.wHour * 3600000LL;
}
// 打印调试信息(支持中文)
void debug_print(const wchar_t* message) {
wprintf(L"[DEBUG] %s\n", message);
}

View File

@@ -0,0 +1,11 @@
#include "../include/memory_trainer.h"
// 获取版本信息
const wchar_t* get_version_string(void) {
return L"内存锻炼器 v1.0.0";
}
// 获取构建日期
const wchar_t* get_build_date(void) {
return L"2025-06-01";
}

Some files were not shown because too many files have changed in this diff Show More