Compare commits

...

33 Commits

Author SHA1 Message Date
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
89 changed files with 4405 additions and 13 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

@@ -50,7 +50,7 @@ namespace AppStore
// 初始化并添加应用信息
infoLabel = new Label();
infoLabel.Text = "kortapp-z\n版本: 1.0.2\n作者: zs-yg\n一个简单、开源的应用商店\nkortapp-z是完全免费\n基于.NET8和C++的软件";
infoLabel.Text = "kortapp-z\n版本: 1.0.7\n作者: zs-yg\n一个简单、开源的应用商店\nkortapp-z是完全免费\n基于.NET8和C/C++的软件";
infoLabel.Font = new Font("Microsoft YaHei", 12);
infoLabel.AutoSize = false;
infoLabel.Width = 300;

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

@@ -267,8 +267,13 @@ namespace AppStore
var flowPanel = new FlowLayoutPanel();
flowPanel.Dock = DockStyle.Fill;
flowPanel.AutoScroll = true;
flowPanel.WrapContents = false;
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);
// 系统清理卡片
@@ -300,6 +305,185 @@ namespace AppStore
}
};
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);
}
catch (Exception ex)
{
@@ -362,11 +546,43 @@ namespace AppStore
{
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, 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;
@@ -639,6 +855,12 @@ namespace AppStore
"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(
"星愿浏览器",
"https://d1.twinkstar.com/win/Twinkstar_v10.7.1000.2505_Release.exe",
"img/jpg/Twinkstar.jpg"));
flowPanel.Controls.Add(CreateAppCard(
"Mem Reduct",

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

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/Twinkstar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 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: 580 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 KiB

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";
}

View File

@@ -0,0 +1,34 @@
# 编译器设置
CC = gcc
CFLAGS = -Wall -Wextra -O2 -Iinclude
LDFLAGS = -lavcodec -lavformat -lavutil -lswscale -lgdi32 -lcomdlg32 -mwindows
# 目录设置
OBJ_DIR = obj
BUILD_DIR = build
# 源文件和目标文件
SRC = $(wildcard src/*.c)
OBJ = $(patsubst src/%.c,$(OBJ_DIR)/%.o,$(SRC))
EXEC = $(BUILD_DIR)/video_compressor.exe
# 创建目录
$(shell mkdir -p $(OBJ_DIR))
$(shell mkdir -p $(BUILD_DIR))
# 默认目标
all: $(EXEC)
# 链接可执行文件
$(EXEC): $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
# 编译规则
$(OBJ_DIR)/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理规则
clean:
del /Q $(OBJ_DIR)\*.o $(EXEC)
.PHONY: all clean

View File

@@ -0,0 +1,65 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stdbool.h>
/**
* 加载配置文件
* @param config_file 配置文件路径
* @return true表示成功false表示失败
*/
bool config_load(const char* config_file);
/**
* 保存配置文件
* @param config_file 配置文件路径
* @return true表示成功false表示失败
*/
bool config_save(const char* config_file);
/**
* 获取字符串配置值
* @param key 配置键
* @param default_value 默认值
* @return 配置值
*/
const char* config_get_string(const char* key, const char* default_value);
/**
* 获取整数配置值
* @param key 配置键
* @param default_value 默认值
* @return 配置值
*/
int config_get_int(const char* key, int default_value);
/**
* 获取布尔配置值
* @param key 配置键
* @param default_value 默认值
* @return 配置值
*/
bool config_get_bool(const char* key, bool default_value);
/**
* 设置字符串配置值
* @param key 配置键
* @param value 配置值
*/
void config_set_string(const char* key, const char* value);
/**
* 设置整数配置值
* @param key 配置键
* @param value 配置值
*/
void config_set_int(const char* key, int value);
/**
* 设置布尔配置值
* @param key 配置键
* @param value 配置值
*/
void config_set_bool(const char* key, bool value);
#endif // CONFIG_H

View File

@@ -0,0 +1,37 @@
#ifndef ERROR_H
#define ERROR_H
typedef enum {
ERR_NONE = 0,
ERR_FILE_NOT_FOUND,
ERR_INVALID_ARGUMENT,
ERR_MEMORY_ALLOC,
ERR_FFMPEG,
ERR_UNKNOWN
} ErrorCode;
/**
* 设置当前错误代码
* @param code 错误代码
* @param message 错误信息(可选)
*/
void error_set(ErrorCode code, const char* message);
/**
* 获取当前错误代码
* @return 错误代码
*/
ErrorCode error_get_code();
/**
* 获取当前错误信息
* @return 错误信息字符串
*/
const char* error_get_message();
/**
* 清除错误状态
*/
void error_clear();
#endif // ERROR_H

View File

@@ -0,0 +1,27 @@
#ifndef FILE_UTILS_H
#define FILE_UTILS_H
#include <stdbool.h>
/**
* 检查文件是否存在
* @param path 文件路径
* @return true表示存在false表示不存在
*/
bool file_exists(const char* path);
/**
* 获取文件大小
* @param path 文件路径
* @return 文件大小(字节)-1表示错误
*/
long file_size(const char* path);
/**
* 获取文件扩展名
* @param path 文件路径
* @return 扩展名字符串(包含.)NULL表示没有扩展名
*/
const char* file_extension(const char* path);
#endif // FILE_UTILS_H

View File

@@ -0,0 +1,16 @@
#ifndef GUI_H
#define GUI_H
#include <windows.h>
// 初始化GUI界面
BOOL init_gui(HINSTANCE hInstance);
// 主窗口过程函数
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam);
// 创建压缩参数设置控件
void create_compression_controls(HWND hwnd);
#endif // GUI_H

View File

@@ -0,0 +1,38 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <stdio.h>
typedef enum {
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
/**
* 初始化日志系统
* @param log_file 日志文件路径NULL表示输出到stdout
*/
void logger_init(const char* log_file);
/**
* 设置日志级别
* @param level 日志级别
*/
void logger_set_level(LogLevel level);
/**
* 记录日志
* @param level 日志级别
* @param format 格式化字符串
* @param ... 可变参数
*/
void logger_log(LogLevel level, const char* format, ...);
/**
* 关闭日志系统
*/
void logger_close();
#endif // LOGGER_H

View File

@@ -0,0 +1,21 @@
#ifndef PROGRESS_H
#define PROGRESS_H
/**
* 初始化进度显示
* @param total 总工作量
*/
void progress_init(long total);
/**
* 更新进度
* @param current 当前进度
*/
void progress_update(long current);
/**
* 完成进度显示
*/
void progress_finish();
#endif // PROGRESS_H

View File

@@ -0,0 +1,61 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
#include <stddef.h>
/**
* 安全的字符串拷贝
* @param dest 目标缓冲区
* @param src 源字符串
* @param dest_size 目标缓冲区大小
* @return 目标字符串
*/
char* str_copy(char* dest, const char* src, size_t dest_size);
/**
* 安全的字符串连接
* @param dest 目标缓冲区
* @param src 要连接的字符串
* @param dest_size 目标缓冲区大小
* @return 目标字符串
*/
char* str_concat(char* dest, const char* src, size_t dest_size);
/**
* 去除字符串两端的空白字符
* @param str 要处理的字符串
* @return 处理后的字符串
*/
char* str_trim(char* str);
/**
* 检查字符串是否以指定前缀开头
* @param str 要检查的字符串
* @param prefix 前缀
* @return 1表示是0表示否
*/
int str_starts_with(const char* str, const char* prefix);
/**
* 检查字符串是否以指定后缀结尾
* @param str 要检查的字符串
* @param suffix 后缀
* @return 1表示是0表示否
*/
int str_ends_with(const char* str, const char* suffix);
/**
* 将字符串转换为小写
* @param str 要转换的字符串
* @return 转换后的字符串
*/
char* str_to_lower(char* str);
/**
* 将字符串转换为大写
* @param str 要转换的字符串
* @return 转换后的字符串
*/
char* str_to_upper(char* str);
#endif // STRING_UTILS_H

View File

@@ -0,0 +1,26 @@
#ifndef UTILS_H
#define UTILS_H
#include <stdbool.h>
/**
* 获取当前时间戳(毫秒)
* @return 时间戳
*/
long long get_timestamp();
/**
* 生成随机字符串
* @param buffer 输出缓冲区
* @param length 字符串长度
*/
void generate_random_string(char* buffer, int length);
/**
* 检查指针是否有效
* @param ptr 要检查的指针
* @return true表示有效false表示无效
*/
bool is_pointer_valid(const void* ptr);
#endif // UTILS_H

View File

@@ -0,0 +1,24 @@
#ifndef VIDEO_COMPRESSOR_H
#define VIDEO_COMPRESSOR_H
/**
* 压缩视频文件
* @param input_file 输入文件路径
* @param output_file 输出文件路径
* @param quality 压缩质量(1-10000)
* @return 0表示成功非0表示失败
*/
int compress_video(const char* input_file, const char* output_file, int quality);
/**
* 初始化视频压缩模块
* @return 0表示成功非0表示失败
*/
int init_video_compressor();
/**
* 清理视频压缩模块资源
*/
void cleanup_video_compressor();
#endif // VIDEO_COMPRESSOR_H

View File

@@ -0,0 +1,127 @@
#include "config.h"
#include "string_utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CONFIG_SIZE 1024
typedef struct ConfigEntry {
char* key;
char* value;
struct ConfigEntry* next;
} ConfigEntry;
static ConfigEntry* config_list = NULL;
static ConfigEntry* config_find_entry(const char* key) {
ConfigEntry* entry = config_list;
while (entry != NULL) {
if (strcmp(entry->key, key) == 0) {
return entry;
}
entry = entry->next;
}
return NULL;
}
bool config_load(const char* config_file) {
FILE* file = fopen(config_file, "r");
if (file == NULL) {
return false;
}
char line[MAX_CONFIG_SIZE];
while (fgets(line, sizeof(line), file) != NULL) {
// 去除注释和空白行
char* comment = strchr(line, '#');
if (comment != NULL) {
*comment = '\0';
}
str_trim(line);
if (strlen(line) == 0) {
continue;
}
// 解析键值对
char* separator = strchr(line, '=');
if (separator == NULL) {
continue;
}
*separator = '\0';
char* key = str_trim(line);
char* value = str_trim(separator + 1);
// 添加到配置列表
config_set_string(key, value);
}
fclose(file);
return true;
}
bool config_save(const char* config_file) {
FILE* file = fopen(config_file, "w");
if (file == NULL) {
return false;
}
ConfigEntry* entry = config_list;
while (entry != NULL) {
fprintf(file, "%s=%s\n", entry->key, entry->value);
entry = entry->next;
}
fclose(file);
return true;
}
const char* config_get_string(const char* key, const char* default_value) {
ConfigEntry* entry = config_find_entry(key);
if (entry != NULL) {
return entry->value;
}
return default_value;
}
int config_get_int(const char* key, int default_value) {
const char* str = config_get_string(key, NULL);
if (str != NULL) {
return atoi(str);
}
return default_value;
}
bool config_get_bool(const char* key, bool default_value) {
const char* str = config_get_string(key, NULL);
if (str != NULL) {
return strcmp(str, "true") == 0 || strcmp(str, "1") == 0;
}
return default_value;
}
void config_set_string(const char* key, const char* value) {
ConfigEntry* entry = config_find_entry(key);
if (entry != NULL) {
free(entry->value);
entry->value = strdup(value);
} else {
entry = malloc(sizeof(ConfigEntry));
entry->key = strdup(key);
entry->value = strdup(value);
entry->next = config_list;
config_list = entry;
}
}
void config_set_int(const char* key, int value) {
char str[32];
snprintf(str, sizeof(str), "%d", value);
config_set_string(key, str);
}
void config_set_bool(const char* key, bool value) {
config_set_string(key, value ? "true" : "false");
}

View File

@@ -0,0 +1,54 @@
#include "error.h"
#include "logger.h"
#include <string.h>
#include <stdlib.h>
static ErrorCode current_error = ERR_NONE;
static char* error_message = NULL;
void error_set(ErrorCode code, const char* message) {
current_error = code;
if (error_message != NULL) {
free(error_message);
error_message = NULL;
}
if (message != NULL) {
error_message = strdup(message);
}
// 记录错误日志
if (code != ERR_NONE) {
const char* error_name;
switch (code) {
case ERR_FILE_NOT_FOUND: error_name = "File not found"; break;
case ERR_INVALID_ARGUMENT: error_name = "Invalid argument"; break;
case ERR_MEMORY_ALLOC: error_name = "Memory allocation failed"; break;
case ERR_FFMPEG: error_name = "FFmpeg error"; break;
default: error_name = "Unknown error"; break;
}
if (message != NULL) {
logger_log(LOG_ERROR, "%s: %s", error_name, message);
} else {
logger_log(LOG_ERROR, "%s", error_name);
}
}
}
ErrorCode error_get_code() {
return current_error;
}
const char* error_get_message() {
return error_message;
}
void error_clear() {
current_error = ERR_NONE;
if (error_message != NULL) {
free(error_message);
error_message = NULL;
}
}

View File

@@ -0,0 +1,39 @@
#include "file_utils.h"
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
bool file_exists(const char* path) {
if (path == NULL) {
return false;
}
struct stat buffer;
return stat(path, &buffer) == 0;
}
long file_size(const char* path) {
if (path == NULL) {
return -1;
}
struct stat buffer;
if (stat(path, &buffer) != 0) {
return -1;
}
return (long)buffer.st_size;
}
const char* file_extension(const char* path) {
if (path == NULL) {
return NULL;
}
const char* dot = strrchr(path, '.');
if (dot == NULL || dot == path) {
return NULL;
}
return dot;
}

View File

@@ -0,0 +1,161 @@
#include "gui.h"
#include "video_compressor.h"
#include "string_utils.h"
#include <windows.h>
#include <commctrl.h>
#define ID_COMPRESS_BUTTON 101
#define ID_QUALITY_SLIDER 102
#define ID_INPUT_FILE_EDIT 103
#define ID_OUTPUT_FILE_EDIT 104
#define ID_BROWSE_INPUT_BUTTON 105
#define ID_BROWSE_OUTPUT_BUTTON 106
// 全局变量
static HWND g_hwndQualitySlider;
static HWND g_hwndInputFileEdit;
static HWND g_hwndOutputFileEdit;
static HFONT g_hFont = NULL;
// 设置中文字体
static void SetChineseFont(HWND hwnd) {
if (g_hFont == NULL) {
g_hFont = CreateFontW(
16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
GB2312_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS,
L"Microsoft YaHei"
);
}
if (g_hFont) {
SendMessageW(hwnd, WM_SETFONT, (WPARAM)g_hFont, TRUE);
}
}
BOOL init_gui(HINSTANCE hInstance) {
// 注册窗口类
WNDCLASSEXW wc = {0};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_ARROW));
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszClassName = L"VideoCompressorClass";
if (!RegisterClassExW(&wc)) {
return FALSE;
}
// 创建主窗口
HWND hwnd = CreateWindowExW(0, wc.lpszClassName, L"视频压缩工具",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
500, 300, NULL, NULL, hInstance, NULL);
if (!hwnd) {
return FALSE;
}
// 创建控件
create_compression_controls(hwnd);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
return TRUE;
}
void create_compression_controls(HWND hwnd) {
// 设置字体
SetChineseFont(hwnd);
// 创建输入文件选择控件
CreateWindowW(L"STATIC", L"输入文件:", WS_CHILD | WS_VISIBLE,
20, 20, 80, 20, hwnd, NULL, NULL, NULL);
g_hwndInputFileEdit = CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER,
110, 20, 250, 20, hwnd, (HMENU)ID_INPUT_FILE_EDIT, NULL, NULL);
CreateWindowW(L"BUTTON", L"浏览...", WS_CHILD | WS_VISIBLE,
370, 20, 60, 20, hwnd, (HMENU)ID_BROWSE_INPUT_BUTTON, NULL, NULL);
// 创建输出文件选择控件
CreateWindowW(L"STATIC", L"输出文件:", WS_CHILD | WS_VISIBLE,
20, 50, 80, 20, hwnd, NULL, NULL, NULL);
g_hwndOutputFileEdit = CreateWindowW(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER,
110, 50, 250, 20, hwnd, (HMENU)ID_OUTPUT_FILE_EDIT, NULL, NULL);
CreateWindowW(L"BUTTON", L"浏览...", WS_CHILD | WS_VISIBLE,
370, 50, 60, 20, hwnd, (HMENU)ID_BROWSE_OUTPUT_BUTTON, NULL, NULL);
// 创建质量滑块
CreateWindowW(L"STATIC", L"压缩质量(1-10000):", WS_CHILD | WS_VISIBLE,
20, 80, 150, 20, hwnd, NULL, NULL, NULL);
g_hwndQualitySlider = CreateWindowW(TRACKBAR_CLASSW, L"", WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS,
20, 100, 400, 30, hwnd, (HMENU)ID_QUALITY_SLIDER, NULL, NULL);
SendMessageW(g_hwndQualitySlider, TBM_SETRANGE, TRUE, MAKELONG(1, 10000));
SendMessageW(g_hwndQualitySlider, TBM_SETPOS, TRUE, 5000);
// 创建压缩按钮
CreateWindowW(L"BUTTON", L"开始压缩", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
180, 150, 100, 30, hwnd, (HMENU)ID_COMPRESS_BUTTON, NULL, NULL);
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_COMMAND:
if (LOWORD(wParam) == ID_COMPRESS_BUTTON) {
// 处理压缩按钮点击事件
int quality = (int)SendMessageW(g_hwndQualitySlider, TBM_GETPOS, 0, 0);
wchar_t inputFile[MAX_PATH];
GetWindowTextW(g_hwndInputFileEdit, inputFile, MAX_PATH);
wchar_t outputFile[MAX_PATH];
GetWindowTextW(g_hwndOutputFileEdit, outputFile, MAX_PATH);
// 转换为UTF-8
char inputFileUtf8[MAX_PATH * 4];
char outputFileUtf8[MAX_PATH * 4];
WideCharToMultiByte(CP_UTF8, 0, inputFile, -1, inputFileUtf8, sizeof(inputFileUtf8), NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, outputFile, -1, outputFileUtf8, sizeof(outputFileUtf8), NULL, NULL);
// 调用压缩函数
compress_video(inputFileUtf8, outputFileUtf8, quality);
return 0;
} else if (LOWORD(wParam) == ID_BROWSE_INPUT_BUTTON || LOWORD(wParam) == ID_BROWSE_OUTPUT_BUTTON) {
// 文件选择对话框
OPENFILENAMEW ofn;
wchar_t szFile[MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile)/sizeof(szFile[0]);
ofn.lpstrFilter = L"视频文件\0*.mp4;*.avi;*.mkv;*.mov\0所有文件\0*.*\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileNameW(&ofn)) {
HWND targetEdit = (LOWORD(wParam) == ID_BROWSE_INPUT_BUTTON) ?
g_hwndInputFileEdit : g_hwndOutputFileEdit;
SetWindowTextW(targetEdit, szFile);
}
return 0;
}
break;
case WM_DESTROY:
if (g_hFont) {
DeleteObject(g_hFont);
g_hFont = NULL;
}
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}

