优化windows下系统弹窗在高分屏下的显示,修复多处bug,去掉showsystemselectlist接口,调整runSharp接口,支持传参

This commit is contained in:
fofolee 2025-01-13 18:04:29 +08:00
parent 0a8c24374a
commit 877d13958a
6 changed files with 954 additions and 634 deletions

745
plugin/lib/csharp/dialog.cs Normal file
View File

@ -0,0 +1,745 @@
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Drawing2D;
public class DialogGenerator
{
[DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
private const int DEFAULT_WIDTH = 900;
private const int DEFAULT_HEIGHT = 350;
private const int PADDING = 30;
private const int BUTTON_HEIGHT = 50;
private const int BUTTON_WIDTH = 140;
private const int INPUT_HEIGHT = 40;
private const int SPACING = 20;
private const int EM_SETRECT = 0xB3;
private static void InitializeDPIAwareness()
{
if (Environment.OSVersion.Version.Major >= 6)
{
SetProcessDPIAware();
}
}
public static DialogResult Show(string[] args)
{
string type = GetArgumentValue(args, "-type");
string title = GetArgumentValue(args, "-title");
string content = GetArgumentValue(args, "-content");
string iconPath = GetArgumentValue(args, "-iconpath");
if (string.IsNullOrEmpty(type) || string.IsNullOrEmpty(title))
{
MessageBox.Show("必须指定 -type 和 -title 参数");
return DialogResult.None;
}
Form dialog = CreateBaseDialog(title);
// 设置图标
if (!string.IsNullOrEmpty(iconPath) && File.Exists(iconPath))
{
try
{
using (Bitmap bmp = new Bitmap(iconPath))
{
dialog.Icon = Icon.FromHandle(bmp.GetHicon());
}
}
catch (Exception ex)
{
MessageBox.Show("加载图标失败: " + ex.Message);
}
}
switch (type.ToLower())
{
case "message":
CreateMessageDialog(dialog, content);
break;
case "input":
CreateInputDialog(dialog, content);
break;
case "confirm":
CreateConfirmDialog(dialog, content);
break;
case "buttons":
CreateButtonsDialog(dialog, content);
break;
case "textarea":
CreateTextAreaDialog(dialog, content);
break;
default:
MessageBox.Show("不支持的对话框类型");
return DialogResult.None;
}
return dialog.ShowDialog();
}
private static Form CreateBaseDialog(string title)
{
Form dialog = new Form();
dialog.Text = title;
dialog.Width = DEFAULT_WIDTH;
dialog.Height = DEFAULT_HEIGHT;
dialog.StartPosition = FormStartPosition.CenterScreen;
// 使用 Microsoft YaHei UI 字体
dialog.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular, GraphicsUnit.Point);
// 设置DPI感知
dialog.AutoScaleMode = AutoScaleMode.Dpi;
// 设置文本渲染质量
dialog.Paint += delegate(object sender, PaintEventArgs e) {
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
};
return dialog;
}
private static void CreateMessageDialog(Form dialog, string content)
{
const int MAX_CONTENT_HEIGHT = 500;
const int MIN_CONTENT_HEIGHT = 200;
int iconSize = 96;
// 先计算所需的内容高度
int requiredHeight = Math.Max(
TextRenderer.MeasureText(content,
new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
new Size(dialog.ClientSize.Width - PADDING * 3 - iconSize, int.MaxValue),
TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl
).Height + 20,
MIN_CONTENT_HEIGHT
);
int contentHeight = Math.Min(requiredHeight, MAX_CONTENT_HEIGHT);
dialog.Height = contentHeight + PADDING * 3 + BUTTON_HEIGHT;
// 创建内容面板
Panel contentPanel = new Panel
{
AutoScroll = false,
Width = dialog.ClientSize.Width - PADDING * 2,
Height = dialog.ClientSize.Height - PADDING * 3 - BUTTON_HEIGHT,
Location = new Point(PADDING, PADDING),
BackColor = SystemColors.Control
};
dialog.Controls.Add(contentPanel);
// 添加图标
PictureBox iconBox = new PictureBox
{
Width = iconSize,
Height = iconSize,
Location = new Point(0, 0),
SizeMode = PictureBoxSizeMode.Zoom,
BackColor = Color.Transparent
};
try
{
Icon sysIcon = SystemIcons.Information;
Bitmap bmp = new Bitmap(iconSize, iconSize);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawIcon(sysIcon, new Rectangle(0, 0, iconSize, iconSize));
}
iconBox.Image = bmp;
}
catch
{
iconBox.Visible = false;
}
contentPanel.Controls.Add(iconBox);
// 使用普通TextBox替代RichTextBox
TextBox messageBox = new TextBox
{
Text = content,
ReadOnly = true,
Multiline = true,
BorderStyle = BorderStyle.None,
BackColor = SystemColors.Control,
Location = new Point(iconSize + PADDING, 0),
Width = contentPanel.ClientSize.Width - iconSize - PADDING,
Height = contentPanel.Height,
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
WordWrap = true,
TabStop = false,
Cursor = Cursors.IBeam,
ScrollBars = requiredHeight > MAX_CONTENT_HEIGHT ? ScrollBars.Vertical : ScrollBars.None
};
// 隐藏光标但允许选择
messageBox.GotFocus += delegate(object sender, EventArgs e) {
if (messageBox.SelectionLength == 0)
{
NativeMethods.HideCaret(messageBox.Handle);
}
};
contentPanel.Controls.Add(messageBox);
// 添加确定按钮
Button okButton = CreateStyledButton("确定", DialogResult.OK);
okButton.Location = new Point(
dialog.ClientSize.Width - BUTTON_WIDTH - PADDING,
dialog.ClientSize.Height - PADDING - BUTTON_HEIGHT
);
dialog.Controls.Add(okButton);
// 确保按钮始终在最上层
okButton.BringToFront();
}
private static void CreateInputDialog(Form dialog, string content)
{
const int MAX_CONTENT_HEIGHT = 500;
const int MIN_CONTENT_HEIGHT = 200;
string[] prompts = content.Split(new[] { "|||||" }, StringSplitOptions.None);
var textBoxes = new System.Collections.Generic.List<TextBox>();
// 创建一个临时窗体和面板来准确计算高度
using (Form tempForm = new Form())
{
tempForm.Width = dialog.Width;
Panel tempPanel = new Panel
{
Width = dialog.ClientSize.Width - PADDING * 2,
AutoSize = true
};
tempForm.Controls.Add(tempPanel);
// 添加临时控件来计算实际高度
int currentY = (int)(PADDING * 1.5); // 起始位置
foreach (string prompt in prompts)
{
Label label = new Label
{
Text = prompt,
AutoSize = true,
Location = new Point(PADDING, currentY),
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular)
};
tempPanel.Controls.Add(label);
TextBox textBox = new TextBox
{
Width = tempPanel.Width - PADDING * 2,
Height = INPUT_HEIGHT,
Location = new Point(PADDING, currentY + label.Height + 5),
BorderStyle = BorderStyle.FixedSingle
};
tempPanel.Controls.Add(textBox);
currentY += label.Height + INPUT_HEIGHT + SPACING;
}
// 获取实际需要的高度
int totalContentHeight = currentY + PADDING; // 添加底部边距
int requiredHeight = Math.Max(totalContentHeight, MIN_CONTENT_HEIGHT);
int contentHeight = Math.Min(requiredHeight, MAX_CONTENT_HEIGHT);
// 设置对话框高度,保持原有的总体布局
dialog.Height = contentHeight + PADDING * 3 + BUTTON_HEIGHT;
// 创建实际的内容面板
Panel contentPanel = new Panel
{
AutoScroll = false,
Width = dialog.ClientSize.Width - PADDING * 2,
Height = dialog.ClientSize.Height - PADDING * 3 - BUTTON_HEIGHT,
Location = new Point(PADDING, PADDING),
BackColor = SystemColors.Control
};
// 只有当实际内容超过最大高度时才启用滚动
if (requiredHeight > MAX_CONTENT_HEIGHT)
{
contentPanel.AutoScroll = true;
contentPanel.AutoScrollMinSize = new Size(0, requiredHeight);
}
dialog.Controls.Add(contentPanel);
// 添加实际的输入控件
currentY = (int)(PADDING * 0.5);
bool needScroll = requiredHeight > MAX_CONTENT_HEIGHT;
int scrollWidth = needScroll ? SystemInformation.VerticalScrollBarWidth + 10 : 0;
foreach (string prompt in prompts)
{
Label label = new Label
{
Text = prompt,
AutoSize = true,
Location = new Point(0, currentY),
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular)
};
contentPanel.Controls.Add(label);
TextBox textBox = new TextBox
{
Width = contentPanel.ClientSize.Width - scrollWidth,
Height = INPUT_HEIGHT,
Location = new Point(0, currentY + label.Height + 5),
BorderStyle = BorderStyle.FixedSingle,
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular)
};
contentPanel.Controls.Add(textBox);
textBoxes.Add(textBox);
currentY += label.Height + INPUT_HEIGHT + SPACING;
}
}
// 添加确定按钮
Button okButton = CreateStyledButton("确定", DialogResult.OK);
okButton.Location = new Point(
dialog.ClientSize.Width - BUTTON_WIDTH - PADDING,
dialog.ClientSize.Height - PADDING - BUTTON_HEIGHT
);
// 处理确定按钮点击事件
okButton.Click += (sender, e) => {
bool hasInput = false;
foreach (var textBox in textBoxes)
{
if (!string.IsNullOrEmpty(textBox.Text))
{
hasInput = true;
break;
}
}
if (hasInput)
{
Console.Write("[");
for (int i = 0; i < textBoxes.Count; i++)
{
string value = textBoxes[i].Text ?? "";
Console.Write("\"" + value.Replace("\"", "\\\"") + "\"");
if (i < textBoxes.Count - 1)
{
Console.Write(",");
}
}
Console.Write("]");
}
else
{
Console.Write("[]");
}
};
dialog.Controls.Add(okButton);
okButton.BringToFront();
}
private static void CreateConfirmDialog(Form dialog, string content)
{
const int MAX_CONTENT_HEIGHT = 500;
const int MIN_CONTENT_HEIGHT = 200;
int iconSize = 96;
// 先计算所需的内容高度
int requiredHeight = Math.Max(
TextRenderer.MeasureText(content,
new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
new Size(dialog.ClientSize.Width - PADDING * 3 - iconSize, int.MaxValue),
TextFormatFlags.WordBreak | TextFormatFlags.TextBoxControl
).Height + 20,
MIN_CONTENT_HEIGHT
);
int contentHeight = Math.Min(requiredHeight, MAX_CONTENT_HEIGHT);
dialog.Height = contentHeight + PADDING * 3 + BUTTON_HEIGHT;
// 创建内容面板
Panel contentPanel = new Panel
{
AutoScroll = false,
Width = dialog.ClientSize.Width - PADDING * 2,
Height = dialog.ClientSize.Height - PADDING * 3 - BUTTON_HEIGHT,
Location = new Point(PADDING, PADDING),
BackColor = SystemColors.Control
};
dialog.Controls.Add(contentPanel);
// 添加图标
PictureBox iconBox = new PictureBox
{
Width = iconSize,
Height = iconSize,
Location = new Point(0, 0),
SizeMode = PictureBoxSizeMode.Zoom,
BackColor = Color.Transparent
};
try
{
Icon sysIcon = SystemIcons.Warning; // 改为警告图标
Bitmap bmp = new Bitmap(iconSize, iconSize);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawIcon(sysIcon, new Rectangle(0, 0, iconSize, iconSize));
}
iconBox.Image = bmp;
}
catch
{
iconBox.Visible = false;
}
contentPanel.Controls.Add(iconBox);
// 使用TextBox显示内容
TextBox messageBox = new TextBox
{
Text = content,
ReadOnly = true,
Multiline = true,
BorderStyle = BorderStyle.None,
BackColor = SystemColors.Control,
Location = new Point(iconSize + PADDING, 0),
Width = contentPanel.ClientSize.Width - iconSize - PADDING,
Height = contentPanel.Height,
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
WordWrap = true,
TabStop = false,
Cursor = Cursors.IBeam,
ScrollBars = requiredHeight > MAX_CONTENT_HEIGHT ? ScrollBars.Vertical : ScrollBars.None
};
// 隐藏光标但允许选择
messageBox.GotFocus += delegate(object sender, EventArgs e) {
if (messageBox.SelectionLength == 0)
{
NativeMethods.HideCaret(messageBox.Handle);
}
};
contentPanel.Controls.Add(messageBox);
// 添加确定和取消按钮
Button okButton = CreateStyledButton("确定", DialogResult.OK);
Button cancelButton = CreateStyledButton("取消", DialogResult.Cancel);
// 修改取消按钮样式为灰色
cancelButton.BackColor = Color.FromArgb(153, 153, 153);
cancelButton.MouseEnter += delegate(object sender, EventArgs e) {
cancelButton.BackColor = Color.FromArgb(133, 133, 133);
};
cancelButton.MouseLeave += delegate(object sender, EventArgs e) {
cancelButton.BackColor = Color.FromArgb(153, 153, 153);
};
// 调整按钮位置,靠右对齐,确认在最右边
okButton.Location = new Point(
dialog.ClientSize.Width - BUTTON_WIDTH - PADDING,
dialog.ClientSize.Height - PADDING - BUTTON_HEIGHT
);
cancelButton.Location = new Point(
dialog.ClientSize.Width - BUTTON_WIDTH * 2 - PADDING * 2,
dialog.ClientSize.Height - PADDING - BUTTON_HEIGHT
);
// 处理按钮点击事件
okButton.Click += (sender, e) => {
Console.Write("true");
};
cancelButton.Click += (sender, e) => {
Console.Write("false");
};
// 处理窗口关闭事件
dialog.FormClosing += delegate(object sender, FormClosingEventArgs e) {
if (dialog.DialogResult == DialogResult.None)
{
Console.Write("{}");
}
};
dialog.Controls.Add(okButton);
dialog.Controls.Add(cancelButton);
// 确保按钮始终在最上层
okButton.BringToFront();
cancelButton.BringToFront();
}
private static void CreateButtonsDialog(Form dialog, string content)
{
const int MAX_CONTENT_HEIGHT = 500;
const int MIN_CONTENT_HEIGHT = 200;
string[] buttonTexts = content.Split(new[] { "|||||" }, StringSplitOptions.None);
// 计算所需的内容高度
int totalHeight = buttonTexts.Length * (BUTTON_HEIGHT + SPACING) - SPACING; // 减去最后一个按钮后的间距
int requiredHeight = Math.Max(totalHeight + PADDING * 2, MIN_CONTENT_HEIGHT); // 添加上下内边距
int contentHeight = Math.Min(requiredHeight, MAX_CONTENT_HEIGHT);
// 设置对话框高度,根据按钮数量添加底部空间
int bottomPadding = buttonTexts.Length > 1 ? Math.Min(buttonTexts.Length * 10, 50) : 0; // 根据按钮数量增加底部空间但不超过PADDING
dialog.ClientSize = new Size(dialog.ClientSize.Width, contentHeight + bottomPadding);
// 创建内容面板
Panel contentPanel = new Panel
{
AutoScroll = false,
Width = dialog.ClientSize.Width - PADDING * 2,
Height = dialog.ClientSize.Height - PADDING * 2,
Location = new Point(PADDING, PADDING),
BackColor = SystemColors.Control
};
// 只有当实际内容超过最大高度时才启用滚动
if (requiredHeight > MAX_CONTENT_HEIGHT)
{
contentPanel.AutoScroll = true;
contentPanel.AutoScrollMinSize = new Size(0, totalHeight);
}
dialog.Controls.Add(contentPanel);
// 添加按钮
int currentY = PADDING; // 从内边距开始
bool needScroll = requiredHeight > MAX_CONTENT_HEIGHT;
int scrollWidth = needScroll ? SystemInformation.VerticalScrollBarWidth + 10 : 0;
for (int i = 0; i < buttonTexts.Length; i++)
{
Button button = new Button
{
Text = buttonTexts[i],
Width = contentPanel.ClientSize.Width - scrollWidth,
Height = BUTTON_HEIGHT,
Location = new Point(0, currentY),
Tag = i,
FlatStyle = FlatStyle.Flat,
BackColor = Color.FromArgb(0, 122, 204), // 使用蓝色背景
ForeColor = Color.White, // 白色文字
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
Cursor = Cursors.Hand,
TextAlign = ContentAlignment.MiddleCenter // 文字居中
};
// 设置边框
button.FlatAppearance.BorderSize = 0;
// 添加圆角效果
GraphicsPath path = new GraphicsPath();
int radius = 8; // 圆角半径
Rectangle rect = new Rectangle(0, 0, button.Width, button.Height);
path.AddArc(rect.X, rect.Y, radius * 2, radius * 2, 180, 90);
path.AddArc(rect.X + rect.Width - radius * 2, rect.Y, radius * 2, radius * 2, 270, 90);
path.AddArc(rect.X + rect.Width - radius * 2, rect.Y + rect.Height - radius * 2, radius * 2, radius * 2, 0, 90);
path.AddArc(rect.X, rect.Y + rect.Height - radius * 2, radius * 2, radius * 2, 90, 90);
path.CloseFigure();
button.Region = new Region(path);
// 修改鼠标悬停效果的颜色
button.MouseEnter += delegate(object sender, EventArgs e) {
button.BackColor = Color.FromArgb(0, 102, 184); // 深一点的蓝色
};
button.MouseLeave += delegate(object sender, EventArgs e) {
button.BackColor = Color.FromArgb(0, 122, 204); // 恢复原来的蓝色
};
// 修改文本绘制部分
button.Paint += delegate(object sender, PaintEventArgs e) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (GraphicsPath buttonPath = new GraphicsPath())
{
Rectangle newRect = new Rectangle(0, 0, button.Width, button.Height);
buttonPath.AddArc(newRect.X, newRect.Y, radius * 2, radius * 2, 180, 90);
buttonPath.AddArc(newRect.X + newRect.Width - radius * 2, newRect.Y, radius * 2, radius * 2, 270, 90);
buttonPath.AddArc(newRect.X + newRect.Width - radius * 2, newRect.Y + newRect.Height - radius * 2, radius * 2, radius * 2, 0, 90);
buttonPath.AddArc(newRect.X, newRect.Y + newRect.Height - radius * 2, radius * 2, radius * 2, 90, 90);
buttonPath.CloseFigure();
e.Graphics.FillPath(new SolidBrush(button.BackColor), buttonPath);
// 绘制文本(居中对齐)
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center; // 水平居中
sf.LineAlignment = StringAlignment.Center; // 垂直居中
e.Graphics.DrawString(button.Text, button.Font, new SolidBrush(button.ForeColor), newRect, sf);
}
};
// 添加按钮点击事件
button.Click += delegate(object sender, EventArgs e) {
Button clickedButton = (Button)sender;
int id = (int)clickedButton.Tag;
string text = clickedButton.Text;
Console.Write("{\"id\":" + id + ",\"text\":\"" + text.Replace("\"", "\\\"") + "\"}");
dialog.DialogResult = DialogResult.OK;
};
contentPanel.Controls.Add(button);
currentY += BUTTON_HEIGHT + SPACING;
}
// 处理窗口关闭事件
dialog.FormClosing += delegate(object sender, FormClosingEventArgs e) {
if (dialog.DialogResult == DialogResult.None)
{
Console.Write("{}");
}
};
}
private static void CreateTextAreaDialog(Form dialog, string content)
{
dialog.Height = 600; // 改为600
TextBox textArea = new TextBox
{
Multiline = true,
ScrollBars = ScrollBars.Vertical,
Width = dialog.ClientSize.Width - PADDING * 2,
Height = dialog.ClientSize.Height - PADDING * 3 - BUTTON_HEIGHT,
Location = new Point(PADDING, PADDING),
ForeColor = SystemColors.WindowText,
Text = content, // 使用传入的content作为默认文本
Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Regular),
BorderStyle = BorderStyle.FixedSingle
};
dialog.Controls.Add(textArea);
// 添加确定按钮
Button okButton = CreateStyledButton("确定", DialogResult.OK);
okButton.Location = new Point(
dialog.ClientSize.Width - BUTTON_WIDTH - PADDING,
dialog.ClientSize.Height - PADDING - BUTTON_HEIGHT
);
// 处理确定按钮点击事件
okButton.Click += delegate(object sender, EventArgs e) {
Console.Write(textArea.Text ?? ""); // 直接输出文本,不加引号
};
dialog.Controls.Add(okButton);
okButton.BringToFront();
}
private static string GetArgumentValue(string[] args, string key)
{
int index = Array.IndexOf(args, key);
if (index >= 0 && index < args.Length - 1)
{
return args[index + 1];
}
return string.Empty;
}
private static void StyleButton(Button button)
{
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderSize = 0;
button.BackColor = Color.FromArgb(0, 122, 204);
button.ForeColor = Color.White;
button.Font = new Font("Microsoft YaHei UI", 9F, FontStyle.Regular);
button.Cursor = Cursors.Hand;
button.Width = BUTTON_WIDTH;
button.Height = BUTTON_HEIGHT;
// 圆角绘制
GraphicsPath path = new GraphicsPath();
int radius = 8; // 圆角半径
Rectangle rect = new Rectangle(0, 0, button.Width, button.Height);
path.AddArc(rect.X, rect.Y, radius * 2, radius * 2, 180, 90);
path.AddArc(rect.X + rect.Width - radius * 2, rect.Y, radius * 2, radius * 2, 270, 90);
path.AddArc(rect.X + rect.Width - radius * 2, rect.Y + rect.Height - radius * 2, radius * 2, radius * 2, 0, 90);
path.AddArc(rect.X, rect.Y + rect.Height - radius * 2, radius * 2, radius * 2, 90, 90);
path.CloseFigure();
button.Region = new Region(path);
// 添加鼠标悬停效果
button.MouseEnter += delegate(object sender, EventArgs e) {
button.BackColor = Color.FromArgb(0, 102, 184);
};
button.MouseLeave += delegate(object sender, EventArgs e) {
button.BackColor = Color.FromArgb(0, 122, 204);
};
// 自定义绘制
button.Paint += delegate(object sender, PaintEventArgs e) {
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (GraphicsPath buttonPath = new GraphicsPath())
{
Rectangle newRect = new Rectangle(0, 0, button.Width, button.Height);
buttonPath.AddArc(newRect.X, newRect.Y, radius * 2, radius * 2, 180, 90);
buttonPath.AddArc(newRect.X + newRect.Width - radius * 2, newRect.Y, radius * 2, radius * 2, 270, 90);
buttonPath.AddArc(newRect.X + newRect.Width - radius * 2, newRect.Y + newRect.Height - radius * 2, radius * 2, radius * 2, 0, 90);
buttonPath.AddArc(newRect.X, newRect.Y + newRect.Height - radius * 2, radius * 2, radius * 2, 90, 90);
buttonPath.CloseFigure();
e.Graphics.FillPath(new SolidBrush(button.BackColor), buttonPath);
// 绘制文本
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(button.Text, button.Font, new SolidBrush(button.ForeColor), newRect, sf);
}
};
}
private static Button CreateStyledButton(string text, DialogResult dialogResult)
{
Button button = new Button();
button.Text = text;
button.DialogResult = dialogResult;
StyleButton(button);
return button;
}
public static void Main(string[] args)
{
InitializeDPIAwareness();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Show(args);
}
private class NativeMethods
{
[DllImport("user32.dll")]
public static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref RECT lParam);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
}
}

