Compare commits

...

15 Commits

Author SHA1 Message Date
zsyg
5651e944f9 Add files via upload 2025-06-30 15:46:54 +08:00
zsyg
1dbd9968c9 Add files via upload 2025-06-30 15:46:31 +08:00
zsyg
e387d22fee Add files via upload 2025-06-30 15:44:21 +08:00
zsyg
68bd471bd2 Add files via upload 2025-06-30 15:43:54 +08:00
zsyg
53392a2ce8 Add files via upload 2025-06-29 20:23:29 +08:00
zsyg
5ecfe2da2a Add files via upload 2025-06-29 13:04:34 +08:00
zsyg
5b9532acfe Add files via upload 2025-06-29 13:03:57 +08:00
zsyg
c87d071ee0 Update README.md 2025-06-29 09:58:30 +08:00
zsyg
d54bd4c353 Add files via upload 2025-06-29 09:47:07 +08:00
zsyg
24198b2e09 Add files via upload 2025-06-29 09:46:39 +08:00
zsyg
0a0ef24497 Add files via upload 2025-06-29 09:46:05 +08:00
zsyg
96ab4bc726 添加innosetup脚本 2025-06-29 08:01:13 +08:00
zsyg
be87aaa0e6 Update README.md 2025-06-28 18:27:22 +08:00
zsyg
e8bef7e396 Update README.md 2025-06-28 18:23:41 +08:00
zsyg
7f06c9b6b1 Update README.md 2025-06-28 18:22:59 +08:00
25 changed files with 971 additions and 4 deletions

View File

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

View File