View File

@@ -0,0 +1,61 @@
#include "logger.h"
#include <time.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
static FILE* log_file = NULL;
static LogLevel current_level = LOG_INFO;
void logger_init(const char* log_file_path) {
if (log_file_path != NULL) {
log_file = fopen(log_file_path, "a");
} else {
log_file = stdout;
}
}
void logger_set_level(LogLevel level) {
current_level = level;
}
void logger_log(LogLevel level, const char* format, ...) {
if (log_file == NULL || level < current_level) {
return;
}
// 获取当前时间
time_t now;
time(&now);
char time_str[20];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&now));
// 日志级别字符串
const char* level_str;
switch (level) {
case LOG_DEBUG: level_str = "DEBUG"; break;
case LOG_INFO: level_str = "INFO"; break;
case LOG_WARNING: level_str = "WARNING"; break;
case LOG_ERROR: level_str = "ERROR"; break;
default: level_str = "UNKNOWN"; break;
}
// 写入时间戳和日志级别
fprintf(log_file, "[%s] [%s] ", time_str, level_str);
// 写入日志内容
va_list args;
va_start(args, format);
vfprintf(log_file, format, args);
va_end(args);
fprintf(log_file, "\n");
fflush(log_file);
}
void logger_close() {
if (log_file != NULL && log_file != stdout) {
fclose(log_file);
}
log_file = NULL;
}