View File

@ -10,12 +10,14 @@ const getQuickcommandTempFile = (ext, name, dir = "quickcommandTempDir") => {
};
const getQuickcommandFolderFile = (name, ext) => {
const quickcommandPath = path.join(
const folderPath = path.join(
window.utools.getPath("userData"),
"quickcommand"
);
if (!fs.existsSync(quickcommandPath)) fs.mkdirSync(quickcommandPath);
return path.join(quickcommandPath, `${name}.${ext}`);
if (!fs.existsSync(folderPath)) {
fs.mkdirSync(folderPath, { recursive: true });
}
return path.join(folderPath, `${name}.${ext}`);
};
module.exports = { getQuickcommandTempFile, getQuickcommandFolderFile };

View File

@ -178,6 +178,53 @@ const quickcommand = {
}
return null;
},
// 运行C#脚本
runCsharp: function (script, args = []) {
return new Promise((reslove, reject) => {
let cscPath = path.join(
process.env.WINDIR,
"Microsoft.NET",
"Framework",
"v4.0.30319",
"csc.exe"
);
if (!fs.existsSync(cscPath)) {
cscPath = path.join(
process.env.WINDIR,
"Microsoft.NET",
"Framework",
"v3.5",
"csc.exe"
);
}
if (!fs.existsSync(cscPath)) {
return reject("未安装.NET Framework");
}
let tempCsharpFile = getQuickcommandTempFile("cs");
let tempBuildFile = getQuickcommandTempFile("exe");
fs.writeFile(tempCsharpFile, iconv.encode(script, "gbk"), (err) => {
if (err) return reject(err.toString());
// 添加命令行参数
const argsStr =
args.length > 0 ? " " + args.map((arg) => `"${arg}"`).join(" ") : "";
child_process.exec(
`${cscPath} /nologo /out:${tempBuildFile} ${tempCsharpFile} && ${tempBuildFile}${argsStr}`,
{
encoding: "buffer",
windowsHide: true,
},
(err, stdout) => {
if (err) reject(iconv.decode(stdout, "gbk"));
else reslove(iconv.decode(stdout, "gbk"));
fs.unlink(tempCsharpFile, () => {});
fs.unlink(tempBuildFile, () => {});
}
);
});
});
},
};
if (process.platform === "win32") {
@ -219,52 +266,6 @@ if (process.platform === "win32") {
});
};
// 运行C#脚本
quickcommand.runCsharp = function (script) {
return new Promise((reslove, reject) => {
// 找到csc.exe
let cscPath = path.join(
process.env.WINDIR,
"Microsoft.NET",
"Framework",
"v4.0.30319",
"csc.exe"
);
if (!fs.existsSync(cscPath)) {
cscPath = path.join(
process.env.WINDIR,
"Microsoft.NET",
"Framework",
"v3.5",
"csc.exe"
);
}
if (!fs.existsSync(cscPath)) {
return reject("未安装.NET Framework");
}
// 写入临时文件
let tempCsharpFile = getQuickcommandTempFile("cs");
let tempBuildFile = getQuickcommandTempFile("exe");
fs.writeFile(tempCsharpFile, iconv.encode(script, "gbk"), (err) => {
if (err) return reject(err.toString());
// 运行csc.exe
child_process.exec(
`${cscPath} /nologo /out:${tempBuildFile} ${tempCsharpFile} && ${tempBuildFile}`,
{
encoding: "buffer",
windowsHide: true,
},
(err, stdout) => {
if (err) reject(iconv.decode(stdout, "gbk"));
else reslove(iconv.decode(stdout, "gbk"));
fs.unlink(tempCsharpFile, () => {});
fs.unlink(tempBuildFile, () => {});
}
);
});
});
};
quickcommand.showSystemTextArea = systemDialog.showSystemTextArea;
}
@ -312,7 +313,6 @@ if (process.platform !== "linux") {
quickcommand.showSystemMessageBox = systemDialog.showSystemMessageBox;
quickcommand.showSystemInputBox = systemDialog.showSystemInputBox;
quickcommand.showSystemConfirmBox = systemDialog.showSystemConfirmBox;
quickcommand.showSystemSelectList = systemDialog.showSystemSelectList;
quickcommand.showSystemButtonBox = systemDialog.showSystemButtonBox;
}