@@ -484,6 +484,76 @@ namespace AppStore
};
flowPanel.Controls.Add(videoCompressorCard);
// 计算器工具卡片
var calculatorCard = new CalculatorToolCard();
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "Calculator.png");
if (File.Exists(iconPath))
{
calculatorCard.ToolIcon = Image.FromFile(iconPath);
}
calculatorCard.UpdateDisplay();
}
catch (Exception ex)
{
Logger.LogError("加载计算器图标失败", ex);
}
flowPanel.Controls.Add(calculatorCard);
// 图片查看工具卡片
var imageViewerCard = new KortAppZ.Tools.Viewer.ImageViewerToolCard();
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "ImageCompressor.png");
if (File.Exists(iconPath))
{
imageViewerCard.ToolIcon = Image.FromFile(iconPath);
}
imageViewerCard.UpdateDisplay();
}
catch (Exception ex)
{
Logger.LogError("加载图片查看器图标失败", ex);
}
flowPanel.Controls.Add(imageViewerCard);
// 密码生成器工具卡片
var passwordGeneratorCard = new ToolCard();
passwordGeneratorCard.ToolName = "密码生成器";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "password_generator.png");
if (File.Exists(iconPath))
{
passwordGeneratorCard.ToolIcon = Image.FromFile(iconPath);
}
else
{
passwordGeneratorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
}
catch
{
passwordGeneratorCard.ToolIcon = SystemIcons.Shield.ToBitmap();
}
passwordGeneratorCard.ToolCardClicked += (s, e) => {
try {
string toolPath = Path.Combine(Application.StartupPath, "resource", "password_generator.exe");
if (File.Exists(toolPath)) {
Process.Start(toolPath);
} else {
MessageBox.Show("密码生成器工具未找到,请确保已正确安装", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
} catch (Exception ex) {
MessageBox.Show($"启动密码生成器失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
passwordGeneratorCard.UpdateDisplay();
flowPanel.Controls.Add(passwordGeneratorCard);
}
catch (Exception ex)
{

View File

@@ -35,14 +35,15 @@
### 打包指令
#### 32位版本
```bash
dotnet publish -c Release -r win-x86 -p:PublishSingleFile=true
dotnet publish AppStore.csproj -c Release -r win-x86 --self-contained false /p:Optimize=true /p:DebugType=None
```
#### 64位版本
```bash
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true
dotnet publish AppStore.csproj -c Release -r win-x64 --self-contained false /p:Optimize=true /p:DebugType=None
```
打包后的可执行文件将包含指定的应用程序图标,输出路径为:
@@ -51,7 +52,9 @@ bin\Release\net8.0-windows\[platform]\publish
```
### 高级选项
- 添加`--self-contained true`生成独立包(体积较大
- 使用`--self-contained false`生成框架依赖包(默认
- 使用`/p:Optimize=true`启用代码优化(默认)
- 使用`/p:DebugType=None`禁用调试符号生成(默认)
- 添加`-p:PublishTrimmed=true`可减小包体积(实验性)
## 项目结构

12
TXT/Build.txt Normal file
View File

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

7
TXT/Run.txt Normal file
View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

64
inno/innosetup_x64.iss Normal file
View File

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

56
inno/innosetup_x86.iss Normal file
View File

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

20
others/C/C++/Makefile Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

34
tools/Calculator.cs Normal file
View File

@@ -0,0 +1,34 @@
using System;
namespace AppStore
{
/// <summary>
/// 提供基本数学运算功能的工具类
/// </summary>
public static class Calculator
{
/// <summary>
/// 加法运算
/// </summary>
public static double Add(double a, double b) => a + b;
/// <summary>
/// 减法运算
/// </summary>
public static double Subtract(double a, double b) => a - b;
/// <summary>
/// 乘法运算
/// </summary>
public static double Multiply(double a, double b) => a * b;
/// <summary>
/// 除法运算
/// </summary>
public static double Divide(double a, double b)
{
if (b == 0) throw new DivideByZeroException("除数不能为零");
return a / b;
}
}
}

118
tools/CalculatorForm.cs Normal file
View File

@@ -0,0 +1,118 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using AppStore;
namespace AppStore
{
public class CalculatorForm : Form
{
private TextBox display = new TextBox();
private double firstNumber = 0;
private string operation = "";
public CalculatorForm()
{
this.Text = "计算器";
this.Size = new Size(300, 400);
this.StartPosition = FormStartPosition.CenterScreen;
CreateControls();
}
private void CreateControls()
{
// 显示框
display = new TextBox();
display.ReadOnly = true;
display.TextAlign = HorizontalAlignment.Right;
display.Font = new Font("Microsoft YaHei", 14);
display.Size = new Size(260, 40);
display.Location = new Point(20, 20);
this.Controls.Add(display);
// 按钮布局
string[] buttonLabels = {
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
};
for (int i = 0; i < buttonLabels.Length; i++)
{
var btn = new Button();
btn.Text = buttonLabels[i];
btn.Size = new Size(60, 50);
btn.Location = new Point(20 + (i % 4) * 65, 70 + (i / 4) * 55);
btn.Font = new Font("Microsoft YaHei", 12);
btn.Click += ButtonClickHandler;
this.Controls.Add(btn);
}
// 清除按钮
var clearBtn = new Button();
clearBtn.Text = "C";
clearBtn.Size = new Size(260, 40);
clearBtn.Location = new Point(20, 300);
clearBtn.Font = new Font("Microsoft YaHei", 12);
clearBtn.Click += (s, e) => {
display.Text = "";
firstNumber = 0;
operation = "";
};
this.Controls.Add(clearBtn);
}
private void ButtonClickHandler(object sender, EventArgs e)
{
var button = sender as Button;
if (button == null) return;
switch (button.Text)
{
case "+":
case "-":
case "*":
case "/":
if (!string.IsNullOrEmpty(display.Text))
{
firstNumber = double.Parse(display.Text);
operation = button.Text;
display.Text = "";
}
break;
case "=":
if (!string.IsNullOrEmpty(operation) && !string.IsNullOrEmpty(display.Text))
{
double secondNumber = double.Parse(display.Text);
double result = 0;
try
{
result = operation switch
{
"+" => AppStore.Calculator.Add(firstNumber, secondNumber),
"-" => AppStore.Calculator.Subtract(firstNumber, secondNumber),
"*" => AppStore.Calculator.Multiply(firstNumber, secondNumber),
"/" => AppStore.Calculator.Divide(firstNumber, secondNumber),
_ => 0
};
display.Text = result.ToString();
}
catch (DivideByZeroException)
{
MessageBox.Show("除数不能为零", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
operation = "";
}
break;
default:
display.Text += button.Text;
break;
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace AppStore
{
public class CalculatorToolCard : ToolCard
{
public CalculatorToolCard()
{
ToolName = "计算器";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "Calculator.png");
if (File.Exists(iconPath))
{
ToolIcon = Image.FromFile(iconPath);
}
else
{
ToolIcon = SystemIcons.Application.ToBitmap();
}
}
catch
{
ToolIcon = SystemIcons.Application.ToBitmap();
}
this.ToolCardClicked += OnCalculatorCardClicked;
UpdateDisplay();
}
private void OnCalculatorCardClicked(object sender, EventArgs e)
{
var calculatorForm = new CalculatorForm();
calculatorForm.ShowDialog();
}
}
}

View File

@@ -0,0 +1,21 @@
namespace KortAppZ.Tools.Viewer
{
public interface IImageViewer
{
/// <summary>
/// 加载图片文件
/// </summary>
/// <param name="filePath">图片文件路径</param>
void LoadImage(string filePath);
/// <summary>
/// 显示图片
/// </summary>
void ShowImage();
/// <summary>
/// 关闭图片查看器
/// </summary>
void CloseViewer();
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace KortAppZ.Tools.Viewer
{
public class ImageDisplayForm : Form
{
private PictureBox? pictureBox;
private Image? currentImage;
public ImageDisplayForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.pictureBox = new PictureBox();
//
// pictureBox
//
this.pictureBox.Dock = DockStyle.Fill;
this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
this.pictureBox.BackColor = Color.Black;
//
// ImageDisplayForm
//
this.Text = "图片查看";
this.ClientSize = new Size(800, 600);
this.MaximizeBox = false;
this.MinimizeBox = true;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.ControlBox = true;
this.ShowIcon = true;
this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea;
this.Controls.Add(this.pictureBox);
this.FormClosing += new FormClosingEventHandler(ImageDisplayForm_FormClosing);
}
public void LoadImage(string filePath)
{
try
{
if (currentImage != null)
{
currentImage.Dispose();
currentImage = null;
}
currentImage = ImageFileHandler.LoadImage(filePath);
pictureBox.Image = currentImage;
this.Text = $"图片查看 - {Path.GetFileName(filePath)}";
}
catch (Exception ex)
{
MessageBox.Show($"无法加载图片: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ImageDisplayForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (currentImage != null)
{
currentImage.Dispose();
currentImage = null;
}
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Drawing;
using System.IO;
namespace KortAppZ.Tools.Viewer
{
public static class ImageFileHandler
{
private static readonly string[] SupportedExtensions =
{
".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff", ".tif"
};
public static bool IsImageFile(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return false;
string extension = Path.GetExtension(filePath).ToLower();
return Array.Exists(SupportedExtensions, ext => ext == extension);
}
public static Image LoadImage(string filePath)
{
if (!IsImageFile(filePath))
throw new ArgumentException("不支持的图片格式");
if (!File.Exists(filePath))
throw new FileNotFoundException("图片文件不存在", filePath);
try
{
return Image.FromFile(filePath);
}
catch (Exception ex)
{
throw new Exception($"无法加载图片: {ex.Message}", ex);
}
}
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using KortAppZ.Tools.Viewer;
namespace KortAppZ.Tools.Viewer
{
public class ImageViewerForm : Form
{
private Button? openButton;
public ImageViewerForm()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.openButton = new Button();
//
// openButton
//
this.openButton.Text = "打开图片";
this.openButton.Size = new Size(120, 40);
this.openButton.Font = new Font("Microsoft YaHei", 10);
this.openButton.Anchor = AnchorStyles.None;
this.openButton.Click += new EventHandler(OpenButton_Click);
// 初始位置
CenterOpenButton();
// 窗体大小变化时重新居中按钮
this.Resize += (s, e) => CenterOpenButton();
//
// ImageViewerForm
//
this.Text = "图片查看器";
this.ClientSize = new Size(400, 300);
this.StartPosition = FormStartPosition.CenterScreen;
this.MinimumSize = new Size(300, 200);
this.MaximizeBox = false;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizedBounds = Screen.FromHandle(this.Handle).WorkingArea;
this.Controls.Add(this.openButton);
}
private void CenterOpenButton()
{
if (openButton != null)
{
openButton.Location = new Point(
(this.ClientSize.Width - openButton.Width) / 2,
(this.ClientSize.Height - openButton.Height) / 2);
}
}
private void OpenButton_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff;*.tif|所有文件|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
ShowImage(filePath);
}
}
private void ShowImage(string filePath)
{
try
{
if (!ImageFileHandler.IsImageFile(filePath))
{
MessageBox.Show("不支持的图片格式", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
ImageDisplayForm displayForm = new ImageDisplayForm();
displayForm.LoadImage(filePath);
displayForm.Show();
}
catch (Exception ex)
{
MessageBox.Show($"无法加载图片: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using AppStore;
namespace KortAppZ.Tools.Viewer
{
public class ImageViewerToolCard : ToolCard
{
public ImageViewerToolCard()
{
this.ToolName = "图片查看";
try
{
string iconPath = Path.Combine(Application.StartupPath, "img", "resource", "png", "ImageCompressor.png");
if (File.Exists(iconPath))
{
this.ToolIcon = Image.FromFile(iconPath);
}
else
{
this.ToolIcon = SystemIcons.Application.ToBitmap();
}
}
catch
{
this.ToolIcon = SystemIcons.Application.ToBitmap();
}
this.ToolCardClicked += (s, e) => {
try
{
ImageViewerForm viewerForm = new ImageViewerForm();
viewerForm.Show();
}
catch (Exception ex)
{
MessageBox.Show($"打开图片查看器失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
};
this.UpdateDisplay();
}
}
}