View File

@@ -0,0 +1,26 @@
#include <windows.h>
#include "video_compressor.h"
#include "gui.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// 抑制未使用参数警告
(void)hPrevInstance;
(void)lpCmdLine;
(void)nCmdShow;
// 初始化GUI
if (!init_gui(hInstance)) {
return 1;
}
// 主消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}

View File

@@ -0,0 +1,120 @@
#include "string_utils.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
char* str_copy(char* dest, const char* src, size_t dest_size) {
if (dest == NULL || src == NULL || dest_size == 0) {
return NULL;
}
size_t i;
for (i = 0; i < dest_size - 1 && src[i] != '\0'; i++) {
dest[i] = src[i];
}
dest[i] = '\0';
return dest;
}
char* str_concat(char* dest, const char* src, size_t dest_size) {
if (dest == NULL || src == NULL || dest_size == 0) {
return NULL;
}
size_t dest_len = strlen(dest);
if (dest_len >= dest_size) {
return dest;
}
size_t i;
for (i = 0; i < dest_size - dest_len - 1 && src[i] != '\0'; i++) {
dest[dest_len + i] = src[i];
}
dest[dest_len + i] = '\0';
return dest;
}
char* str_trim(char* str) {
if (str == NULL) {
return NULL;
}
char* end;
// 去除前导空白字符
while (isspace((unsigned char)*str)) {
str++;
}
// 如果全是空白字符
if (*str == '\0') {
return str;
}
// 去除尾部空白字符
end = str + strlen(str) - 1;
while (end > str && isspace((unsigned char)*end)) {
end--;
}
// 写入终止符
*(end + 1) = '\0';
return str;
}
int str_starts_with(const char* str, const char* prefix) {
if (str == NULL || prefix == NULL) {
return 0;
}
size_t len_str = strlen(str);
size_t len_prefix = strlen(prefix);
if (len_prefix > len_str) {
return 0;
}
return strncmp(str, prefix, len_prefix) == 0;
}
int str_ends_with(const char* str, const char* suffix) {
if (str == NULL || suffix == NULL) {
return 0;
}
size_t len_str = strlen(str);
size_t len_suffix = strlen(suffix);
if (len_suffix > len_str) {
return 0;
}
return strncmp(str + len_str - len_suffix, suffix, len_suffix) == 0;
}
char* str_to_lower(char* str) {
if (str == NULL) {
return NULL;
}
for (char* p = str; *p != '\0'; p++) {
*p = tolower((unsigned char)*p);
}
return str;
}
char* str_to_upper(char* str) {
if (str == NULL) {
return NULL;
}
for (char* p = str; *p != '\0'; p++) {
*p = toupper((unsigned char)*p);
}
return str;
}