View File

@ -3,7 +3,13 @@ const path = require("path");
const { exec } = require("child_process");
const { getQuickcommandFolderFile } = require("./getQuickcommandFile");
// 添加一个辅助函数来执行命令
// 读取 dialog.cs 模板
const dialogTemplate = fs.readFileSync(
path.join(__dirname, "csharp", "dialog.cs"),
"utf8"
);
// 辅助函数
const execCommand = (cmd) => {
return new Promise((resolve, reject) => {
exec(cmd, (error, stdout, stderr) => {
@ -16,7 +22,6 @@ const execCommand = (cmd) => {
});
};
// 添加一个辅助函数来检查命令是否存在
const checkZenity = async () => {
try {
await execCommand("which zenity");
@ -29,137 +34,75 @@ const checkZenity = async () => {
}
};
// 定义通用样式
const commonStyles = `
static void ApplyModernStyle(Form form) {
form.Font = new Font("Microsoft YaHei UI", 9F);
form.BackColor = Color.White;
form.Padding = new Padding(15);
}
static void ApplyButtonStyle(Button button) {
button.FlatStyle = FlatStyle.Flat;
button.BackColor = Color.FromArgb(0, 120, 212);
button.ForeColor = Color.White;
button.Font = new Font("Microsoft YaHei UI", 9F);
button.Cursor = Cursors.Hand;
button.FlatAppearance.BorderSize = 0;
button.Height = 30;
button.Width = 85;
}
static void ApplySecondaryButtonStyle(Button button) {
button.FlatStyle = FlatStyle.Flat;
button.BackColor = Color.FromArgb(240, 240, 240);
button.ForeColor = Color.Black;
button.Font = new Font("Microsoft YaHei UI", 9F);
button.Cursor = Cursors.Hand;
button.FlatAppearance.BorderSize = 1;
button.FlatAppearance.BorderColor = Color.FromArgb(200, 200, 200);
button.Height = 30;
button.Width = 85;
}
static void ApplyTextBoxStyle(TextBox textBox) {
textBox.BorderStyle = BorderStyle.FixedSingle;
textBox.Font = new Font("Microsoft YaHei UI", 9F);
}
static void ApplyLabelStyle(Label label) {
label.Font = new Font("Microsoft YaHei UI", 9F);
label.ForeColor = Color.FromArgb(51, 51, 51);
}
static void ApplyListBoxStyle(ListBox listBox) {
listBox.Font = new Font("Microsoft YaHei UI", 9F);
listBox.BorderStyle = BorderStyle.FixedSingle;
listBox.BackColor = Color.White;
}`;
const getQuickcommandIconPath = () => {
try {
const iconPath = getQuickcommandFolderFile("logo", "png");
if (!fs.existsSync(iconPath)) {
fs.copyFileSync(path.join(__dirname, "..", "logo.png"), iconPath);
const sourcePath = path.join(__dirname, "..", "logo.png");
if (!fs.existsSync(sourcePath)) {
console.error("Source icon not found:", sourcePath);
return "";
}
fs.copyFileSync(sourcePath, iconPath);
}
return iconPath;
} catch (error) {
console.error(error);
return null;
console.error("Error getting icon path:", error);
return "";
}
};
// 修改对话框函数,使用新的 dialog.cs
const showSystemMessageBox = async function (content, title = "") {
const iconPath = getQuickcommandIconPath();
if (window.utools.isMacOs()) {
let iconParam = "note";
if (iconPath) {
const posixPath = iconPath.replace(/\\/g, "/");
iconParam = `alias POSIX file "${posixPath}"`;
try {
const iconPath = getQuickcommandIconPath();
if (window.utools.isWindows()) {
const args = [
"-type",
"message",
"-title",
title,
"-content",
content.replace(/\r\n|\n/g, ""),
];
if (iconPath) {
args.push("-iconpath", iconPath.replace(/\\/g, "\\\\"));
}
const csharpCode = dialogTemplate;
const result = await this.runCsharp(csharpCode, args);
if (result && result.startsWith("Error:")) {
throw new Error(result.substring(7));
}
return;
}
const script = `display dialog "${content}" with title "${title}" buttons {"确定"} default button "确定" with icon ${iconParam}`;
await this.runAppleScript(script);
} else if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
class Program {
${commonStyles}
static void Main() {
Form form = new Form();
Label label = new Label();
Button okButton = new Button();
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(400, 130);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
ApplyLabelStyle(label);
label.Text = "${content}";
label.SetBounds(15, 15, 370, 60);
label.AutoSize = true;
form.Controls.Add(label);
ApplyButtonStyle(okButton);
okButton.Text = "确定";
okButton.DialogResult = DialogResult.OK;
okButton.SetBounds(300, 80, 85, 30);
form.Controls.Add(okButton);
form.AcceptButton = okButton;
form.ShowDialog();
form.Dispose();
}
}`;
await this.runCsharp(csharpScript);
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return;
try {
const script = `zenity --info --title="${title}" --text="${content}" --width=400`;
await execCommand(script);
} catch (error) {
console.error("执行 zenity 命令失败:", error);
if (window.utools.isMacOs()) {
let iconParam = "note";
if (iconPath) {
const posixPath = iconPath.replace(/\\/g, "/");
iconParam = `alias POSIX file "${posixPath}"`;
}
const script = `display dialog "${content}" with title "${title}" buttons {"取消", "确定"} default button "确定" with icon ${iconParam}`;
const result = await this.runAppleScript(script);
return result.includes("button returned:确定");
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return false;
try {
const script = `zenity --info --title="${title}" --text="${content}" --width=400`;
await execCommand(script);
return true;
} catch (error) {
return false;
}
}
} catch (error) {
console.error("Dialog error:", error);
window.utools.showNotification(`对话框错误: ${error.message}`);
return false;
}
};
// 系统级输入框
const showSystemInputBox = async function (placeholders, title = "") {
if (!Array.isArray(placeholders)) {
placeholders = [placeholders];
@ -189,79 +132,23 @@ const showSystemInputBox = async function (placeholders, title = "") {
}
return results;
} else if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
const args = [
"-type",
"input",
"-title",
title,
"-content",
placeholders.join("|||||"),
];
class Program {
${commonStyles}
if (iconPath) {
args.push("-iconpath", iconPath.replace(/\\/g, "\\\\"));
}
static void Main() {
Form form = new Form();
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(350, ${45 + placeholders.length * 70});
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
${placeholders
.map(
(placeholder, index) => `
Label label${index} = new Label();
ApplyLabelStyle(label${index});
label${index}.Text = "${placeholder}";
label${index}.SetBounds(15, ${15 + index * 70}, 320, 20);
form.Controls.Add(label${index});
TextBox textBox${index} = new TextBox();
ApplyTextBoxStyle(textBox${index});
textBox${index}.SetBounds(15, ${40 + index * 70}, 320, 25);
form.Controls.Add(textBox${index});`
)
.join("\n")}
Button okButton = new Button();
ApplyButtonStyle(okButton);
okButton.Text = "确定";
okButton.DialogResult = DialogResult.OK;
okButton.SetBounds(160, ${20 + placeholders.length * 70}, 85, 30);
form.Controls.Add(okButton);
Button cancelButton = new Button();
ApplySecondaryButtonStyle(cancelButton);
cancelButton.Text = "取消";
cancelButton.DialogResult = DialogResult.Cancel;
cancelButton.SetBounds(250, ${
20 + placeholders.length * 70
}, 85, 30);
form.Controls.Add(cancelButton);
form.AcceptButton = okButton;
form.CancelButton = cancelButton;
if (form.ShowDialog() == DialogResult.OK) {
${placeholders
.map((_, index) => `Console.WriteLine(textBox${index}.Text);`)
.join("\n ")}
}
form.Dispose();
}
}`;
const result = await this.runCsharp(csharpScript);
return result.trim() || null;
const csharpCode = dialogTemplate;
const result = await this.runCsharp(csharpCode, args);
console.log(result, JSON.parse(result));
return result ? JSON.parse(result) : null;
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return null;
const results = [];
@ -280,7 +167,6 @@ const showSystemInputBox = async function (placeholders, title = "") {
}
};
// 系统级确认框
const showSystemConfirmBox = async function (content, title = "") {
const iconPath = getQuickcommandIconPath();
if (window.utools.isMacOs()) {
@ -293,65 +179,22 @@ const showSystemConfirmBox = async function (content, title = "") {
const result = await this.runAppleScript(script);
return result.includes("button returned:确定");
} else if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
class Program {
${commonStyles}
const args = [
"-type",
"confirm",
"-title",
title,
"-content",
content.replace(/\r\n|\n/g, "\\n"),
];
static void Main() {
Form form = new Form();
Label label = new Label();
Button okButton = new Button();
Button cancelButton = new Button();
if (iconPath) {
args.push("-iconpath", iconPath.replace(/\\/g, "\\\\"));
}
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(400, 130);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
ApplyLabelStyle(label);
label.Text = "${content}";
label.SetBounds(15, 15, 370, 60);
label.AutoSize = true;
form.Controls.Add(label);
ApplyButtonStyle(okButton);
okButton.Text = "确定";
okButton.DialogResult = DialogResult.OK;
okButton.SetBounds(210, 80, 85, 30);
form.Controls.Add(okButton);
ApplySecondaryButtonStyle(cancelButton);
cancelButton.Text = "取消";
cancelButton.DialogResult = DialogResult.Cancel;
cancelButton.SetBounds(300, 80, 85, 30);
form.Controls.Add(cancelButton);
form.AcceptButton = okButton;
form.CancelButton = cancelButton;
DialogResult result = form.ShowDialog();
Console.WriteLine(result == DialogResult.OK);
form.Dispose();
}
}`;
const result = await this.runCsharp(csharpScript);
return result.trim() === "True";
const csharpCode = dialogTemplate;
const result = await this.runCsharp(csharpCode, args);
return result === "true";
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return false;
try {
@ -364,216 +207,40 @@ const showSystemConfirmBox = async function (content, title = "") {
}
};
// 系统级选择框
const showSystemSelectList = async function (items, title = "") {
const showSystemButtonBox = async function (buttons, title = "") {
const iconPath = getQuickcommandIconPath();
if (window.utools.isMacOs()) {
const itemList = items.map((item) => `"${item}"`).join(", ");
const script = `choose from list {${itemList}} with title "${title}" with prompt "请选择:" default items {"${items[0]}"}`;
const itemList = buttons.map((item) => `"${item}"`).join(", ");
const script = `choose from list {${itemList}} with title "${title}" with prompt "请选择:" default items {"${buttons[0]}"}`;
const result = await this.runAppleScript(script);
if (result.includes("false")) return null;
const text = result.trim();
const id = items.findIndex((item) => item === text);
const id = buttons.findIndex((item) => item === text);
return { id, text };
} else if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
const args = [
"-type",
"buttons",
"-title",
title,
"-content",
buttons.join("|||||"),
];
class Program {
${commonStyles}
if (iconPath) {
args.push("-iconpath", iconPath.replace(/\\/g, "\\\\"));
}
static void Main() {
Form form = new Form();
ListBox listBox = new ListBox();
Button okButton = new Button();
Button cancelButton = new Button();
Label titleLabel = new Label();
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(350, 280);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
titleLabel.Text = "请选择:";
titleLabel.AutoSize = true;
titleLabel.SetBounds(15, 15, 320, 20);
ApplyLabelStyle(titleLabel);
form.Controls.Add(titleLabel);
ApplyListBoxStyle(listBox);
listBox.SetBounds(15, 45, 320, 180);
${items
.map((item) => `listBox.Items.Add("${item}");`)
.join("\n ")}
listBox.SelectedIndex = 0;
form.Controls.Add(listBox);
ApplyButtonStyle(okButton);
okButton.Text = "确定";
okButton.DialogResult = DialogResult.OK;
okButton.SetBounds(160, 235, 85, 30);
form.Controls.Add(okButton);
ApplySecondaryButtonStyle(cancelButton);
cancelButton.Text = "取消";
cancelButton.DialogResult = DialogResult.Cancel;
cancelButton.SetBounds(250, 235, 85, 30);
form.Controls.Add(cancelButton);
form.AcceptButton = okButton;
form.CancelButton = cancelButton;
if (form.ShowDialog() == DialogResult.OK && listBox.SelectedItem != null) {
Console.WriteLine(listBox.SelectedIndex.ToString() + "|||||" + listBox.SelectedItem.ToString());
}
form.Dispose();
}
}`;
const result = await this.runCsharp(csharpScript);
if (result.trim()) {
const [id, text] = result.trim().split("|||||");
return { id: parseInt(id), text };
const csharpCode = dialogTemplate;
const result = await this.runCsharp(csharpCode, args);
if (result) {
return JSON.parse(result);
}
return null;
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return null;
try {
const itemsList = items
.map((item, index) => `"${index}" "${item}"`)
.join(" ");
const script = `zenity --list --title="${title}" --text="请选择:" --column="序号" --column="选项" ${itemsList} --width=400 --height=300`;
const result = await execCommand(script);
if (!result) return null;
const text = result.trim();
const id = items.findIndex((item) => item === text);
return { id, text };
} catch (error) {
console.error("执行 zenity 命令失败:", error);
return null;
}
}
};
// 系统级按钮组弹窗
const showSystemButtonBox = async function (buttons, content = "", title = "") {
const iconPath = getQuickcommandIconPath();
if (window.utools.isMacOs()) {
try {
let iconParam = "note";
if (iconPath) {
const posixPath = iconPath.replace(/\\/g, "/");
iconParam = `alias POSIX file "${posixPath}"`;
}
const buttonList = buttons.map((btn) => `"${btn}"`).join(", ");
const script = `display dialog "${content}" with title "${title}" buttons {${buttonList}} default button "${buttons[0]}" with icon ${iconParam}`;
const result = await this.runAppleScript(script);
const match = result.match(/button returned:(.+)/);
if (match) {
const text = match[1];
const id = buttons.findIndex((btn) => btn === text);
return { id, text };
}
return null;
} catch (error) {
window.utools.showNotification(error);
throw error;
}
} else if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
class Program {
${commonStyles}
static void Main() {
Form form = new Form();
Label label = new Label();
FlowLayoutPanel buttonPanel = new FlowLayoutPanel();
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(400, 160);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
ApplyLabelStyle(label);
label.Text = "${content}";
label.SetBounds(15, 15, 370, 60);
label.AutoSize = true;
form.Controls.Add(label);
buttonPanel.SetBounds(15, 90, 370, 40);
buttonPanel.FlowDirection = FlowDirection.RightToLeft;
buttonPanel.WrapContents = false;
buttonPanel.BackColor = Color.White;
form.Controls.Add(buttonPanel);
${buttons
.map(
(btn, index) => `
Button button${index} = new Button();
button${index}.Text = "${btn}";
button${index}.DialogResult = DialogResult.OK;
button${index}.Tag = "${index}";
${
index === 0 ? "ApplyButtonStyle" : "ApplySecondaryButtonStyle"
}(button${index});
button${index}.Margin = new Padding(5, 0, 0, 0);
buttonPanel.Controls.Add(button${index});`
)
.join("\n")}
DialogResult result = form.ShowDialog();
if (result == DialogResult.OK) {
foreach (Button btn in buttonPanel.Controls) {
if (btn.DialogResult == result) {
Console.WriteLine(btn.Tag.ToString() + "|||||" + btn.Text);
break;
}
}
}
form.Dispose();
}
}`;
const result = await this.runCsharp(csharpScript);
if (result.trim()) {
const [id, text] = result.trim().split("|||||");
return { id: parseInt(id), text };
}
return null;
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return null;
try {
const script1 = `zenity --info --title="${title}" --text="${content}" --width=400`;
const script1 = `zenity --info --title="${title}" --width=400`;
await execCommand(script1);
const itemsList = buttons
@ -592,95 +259,29 @@ const showSystemButtonBox = async function (buttons, content = "", title = "") {
}
};
// 系统级文本区域弹窗
const showSystemTextArea = async function (
placeholder = "",
defaultText = "",
title = ""
) {
const showSystemTextArea = async function (defaultText = "", title = "") {
const iconPath = getQuickcommandIconPath();
if (window.utools.isWindows()) {
const escapedIconPath = iconPath ? iconPath.replace(/\\/g, "\\\\") : null;
const csharpScript = `
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
const args = [
"-type",
"textarea",
"-title",
title,
"-content",
defaultText,
];
class Program {
${commonStyles}
if (iconPath) {
args.push("-iconpath", iconPath.replace(/\\/g, "\\\\"));
}
static void Main() {
Form form = new Form();
TextBox textBox = new TextBox();
Button okButton = new Button();
Button cancelButton = new Button();
Label label = new Label();
ApplyModernStyle(form);
form.Text = "${title}";
form.ClientSize = new Size(450, 320);
form.FormBorderStyle = FormBorderStyle.FixedDialog;
form.StartPosition = FormStartPosition.CenterScreen;
form.MaximizeBox = false;
form.MinimizeBox = false;
${
escapedIconPath
? `using (var bmp = new Bitmap("${escapedIconPath}"))
{
form.Icon = Icon.FromHandle(bmp.GetHicon());
}`
: ""
}
ApplyLabelStyle(label);
label.Text = "${placeholder}";
label.SetBounds(15, 15, 420, 20);
form.Controls.Add(label);
ApplyTextBoxStyle(textBox);
textBox.Multiline = true;
textBox.ScrollBars = ScrollBars.Vertical;
textBox.SetBounds(15, 45, 420, 220);
textBox.Text = "${defaultText}";
textBox.AcceptsReturn = true;
form.Controls.Add(textBox);
ApplyButtonStyle(okButton);
okButton.Text = "确定";
okButton.DialogResult = DialogResult.OK;
okButton.SetBounds(260, 275, 85, 30);
form.Controls.Add(okButton);
ApplySecondaryButtonStyle(cancelButton);
cancelButton.Text = "取消";
cancelButton.DialogResult = DialogResult.Cancel;
cancelButton.SetBounds(350, 275, 85, 30);
form.Controls.Add(cancelButton);
form.AcceptButton = null;
form.CancelButton = cancelButton;
form.KeyPreview = true;
form.KeyDown += (sender, e) => {
if (e.KeyCode == Keys.Enter && e.Control) {
okButton.PerformClick();
e.Handled = true;
}
};
if (form.ShowDialog() == DialogResult.OK) {
Console.WriteLine(textBox.Text);
}
form.Dispose();
}
}`;
const result = await this.runCsharp(csharpScript);
return result.trim() || null;
const csharpCode = dialogTemplate;
const result = await this.runCsharp(csharpCode, args);
return result || null;
} else if (window.utools.isLinux()) {
if (!(await checkZenity())) return null;
try {
const script = `zenity --text-info --title="${title}" --text="${placeholder}" --editable --width=450 --height=350 --filename=<(echo "${defaultText}")`;
const script = `zenity --text-info --title="${title}" --editable --width=450 --height=350 --filename=<(echo "${defaultText}")`;
const result = await execCommand(script);
return result ? result.trim() : null;
} catch (error) {
@ -694,7 +295,6 @@ module.exports = {
showSystemMessageBox,
showSystemInputBox,
showSystemConfirmBox,
showSystemSelectList,
showSystemButtonBox,
showSystemTextArea,
};

View File

@ -200,30 +200,11 @@ export const uiCommands = {
},
{
value: "quickcommand.showSelectList",
label: "uTools选择列表",
label: "选择列表",
desc: "显示一个支持搜索的选项列表,可以动态更新选项",
component: "SelectListEditor",
isAsync: true,
},
{
value: "quickcommand.showSystemSelectList",
label: "系统选择列表",
desc: "选择列表(系统)",
isAsync: true,
config: [
{
label: "选项",
component: "ArrayEditor",
width: 12,
},
{
label: "标题",
component: "VariableInput",
defaultValue: newVarInputVal("str", "请选择"),
width: 12,
},
],
},
{
value: "quickcommand.showTextArea",
label: "文本框",
@ -231,30 +212,44 @@ export const uiCommands = {
isAsync: true,
outputVariable: "textareaValue",
saveOutput: true,
config: [
{
label: "文本框占位符",
component: "VariableInput",
defaultValue: newVarInputVal("str", "请输入"),
width: 6,
},
{
label: "文本框默认值",
component: "VariableInput",
defaultValue: newVarInputVal("str"),
width: 6,
},
],
subCommands: [
{
value: "quickcommand.showTextArea",
icon: "call_to_action",
label: "插件内弹窗",
config: [
{
label: "文本框占位符",
component: "VariableInput",
defaultValue: newVarInputVal("str", "请输入"),
width: 6,
},
{
label: "文本框默认值",
component: "VariableInput",
defaultValue: newVarInputVal("str"),
width: 6,
},
],
},
{
value: "quickcommand.showSystemTextArea",
icon: "report",
label: "系统弹窗(Mac不支持)",
config: [
{
label: "文本框默认值",
component: "VariableInput",
defaultValue: newVarInputVal("str"),
width: 6,
},
{
label: "标题",
component: "VariableInput",
defaultValue: newVarInputVal("str", "请输入"),
width: 6,
},
],
},
],
},

View File

@ -549,30 +549,12 @@ interface quickcommandApi {
*/
showSystemConfirmBox(content: string, title?: string): Promise<boolean>;
/**
* Linux
*
* ```js
* quickcommand.showSystemSelectList(["选项1", "选项2", "选项3"], "请选择").then(result => {
* if (result) {
* console.log(`选择了第${result.id + 1}个选项:${result.text}`)
* }
* })
* ```
*
* @param items
* @param title
*/
showSystemSelectList(
items: string[],
title?: string
): Promise<{ id: number; text: string } | null>;
/**
* Linux
*
* ```js
* quickcommand.showSystemButtonBox(["保存", "不保存", "取消"], "是否保存更改?", "保存确认").then(result => {
* quickcommand.showSystemButtonBox(["保存", "不保存", "取消"], "保存确认").then(result => {
* if (result) {
* console.log(`点击了第${result.id + 1}个按钮:${result.text}`)
* }
@ -580,12 +562,10 @@ interface quickcommandApi {
* ```
*
* @param buttons
* @param content
* @param title
*/
showSystemButtonBox(
buttons: string[],
content: string,
title?: string
): Promise<{ id: number; text: string } | null>;
@ -593,19 +573,17 @@ interface quickcommandApi {
* Windows支持
*
* ```js
* quickcommand.showSystemTextArea("请输入多行文本:", "默认内容", "文本编辑").then(text => {
* quickcommand.showSystemTextArea("默认内容", "文本编辑").then(text => {
* if (text) {
* console.log("输入的文本:", text)
* }
* })
* ```
*
* @param placeholder
* @param defaultText
* @param defaultText
* @param title
*/
showSystemTextArea(
placeholder?: string,
defaultText?: string,
title?: string
): Promise<string | null>;