View File

@@ -0,0 +1,323 @@
#include "video_compressor.h"
#include "string_utils.h"
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <sys/stat.h> // For mkdir()
#include <errno.h> // For errno
// 将质量参数(1-10000)转换为FFmpeg的CRF值(0-51)
static int convert_quality_to_crf(int quality) {
// 更激进的映射关系,确保中等质量也能强力压缩
if (quality < 3000) return 45 - (quality * 15) / 3000; // 低质量区间(30-45)
if (quality < 7000) return 30 - ((quality-3000) * 10) / 4000; // 中等质量区间(20-30)
return 20 - ((quality-7000) * 2) / 3000; // 高质量区间(18-20)
}
int compress_video(const char* input_file, const char* output_file, int quality) {
AVFormatContext *input_ctx = NULL;
AVFormatContext *output_ctx = NULL;
AVCodecContext *encoder_ctx = NULL;
const AVCodec *encoder = NULL;
AVPacket *packet = NULL;
int ret = 0;
int video_stream_index = -1;
int crf = convert_quality_to_crf(quality);
// 打开输入文件
if (avformat_open_input(&input_ctx, input_file, NULL, NULL) < 0) {
fprintf(stderr, "无法打开输入文件\n");
ret = -1;
goto cleanup;
}
// 获取流信息
if (avformat_find_stream_info(input_ctx, NULL) < 0) {
fprintf(stderr, "无法获取流信息\n");
ret = -1;
goto cleanup;
}
// 查找视频流
for (unsigned int i = 0; i < input_ctx->nb_streams; i++) {
if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (video_stream_index == -1) {
fprintf(stderr, "未找到视频流\n");
ret = -1;
goto cleanup;
}
// 创建输出上下文
if (avformat_alloc_output_context2(&output_ctx, NULL, NULL, output_file) < 0) {
fprintf(stderr, "无法创建输出上下文\n");
ret = -1;
goto cleanup;
}
// 打开输出文件
if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&output_ctx->pb, output_file, AVIO_FLAG_WRITE) < 0) {
fprintf(stderr, "无法打开输出文件\n");
ret = -1;
goto cleanup;
}
}
// 配置编码器
encoder = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!encoder) {
fprintf(stderr, "未找到H.264编码器\n");
ret = -1;
goto cleanup;
}
encoder_ctx = avcodec_alloc_context3(encoder);
if (!encoder_ctx) {
fprintf(stderr, "无法分配编码器上下文\n");
ret = -1;
goto cleanup;
}
// 设置更激进的编码参数
int64_t input_bit_rate = input_ctx->bit_rate;
if (input_bit_rate <= 0) {
input_bit_rate = 400000; // 默认值
}
// 设置严格的编码参数确保播放兼容性
encoder_ctx->bit_rate = input_bit_rate * 0.5;
encoder_ctx->rc_max_rate = input_bit_rate * 0.7;
encoder_ctx->rc_min_rate = input_bit_rate * 0.3;
encoder_ctx->rc_buffer_size = input_bit_rate * 0.7 / 25;
encoder_ctx->level = 31; // 明确设置level 3.1确保广泛兼容
encoder_ctx->width = input_ctx->streams[video_stream_index]->codecpar->width;
encoder_ctx->height = input_ctx->streams[video_stream_index]->codecpar->height;
encoder_ctx->time_base = (AVRational){1, 25};
encoder_ctx->framerate = (AVRational){25, 1};
encoder_ctx->gop_size = 10;
encoder_ctx->max_b_frames = 1;
encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
// 设置更激进的x264参数
av_opt_set_int(encoder_ctx->priv_data, "crf", crf, 0);
av_opt_set(encoder_ctx->priv_data, "preset", "slow", 0); // 使用slow预设提高压缩率
// 设置强制兼容性参数
av_opt_set(encoder_ctx->priv_data, "profile", "main", 0);
av_opt_set(encoder_ctx->priv_data, "movflags", "+faststart", 0); // 添加流式播放支持
av_opt_set(encoder_ctx->priv_data, "tune", "zerolatency", 0);
av_opt_set(encoder_ctx->priv_data, "x264-params", "ref=1:bframes=0:subme=2:me=dia:analyse=none:trellis=0", 0);
encoder_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
encoder_ctx->thread_count = 4; // 启用4线程编码
encoder_ctx->thread_type = FF_THREAD_FRAME; // 帧级多线程
encoder_ctx->gop_size = 250; // 更大的GOP提高压缩率
encoder_ctx->max_b_frames = 0; // 禁用B帧提高解码兼容性
// 打开编码器
if (avcodec_open2(encoder_ctx, encoder, NULL) < 0) {
fprintf(stderr, "无法打开编码器\n");
ret = -1;
goto cleanup;
}
// 添加视频流到输出文件
AVStream *out_stream = avformat_new_stream(output_ctx, NULL);
if (!out_stream) {
fprintf(stderr, "无法创建输出流\n");
ret = -1;
goto cleanup;
}
// 复制编码器参数到输出流
if (avcodec_parameters_from_context(out_stream->codecpar, encoder_ctx) < 0) {
fprintf(stderr, "无法复制编码器参数\n");
ret = -1;
goto cleanup;
}
// 写入文件头
if (avformat_write_header(output_ctx, NULL) < 0) {
fprintf(stderr, "写入文件头失败\n");
ret = -1;
goto cleanup;
}
packet = av_packet_alloc();
if (!packet) {
fprintf(stderr, "无法分配AVPacket\n");
ret = -1;
goto cleanup;
}
// 初始化解码器
const AVCodec *decoder = avcodec_find_decoder(input_ctx->streams[video_stream_index]->codecpar->codec_id);
if (!decoder) {
fprintf(stderr, "未找到解码器\n");
ret = -1;
goto cleanup;
}
AVCodecContext *decoder_ctx = avcodec_alloc_context3(decoder);
if (!decoder_ctx) {
fprintf(stderr, "无法分配解码器上下文\n");
ret = -1;
goto cleanup;
}
if (avcodec_parameters_to_context(decoder_ctx, input_ctx->streams[video_stream_index]->codecpar) < 0) {
fprintf(stderr, "无法复制解码器参数\n");
ret = -1;
goto cleanup;
}
if (avcodec_open2(decoder_ctx, decoder, NULL) < 0) {
fprintf(stderr, "无法打开解码器\n");
ret = -1;
goto cleanup;
}
// 初始化帧和转换上下文
AVFrame *frame = av_frame_alloc();
AVFrame *tmp_frame = av_frame_alloc();
if (!frame || !tmp_frame) {
fprintf(stderr, "无法分配帧\n");
ret = -1;
goto cleanup;
}
// 分配输入帧缓冲区
frame->format = decoder_ctx->pix_fmt;
frame->width = decoder_ctx->width;
frame->height = decoder_ctx->height;
if (av_frame_get_buffer(frame, 32) < 0) {
fprintf(stderr, "无法分配输入帧缓冲区\n");
ret = -1;
goto cleanup;
}
// 分配输出帧缓冲区
tmp_frame->format = encoder_ctx->pix_fmt;
tmp_frame->width = encoder_ctx->width;
tmp_frame->height = encoder_ctx->height;
if (av_frame_get_buffer(tmp_frame, 32) < 0) {
fprintf(stderr, "无法分配输出帧缓冲区\n");
ret = -1;
goto cleanup;
}
struct SwsContext *sws_ctx = NULL;
sws_ctx = sws_getContext(
decoder_ctx->width, decoder_ctx->height, decoder_ctx->pix_fmt,
encoder_ctx->width, encoder_ctx->height, encoder_ctx->pix_fmt,
SWS_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
fprintf(stderr, "无法创建图像转换上下文\n");
ret = -1;
goto cleanup;
}
// 彻底解决目录权限问题
if (mkdir("build") != 0 && errno != EEXIST) {
fprintf(stderr, "错误无法创建build目录(errno=%d),请手动创建并设置写权限\n", errno);
ret = -1;
goto cleanup;
}
// 验证目录可写权限
FILE *test_file = fopen("build/test_permission.tmp", "w");
if (!test_file) {
fprintf(stderr, "致命错误无法写入build目录(errno=%d),请确保:\n1. 目录存在且有写权限\n2. 没有其他程序锁定该目录\n3. 磁盘空间充足\n", errno);
ret = -1;
goto cleanup;
}
fclose(test_file);
remove("build/test_permission.tmp");
// 解码和编码循环
while (av_read_frame(input_ctx, packet) >= 0) {
if (packet->stream_index == video_stream_index) {
// 发送包到解码器
if (avcodec_send_packet(decoder_ctx, packet) < 0) {
fprintf(stderr, "解码错误\n");
continue;
}
// 接收解码后的帧
while (avcodec_receive_frame(decoder_ctx, frame) >= 0) {
// 转换像素格式
sws_scale(sws_ctx, (const uint8_t * const*)frame->data,
frame->linesize, 0, decoder_ctx->height,
tmp_frame->data, tmp_frame->linesize);
// 设置帧参数
tmp_frame->format = encoder_ctx->pix_fmt;
tmp_frame->width = encoder_ctx->width;
tmp_frame->height = encoder_ctx->height;
tmp_frame->pts = frame->pts;
// 发送帧到编码器
if (avcodec_send_frame(encoder_ctx, tmp_frame) < 0) {
fprintf(stderr, "编码错误\n");
break;
}
// 接收编码后的包
while (avcodec_receive_packet(encoder_ctx, packet) >= 0) {
// 写入输出文件
if (av_interleaved_write_frame(output_ctx, packet) < 0) {
fprintf(stderr, "写入帧失败\n");
av_packet_unref(packet);
ret = -1;
goto cleanup;
}
av_packet_unref(packet);
}
}
}
av_packet_unref(packet);
}
// 刷新编码器
avcodec_send_frame(encoder_ctx, NULL);
while (avcodec_receive_packet(encoder_ctx, packet) >= 0) {
if (av_interleaved_write_frame(output_ctx, packet) < 0) {
fprintf(stderr, "写入帧失败\n");
av_packet_unref(packet);
ret = -1;
goto cleanup;
}
av_packet_unref(packet);
}
// 写入文件尾
av_write_trailer(output_ctx);
cleanup:
if (packet) av_packet_free(&packet);
if (frame) av_frame_free(&frame);
if (tmp_frame) av_frame_free(&tmp_frame);
if (sws_ctx) sws_freeContext(sws_ctx);
if (decoder_ctx) avcodec_free_context(&decoder_ctx);
if (input_ctx) avformat_close_input(&input_ctx);
if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_closep(&output_ctx->pb);
}
if (output_ctx) avformat_free_context(output_ctx);
if (encoder_ctx) avcodec_free_context(&encoder_ctx);
return ret;
}
int init_video_compressor() {
// 新版本FFmpeg不需要显式初始化
return 0;
}
void cleanup_video_compressor() {
// 当前无需特殊清理
}

2
renexe.bat Normal file
View File

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

Binary file not shown.

BIN
resource/memory_trainer.exe Normal file

Binary file not shown.

BIN
resource/system_info.exe Normal file

Binary file not shown.

Binary file not shown.

136
tools/QrCodeGenerator.cs Normal file
View File

@@ -0,0 +1,136 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using ZXing;
using ZXing.Common;
using ZXing.QrCode;
namespace AppStore
{
public class QrCodeGeneratorForm : Form
{
private TextBox? inputTextBox;
private PictureBox? qrCodePictureBox;
private Button? generateButton;
private Button? saveButton;
public QrCodeGeneratorForm()
{
InitializeComponent();
this.Text = "二维码生成器";
this.Size = new Size(500, 600);
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
}
private void InitializeComponent()
{
// 输入文本框
inputTextBox = new TextBox();
inputTextBox.Multiline = true;
inputTextBox.ScrollBars = ScrollBars.Vertical;
inputTextBox.Size = new Size(400, 100);
inputTextBox.Location = new Point(50, 30);
inputTextBox.PlaceholderText = "请输入要生成二维码的文本内容...";
this.Controls.Add(inputTextBox);
// 生成按钮
generateButton = new Button();
generateButton.Text = "生成二维码";
generateButton.Size = new Size(150, 40);
generateButton.Location = new Point(50, 150);
generateButton.Click += GenerateButton_Click;
this.Controls.Add(generateButton);
// 二维码显示区域
qrCodePictureBox = new PictureBox();
qrCodePictureBox.Size = new Size(300, 300);
qrCodePictureBox.Location = new Point(100, 220);
qrCodePictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
qrCodePictureBox.BorderStyle = BorderStyle.FixedSingle;
this.Controls.Add(qrCodePictureBox);
// 保存按钮
saveButton = new Button();
saveButton.Text = "保存二维码";
saveButton.Size = new Size(150, 40);
saveButton.Location = new Point(300, 150);
saveButton.Click += SaveButton_Click;
this.Controls.Add(saveButton);
}
private void GenerateButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(inputTextBox?.Text))
{
MessageBox.Show("请输入要生成二维码的文本内容", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
var writer = new BarcodeWriterPixelData
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Width = 300,
Height = 300,
Margin = 1
}
};
var pixelData = writer.Write(inputTextBox.Text);
var bitmap = new Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, pixelData.Width, pixelData.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try
{
System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
qrCodePictureBox!.Image = bitmap;
}
catch (Exception ex)
{
MessageBox.Show($"生成二维码失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SaveButton_Click(object sender, EventArgs e)
{
if (qrCodePictureBox?.Image == null)
{
MessageBox.Show("请先生成二维码", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var saveDialog = new SaveFileDialog())
{
saveDialog.Filter = "PNG 图片|*.png|JPEG 图片|*.jpg|BMP 图片|*.bmp";
saveDialog.Title = "保存二维码图片";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
try
{
qrCodePictureBox!.Image.Save(saveDialog.FileName);
MessageBox.Show("二维码保存成功", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存二维码失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
}

103
tools/image_compressor.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include <iostream>
#include <filesystem>
#include <string>
#include <windows.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb/stb_image_write.h>
namespace fs = std::filesystem;
void ShowHelp() {
std::cout << "图片压缩工具 v1.0\n";
std::cout << "用法: image_compressor [选项] 输入文件 输出文件\n";
std::cout << "选项:\n";
std::cout << " -t <type> 压缩类型: lossy(有损)/lossless(无损) (默认: lossy)\n";
std::cout << " -q <quality> 压缩质量 (1-1000) (默认: 80)\n";
std::cout << " -e 保留EXIF信息 (默认: 不保留)\n";
std::cout << " -h 显示帮助信息\n";
}
int main(int argc, char** argv) {
// 默认参数
std::string compressType = "lossy";
int quality = 80;
bool keepExif = false;
std::string inputFile;
std::string outputFile;
// 解析命令行参数
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "-h") {
ShowHelp();
return 0;
} else if (arg == "-t" && i + 1 < argc) {
compressType = argv[++i];
} else if (arg == "-q" && i + 1 < argc) {
quality = std::stoi(argv[++i]);
} else if (arg == "-e") {
keepExif = true;
} else if (inputFile.empty()) {
inputFile = arg;
} else {
outputFile = arg;
}
}
// 验证参数
if (inputFile.empty() || outputFile.empty()) {
std::cerr << "错误: 必须指定输入文件和输出文件\n";
ShowHelp();
return 1;
}
if (quality < 1 || quality > 1000) {
std::cerr << "错误: 压缩质量必须在1-1000之间\n";
return 1;
}
try {
std::cout << "正在压缩: " << inputFile << " -> " << outputFile << std::endl;
std::cout << "类型: " << compressType << std::endl;
std::cout << "质量: " << quality << std::endl;
std::cout << "保留EXIF: " << (keepExif ? "" : "") << std::endl;
// 加载图片
int width, height, channels;
unsigned char* image = stbi_load(inputFile.c_str(), &width, &height, &channels, 0);
if (!image) {
std::cerr << "错误: 无法加载图片 " << inputFile << " - " << stbi_failure_reason() << std::endl;
return 1;
}
// 压缩图片
int result = 0;
if (compressType == "lossy") {
// 有损压缩 (JPEG)
int jpeg_quality = quality / 10; // 将1-1000映射到1-100
jpeg_quality = std::max(1, std::min(jpeg_quality, 100));
result = stbi_write_jpg(outputFile.c_str(), width, height, channels, image, jpeg_quality);
} else {
// 无损压缩 (PNG)
result = stbi_write_png(outputFile.c_str(), width, height, channels, image, width * channels);
}
// 释放内存
stbi_image_free(image);
if (!result) {
std::cerr << "错误: 无法保存图片 " << outputFile << std::endl;
return 1;
}
std::cout << "压缩完成\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "发生错误: " << e.what() << std::endl;
return 1;
}
}

113
zh-TW_README.md Normal file
View File

@@ -0,0 +1,113 @@
# Kortapp-z - Windows應用商店 --主張軟體開源、免費,拒絕廣告
小立一個flag從不接受廣告不停更新
## 專案開源行為
1. 專案程式碼開源,允許任何人使用、修改、分發、商用,但必須註明原作者。
2. 專案文件開源,允許任何人使用、修改、分發、商用,但必須註明原作者。
3. 專案圖示、截圖等資源開源,允許任何人使用、修改、分發、商用,但必須註明原作者。
4. 專案的任何衍生品包括但不限於網站、APP、外掛等必須遵循以上開源協議。
5. 專案不接受任何形式的廣告,不得在任何地方投放廣告。
6. 專案不接受任何形式的捐贈。
7. 專案不接受任何形式的贊助。
8. 專案可以進行PR歡迎任何形式的PR不提交issue也可以
9. 本專案可以PR一些你自己的專案如果star數量不到1k都會被刪除
## 專案簡介
一個簡單的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\[platform]\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執行時(如果使用框架依賴發布)
- Windows 10或更高版本
## 授權許可
MIT License
Copyright (c) 2025 zsyg
## 其他網站
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
```
b站帳號
```
Zayisynth
```