diff --git a/src/main/java/com/axis/innovators/box/register/RegistrationTool.java b/src/main/java/com/axis/innovators/box/register/RegistrationTool.java index 311f0b2..4a443c6 100644 --- a/src/main/java/com/axis/innovators/box/register/RegistrationTool.java +++ b/src/main/java/com/axis/innovators/box/register/RegistrationTool.java @@ -6,6 +6,7 @@ import com.axis.innovators.box.window.FridaWindow; import com.axis.innovators.box.window.JarApiProfilingWindow; import com.axis.innovators.box.window.MainWindow; import com.axis.innovators.box.plugins.PluginDescriptor; +import com.axis.innovators.box.window.TaskbarAppearanceWindow; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.tzd.lm.LM; @@ -47,7 +48,6 @@ public class RegistrationTool { } })); - MainWindow.ToolCategory programmingToolsCategory = new MainWindow.ToolCategory("编程工具", "programming/programming.png", "编程工具"); @@ -108,9 +108,23 @@ public class RegistrationTool { } })); + MainWindow.ToolCategory systemCategory = new MainWindow.ToolCategory("系统工具", + "windows/windows.png", + "系统工具"); + systemCategory.addTool(new MainWindow.ToolItem("任务栏主题设置", "windows/windowsOptimization/windowsOptimization.png", + "可以设置Windows任务栏的颜色等各种信息",++id, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + Window owner = SwingUtilities.windowForComponent((Component) e.getSource()); + TaskbarAppearanceWindow taskbarAppearanceWindow = new TaskbarAppearanceWindow(owner); + main.popupWindow(taskbarAppearanceWindow); + } + })); + addToolCategory(debugCategory, "system:debugTools"); addToolCategory(aICategory,"system:fridaTools"); addToolCategory(programmingToolsCategory, "system:programmingTools"); + addToolCategory(systemCategory, "system:systemTools"); } /** diff --git a/src/main/java/com/axis/innovators/box/window/MainWindow.java b/src/main/java/com/axis/innovators/box/window/MainWindow.java index afabb27..57cbecb 100644 --- a/src/main/java/com/axis/innovators/box/window/MainWindow.java +++ b/src/main/java/com/axis/innovators/box/window/MainWindow.java @@ -1186,14 +1186,7 @@ public class MainWindow extends JFrame { public String getDescription() { return description; } public String getIcon() { if (isDarkTheme()) { - int lastDotIndex = 0; - if (icon != null) { - lastDotIndex = icon.lastIndexOf('.'); - } - if (lastDotIndex > 0) { - return icon.substring(0, lastDotIndex) + "_dark" + icon.substring(lastDotIndex); - } - return icon + "_dark"; + return icon.replace(".png", "_dark.png"); } return icon; } diff --git a/src/main/java/com/axis/innovators/box/window/TaskbarAppearanceWindow.java b/src/main/java/com/axis/innovators/box/window/TaskbarAppearanceWindow.java new file mode 100644 index 0000000..aee0fbe --- /dev/null +++ b/src/main/java/com/axis/innovators/box/window/TaskbarAppearanceWindow.java @@ -0,0 +1,657 @@ +package com.axis.innovators.box.window; + +import com.axis.innovators.box.window.WindowsJDialog; +import org.tzd.explorer.LocalCall; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.RoundRectangle2D; +import java.awt.geom.Point2D; +import java.awt.RadialGradientPaint; +import java.io.IOException; +import java.util.Map; + + +/** + * @author tzdwindows 7 + */ +public class TaskbarAppearanceWindow extends WindowsJDialog { + private final JComboBox modeCombo; + private final JButton colorButton; + private final JSlider alphaSlider; + private final JButton applyButton; + private final JButton helpButton; + private final PreviewPanel previewPanel; + + private final JButton sysTextColorButton; + private final JButton applySysTextColorButton; + private Color sysTextColor = Color.BLACK; + + // 动画平滑过渡参数 + private Color currentColor = new Color(0, 0, 0); + private Color targetColor = new Color(0, 0, 0); + private int currentAlpha = 255; // 用于动画(实际 0-255) + private int targetAlpha = 255; // 用于动画(实际 0-255) + private LocalCall.TaskbarAccentMode currentMode = LocalCall.TaskbarAccentMode.ACCENT_DISABLED; + private LocalCall.TaskbarAccentMode targetMode = LocalCall.TaskbarAccentMode.ACCENT_DISABLED; + private Timer animationTimer = new Timer(16, e -> {}); + + // UI 元素引用(需要动态修改标签) + private JPanel alphaLabeledPanel; + private JLabel alphaLabel; + + private static final Map MODE_LABELS = Map.of( + LocalCall.TaskbarAccentMode.ACCENT_DISABLED, "禁用特效(无额外效果)", + LocalCall.TaskbarAccentMode.ACCENT_ENABLE_GRADIENT, "渐变(纯色/渐变)", + LocalCall.TaskbarAccentMode.ACCENT_ENABLE_TRANSPARENTGRADIENT, "透明渐变(半透明)", + LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND, "毛玻璃模糊(高档模糊)", + LocalCall.TaskbarAccentMode.ACCENT_ENABLE_ACRYLICBLURBEHIND, "亚克力模糊(Fluent 风格)", + LocalCall.TaskbarAccentMode.ACCENT_INVALID_STATE, "无效状态(保留)" + ); + + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + TaskbarAppearanceWindow w = new TaskbarAppearanceWindow(null); + w.setVisible(true); + }); + } + + public TaskbarAppearanceWindow(Window owner) { + super(owner, "任务栏外观设置", ModalityType.MODELESS); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + // 基本窗口设置 + setSize(1220, 750); + setLocationRelativeTo(owner); + ((JComponent) getContentPane()).setBorder(new EmptyBorder(12, 12, 12, 12)); + setLayout(new BorderLayout(12, 12)); + + // 顶部标题 + JPanel top = new JPanel(new BorderLayout()); + top.setOpaque(false); + JLabel header = new JLabel("任务栏外观 - 高级设置"); + header.setFont(header.getFont().deriveFont(Font.BOLD, 18f)); + JLabel sub = new JLabel("可实时预览任务栏效果。"); + sub.setFont(sub.getFont().deriveFont(12f)); + top.add(header, BorderLayout.NORTH); + top.add(sub, BorderLayout.SOUTH); + add(top, BorderLayout.NORTH); + + // 左侧:控制区 + JPanel left = new JPanel(); + left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS)); + left.setOpaque(false); + left.setPreferredSize(new Dimension(400, getHeight())); + left.setMaximumSize(new Dimension(420, Integer.MAX_VALUE)); + left.setBorder(new EmptyBorder(6, 6, 6, 6)); + + // 模式选择 + modeCombo = new JComboBox<>(LocalCall.TaskbarAccentMode.values()); + modeCombo.setMaximumSize(new Dimension(Integer.MAX_VALUE, 34)); + modeCombo.setRenderer((list, value, index, isSelected, cellHasFocus) -> { + JLabel lab = new JLabel(); + if (value instanceof LocalCall.TaskbarAccentMode) { + LocalCall.TaskbarAccentMode m = (LocalCall.TaskbarAccentMode) value; + lab.setText(MODE_LABELS.getOrDefault(m, m.name())); + } else { + lab.setText(String.valueOf(value)); + } + lab.setOpaque(isSelected); + if (isSelected) { + lab.setBackground(new Color(0, 120, 215, 40)); + } + lab.setBorder(new EmptyBorder(4, 4, 4, 4)); + return lab; + }); + left.add(labeledComponent("模式", modeCombo)); + left.add(Box.createVerticalStrut(10)); + + // 颜色选择 + colorButton = new JButton("选择任务栏颜色"); + colorButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 34)); + colorButton.setPreferredSize(new Dimension(200, 32)); + colorButton.setFocusPainted(false); + colorButton.addActionListener(e -> { + Color chosen = JColorChooser.showDialog(this, "选择任务栏颜色", targetColor); + if (chosen != null) { + setTargetColor(chosen); + } + }); + left.add(labeledComponent("颜色", colorButton)); + left.add(Box.createVerticalStrut(10)); + + // alpha 滑块(我们要能动态修改其标签和范围) + alphaSlider = new JSlider(0, 255, 255); + alphaSlider.setMajorTickSpacing(64); + alphaSlider.setMinorTickSpacing(16); + alphaSlider.setPaintTicks(true); + alphaSlider.setPaintLabels(true); + alphaSlider.setMaximumSize(new Dimension(Integer.MAX_VALUE, 64)); + alphaSlider.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + // 根据当前模式决定如何解释滑块值:如果是毛玻璃(degree 0-64),映射到 0-255;否则直接为 alpha + int v = alphaSlider.getValue(); + if (targetMode == LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND) { + // degree -> alpha (scale 0-64 to 0-255) + float ratio = Math.max(0f, Math.min(1f, v / 64f)); + targetAlpha = Math.round(ratio * 255f); + } else { + targetAlpha = clamp(v); + } + targetSliderChanged(v); + } + }); + // 用一个可变标签面板包裹 + alphaLabeledPanel = createAlphaLabeledPanel("不透明度 (Alpha)", alphaSlider); + left.add(alphaLabeledPanel); + left.add(Box.createVerticalStrut(10)); + + // 去掉字节序提示(按要求删除) + // left.add(Box.createVerticalStrut(10)); // 不再添加提示 + + // 按钮行 + JPanel btnRow = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0)); + btnRow.setOpaque(false); + applyButton = new JButton("应用到任务栏"); + helpButton = new JButton("查看帮助"); + Dimension smallBtn = new Dimension(140, 30); + applyButton.setPreferredSize(smallBtn); + helpButton.setPreferredSize(smallBtn); + applyButton.setMaximumSize(smallBtn); + helpButton.setMaximumSize(smallBtn); + applyButton.setFocusable(false); + helpButton.setFocusable(false); + applyButton.setMargin(new Insets(6, 10, 6, 10)); + helpButton.setMargin(new Insets(6, 10, 6, 10)); + btnRow.add(helpButton); + btnRow.add(applyButton); + btnRow.setAlignmentX(Component.LEFT_ALIGNMENT); + left.add(btnRow); + + left.add(Box.createVerticalStrut(14)); + + // 系统文字颜色(实验性) + sysTextColorButton = new JButton("选择系统文字颜色"); + sysTextColorButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 34)); + sysTextColorButton.setPreferredSize(new Dimension(180, 30)); + sysTextColorButton.setBackground(sysTextColor); + sysTextColorButton.setForeground(contrast(sysTextColor)); + sysTextColorButton.setFocusPainted(false); + sysTextColorButton.addActionListener(e -> { + Color chosen = JColorChooser.showDialog(this, "选择要设置的系统文字颜色", sysTextColor); + if (chosen != null) { + sysTextColor = chosen; + sysTextColorButton.setBackground(sysTextColor); + sysTextColorButton.setForeground(contrast(sysTextColor)); + } + }); + left.add(labeledComponent("系统文字颜色(实验性)", sysTextColorButton)); + left.add(Box.createVerticalStrut(8)); + applySysTextColorButton = new JButton("应用系统文字颜色(修改注册表)"); + applySysTextColorButton.setAlignmentX(Component.LEFT_ALIGNMENT); + applySysTextColorButton.setPreferredSize(new Dimension(220, 30)); + applySysTextColorButton.setMaximumSize(new Dimension(Integer.MAX_VALUE, 34)); + applySysTextColorButton.setFocusPainted(false); + left.add(applySysTextColorButton); + + left.add(Box.createVerticalGlue()); + + // 右侧:实时预览区 + previewPanel = new PreviewPanel(); + previewPanel.setPreferredSize(new Dimension(720, 520)); + JPanel previewWrap = new JPanel(new BorderLayout()); + previewWrap.setBorder(BorderFactory.createTitledBorder("实时预览")); + previewWrap.add(previewPanel, BorderLayout.CENTER); + + // 主布局 + JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, previewWrap); + split.setResizeWeight(0); + split.setDividerLocation(420); + split.setOneTouchExpandable(false); + add(split, BorderLayout.CENTER); + + // 事件绑定:模式切换时更新控件状态 + modeCombo.addActionListener(e -> { + LocalCall.TaskbarAccentMode sel = (LocalCall.TaskbarAccentMode) modeCombo.getSelectedItem(); + if (sel != null) { + setTargetMode(sel); + updateControlsForMode(sel); + } + }); + + // apply 按钮行为(在后台线程执行 LocalCall) + applyButton.addActionListener(e -> { + setControlsEnabled(false); + LocalCall.TaskbarAccentMode mode = targetMode; + String colorArg = buildColorArg(targetColor); // 0xRRGGBB + int alphaToSend = targetAlpha; // targetAlpha 已经是 0-255(如果毛玻璃,按 degree 映射) + boolean restartExplorerAlways = false; + if (mode == LocalCall.TaskbarAccentMode.ACCENT_INVALID_STATE) { + restartExplorerAlways = true; + } + + boolean finalRestartExplorerAlways = restartExplorerAlways; + SwingWorker worker = new SwingWorker<>() { + Exception ex = null; + @Override + protected Void doInBackground() { + try { + LocalCall.setTaskbarAppearance(mode, colorArg, alphaToSend, finalRestartExplorerAlways); + } catch (IOException | InterruptedException e1) { + ex = e1; + } + return null; + } + @Override + protected void done() { + setControlsEnabled(true); + if (ex != null) { + JOptionPane.showMessageDialog(TaskbarAppearanceWindow.this, + "应用到任务栏失败: " + ex.getMessage(), + "错误", JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(TaskbarAppearanceWindow.this, + "已尝试应用设置。若未生效可能需要 Explorer 重启或注销。", "完成", + JOptionPane.INFORMATION_MESSAGE); + } + } + }; + worker.execute(); + }); + + // 帮助按钮 + helpButton.addActionListener(e -> { + SwingWorker w = new SwingWorker<>() { + Exception ex = null; + @Override + protected Void doInBackground() { + try { + LocalCall.showTaskbarHelp(); + } catch (IOException | InterruptedException ioException) { + ex = ioException; + } + return null; + } + @Override + protected void done() { + if (ex != null) { + JOptionPane.showMessageDialog(TaskbarAppearanceWindow.this, + "调用帮助失败:" + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE); + } + } + }; + w.execute(); + }); + + // 应用系统文字颜色 + applySysTextColorButton.addActionListener(e -> { + applySysTextColorButton.setEnabled(false); + sysTextColorButton.setEnabled(false); + SwingWorker worker = new SwingWorker<>() { + Exception ex = null; + @Override + protected Void doInBackground() { + try { + setWindowsTextColor(sysTextColor); + } catch (IOException | InterruptedException ioException) { + ex = ioException; + } + return null; + } + @Override + protected void done() { + applySysTextColorButton.setEnabled(true); + sysTextColorButton.setEnabled(true); + if (ex != null) { + JOptionPane.showMessageDialog(TaskbarAppearanceWindow.this, + "应用系统文字颜色失败:" + ex.getMessage(), + "错误", JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(TaskbarAppearanceWindow.this, + "已尝试修改注册表并刷新用户外观参数(可能需要注销/重启以完全生效)。", + "提示", JOptionPane.INFORMATION_MESSAGE); + } + } + }; + worker.execute(); + }); + + // 双击预览快速体验 + previewPanel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + modeCombo.setSelectedItem(LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND); + // 设置滑块为中等程度示例 + alphaSlider.setValue(32); + applyButton.doClick(); + } + } + }); + + // 初始化目标并启动动画 Timer + setTargetColor(currentColor); + // 初始化 slider 为 255(默认) + alphaSlider.setValue(255); + // 默认模式更新 UI + updateControlsForMode(currentMode); + + animationTimer = new Timer(16, e -> { + boolean changed = false; + int rCur = currentColor.getRed(), gCur = currentColor.getGreen(), bCur = currentColor.getBlue(); + int rT = targetColor.getRed(), gT = targetColor.getGreen(), bT = targetColor.getBlue(); + int rNew = lerp(rCur, rT, 0.12f); + int gNew = lerp(gCur, gT, 0.12f); + int bNew = lerp(bCur, bT, 0.12f); + Color newColor = new Color(clamp(rNew), clamp(gNew), clamp(bNew)); + if (!newColor.equals(currentColor)) { + currentColor = newColor; + changed = true; + } + int aNew = lerp(currentAlpha, targetAlpha, 0.14f); + if (aNew != currentAlpha) { + currentAlpha = aNew; + changed = true; + } + if (currentMode != targetMode) { + if (Math.abs(currentAlpha - targetAlpha) < 3 && + Math.abs(currentColor.getRed() - targetColor.getRed()) < 3 && + Math.abs(currentColor.getGreen() - targetColor.getGreen()) < 3 && + Math.abs(currentColor.getBlue() - targetColor.getBlue()) < 3) { + currentMode = targetMode; + changed = true; + } + } + if (changed) { + previewPanel.setPreviewState(currentColor, currentAlpha, currentMode); + } else { + animationTimer.stop(); + } + }); + } + + // Enable / disable 控件 + private void setControlsEnabled(boolean enabled) { + // 模式选择保持可用(用户可以改变) + modeCombo.setEnabled(true); + //applyButton.setEnabled(enabled); + helpButton.setEnabled(enabled); + colorButton.setEnabled(enabled && targetMode != LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND + && targetMode != LocalCall.TaskbarAccentMode.ACCENT_INVALID_STATE); + alphaSlider.setEnabled(enabled && targetMode != LocalCall.TaskbarAccentMode.ACCENT_INVALID_STATE); + applySysTextColorButton.setEnabled(enabled); + sysTextColorButton.setEnabled(enabled); + } + + // 带标签的组件包装(左对齐) + private JPanel labeledComponent(String label, JComponent comp) { + JPanel p = new JPanel(); + p.setLayout(new BorderLayout(8, 8)); + p.setOpaque(false); + JLabel l = new JLabel(label); + l.setPreferredSize(new Dimension(140, 24)); + p.add(l, BorderLayout.WEST); + p.add(comp, BorderLayout.CENTER); + p.setAlignmentX(Component.LEFT_ALIGNMENT); + return p; + } + + // 创建 alpha 带可变标签的面板 + private JPanel createAlphaLabeledPanel(String labelText, JComponent comp) { + JPanel p = new JPanel(new BorderLayout(8, 8)); + p.setOpaque(false); + alphaLabel = new JLabel(labelText); + alphaLabel.setPreferredSize(new Dimension(140, 24)); + p.add(alphaLabel, BorderLayout.WEST); + p.add(comp, BorderLayout.CENTER); + p.setAlignmentX(Component.LEFT_ALIGNMENT); + return p; + } + + private void setTargetColor(Color c) { + if (c == null) return; + targetColor = c; + colorButton.setBackground(c); + colorButton.setForeground(contrast(c)); + previewPanel.setPreviewState(targetColor, targetAlpha, targetMode); + startAnimationIfNeeded(); + } + + // 当滑块值改变(v 为滑块上的值:可能是 0-255 或 0-64) + private void targetSliderChanged(int v) { + // 更新预览(targetAlpha 已在 ChangeListener 中计算) + previewPanel.setPreviewState(targetColor, targetAlpha, targetMode); + startAnimationIfNeeded(); + } + + private void setTargetMode(LocalCall.TaskbarAccentMode mode) { + if (mode == null) return; + targetMode = mode; + // 如果进入毛玻璃模式,确保 targetAlpha 基于当前 slider(映射) + if (targetMode == LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND) { + int degree = alphaSlider.getValue(); + float ratio = Math.max(0f, Math.min(1f, degree / 64f)); + targetAlpha = Math.round(ratio * 255f); + } + previewPanel.setPreviewState(targetColor, targetAlpha, targetMode); + startAnimationIfNeeded(); + } + + private void updateControlsForMode(LocalCall.TaskbarAccentMode mode) { + // 默认启用全部(模式选择除外) + boolean disableAll = (mode == LocalCall.TaskbarAccentMode.ACCENT_INVALID_STATE); + boolean isBlur = (mode == LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND); + + // 如果无效状态:什么都不能设置(除模式之外) + colorButton.setEnabled(!disableAll && !isBlur); + sysTextColorButton.setEnabled(!disableAll); + applySysTextColorButton.setEnabled(!disableAll); + helpButton.setEnabled(!disableAll); + //applyButton.setEnabled(!disableAll); + + // 配置滑块范围与标签 + if (isBlur) { + // 毛玻璃:滑块行为为 程度 0-64 + alphaLabel.setText("程度 (0-64)"); + alphaSlider.setMinimum(0); + alphaSlider.setMaximum(64); + alphaSlider.setMajorTickSpacing(16); + alphaSlider.setMinorTickSpacing(4); + alphaSlider.setPaintLabels(true); + // 如果之前值超范围则设置为上限 + if (alphaSlider.getValue() > 64) alphaSlider.setValue(32); + // 计算 targetAlpha(映射到 0-255) + int degree = alphaSlider.getValue(); + float ratio = Math.max(0f, Math.min(1f, degree / 64f)); + targetAlpha = Math.round(ratio * 255f); + } else { + // 常规模式:不透明度 0-255 + alphaLabel.setText("不透明度 (Alpha)"); + alphaSlider.setMinimum(0); + alphaSlider.setMaximum(255); + alphaSlider.setMajorTickSpacing(64); + alphaSlider.setMinorTickSpacing(16); + alphaSlider.setPaintLabels(true); + // 若当前 slider 值超过 255,调整 + if (alphaSlider.getValue() > 255) alphaSlider.setValue(255); + targetAlpha = clamp(alphaSlider.getValue()); + } + + // 预览和控件可用性 + alphaSlider.setEnabled(!disableAll); + setControlsEnabled(!disableAll); + + // 立即更新预览状态 + previewPanel.setPreviewState(targetColor, targetAlpha, mode); + startAnimationIfNeeded(); + } + + private void startAnimationIfNeeded() { + if (!animationTimer.isRunning()) animationTimer.start(); + } + + private static int lerp(int a, int b, float t) { + return Math.round(a + (b - a) * t); + } + + private static int clamp(int v) { + return Math.min(255, Math.max(0, v)); + } + + private static Color contrast(Color bg) { + double luminance = (0.299 * bg.getRed() + 0.587 * bg.getGreen() + 0.114 * bg.getBlue()) / 255.0; + return luminance > 0.6 ? Color.BLACK : Color.WHITE; + } + + /** + * 构建传入本地工具的颜色字符串(固定为 0xRRGGBB) + * 说明:为避免字节序混淆,Java 端始终发送 RGB(不包含 alpha),例如 #0099CC -> 0x0099CC + */ + private static String buildColorArg(Color c) { + if (c == null) return "0x000000"; + int r = c.getRed(); + int g = c.getGreen(); + int b = c.getBlue(); + return String.format("0x%02X%02X%02X", r, g, b); + } + + /** + * 通过修改注册表设置系统文字颜色(实验性) + */ + private static void setWindowsTextColor(Color c) throws IOException, InterruptedException { + String rgb = String.format("%d %d %d", c.getRed(), c.getGreen(), c.getBlue()); + String key = "HKCU\\Control Panel\\Colors"; + String[] values = new String[]{"WindowText", "HilightText", "ButtonText"}; + for (String v : values) { + String cmd = String.format("reg add \"%s\" /v %s /t REG_SZ /d \"%s\" /f", key, v, rgb); + Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", cmd}); + p.waitFor(); + } + Process refresh = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", + "RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters"}); + refresh.waitFor(); + } + + /** + * 预览面板:绘制模拟任务栏效果(更现代的表现) + */ + private static class PreviewPanel extends JPanel { + private Color previewColor = new Color(0, 0, 0); + private int previewAlpha = 255; + private LocalCall.TaskbarAccentMode previewMode = LocalCall.TaskbarAccentMode.ACCENT_DISABLED; + + PreviewPanel() { + setOpaque(true); + setBackground(new Color(0xF4F7FB)); + } + + void setPreviewState(Color color, int alpha, LocalCall.TaskbarAccentMode mode) { + this.previewColor = color != null ? color : new Color(0,0,0); + this.previewAlpha = clamp(alpha); + this.previewMode = mode != null ? mode : LocalCall.TaskbarAccentMode.ACCENT_DISABLED; + repaint(); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + int w = getWidth(); + int h = getHeight(); + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + // 背景渐变 + GradientPaint bg = new GradientPaint(0, 0, new Color(0xEAF3FF), 0, h, new Color(0xE6F0FF)); + g2.setPaint(bg); + g2.fillRect(0, 0, w, h); + + // 任务栏容器 + int barH = Math.max(76, h / 6); + int barY = h - barH - 36; + int margin = 36; + int barX = margin; + int barW = w - margin * 2; + RoundRectangle2D.Float barRect = new RoundRectangle2D.Float(barX, barY, barW, barH, 18, 18); + + // 根据模式绘制 + switch (previewMode) { + case ACCENT_DISABLED: + Color solid = new Color(previewColor.getRed(), previewColor.getGreen(), previewColor.getBlue(), + Math.max(200, previewAlpha)); + g2.setPaint(solid); + g2.fill(barRect); + break; + case ACCENT_ENABLE_GRADIENT: + case ACCENT_ENABLE_TRANSPARENTGRADIENT: + Color c1 = new Color(previewColor.getRed(), previewColor.getGreen(), previewColor.getBlue(), + Math.max(60, previewAlpha / 2)); + Color c2 = new Color(clamp(previewColor.getRed() + 30), clamp(previewColor.getGreen() + 30), + clamp(previewColor.getBlue() + 30), Math.max(60, previewAlpha / 2)); + GradientPaint gp = new GradientPaint(barX, barY, c1, barX + barW, barY + barH, c2); + g2.setPaint(gp); + g2.fill(barRect); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.08f)); + g2.fill(new RoundRectangle2D.Float(barX, barY, barW, barH / 2f, 16, 16)); + g2.setComposite(AlphaComposite.SrcOver); + break; + case ACCENT_ENABLE_BLURBEHIND: + Color base = new Color(previewColor.getRed(), previewColor.getGreen(), previewColor.getBlue(), + Math.max(8, previewAlpha / 3)); + g2.setPaint(base); + g2.fill(barRect); + Point2D center = new Point2D.Float(barX + barW / 2f, barY + barH / 2f); + float radius = Math.max(barW, barH); + RadialGradientPaint rgp = new RadialGradientPaint(center, radius, + new float[]{0f, 1f}, + new Color[]{new Color(255, 255, 255, Math.min(100, previewAlpha / 2)), + new Color(0, 0, 0, Math.min(40, previewAlpha / 6))}); + g2.setPaint(rgp); + g2.fill(barRect); + g2.setStroke(new BasicStroke(1.2f)); + for (int i = 0; i < 5; i++) { + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.04f + i * 0.02f)); + g2.draw(new RoundRectangle2D.Float(barX + i, barY + i, barW - i * 2f, barH - i * 2f, 16, 16)); + } + g2.setComposite(AlphaComposite.SrcOver); + break; + case ACCENT_ENABLE_ACRYLICBLURBEHIND: + case ACCENT_INVALID_STATE: + default: + Color acr = new Color(previewColor.getRed(), previewColor.getGreen(), previewColor.getBlue(), + Math.max(20, previewAlpha / 2)); + g2.setPaint(acr); + g2.fill(barRect); + GradientPaint spot = new GradientPaint(barX, barY, new Color(255, 255, 255, 140), + barX + barW / 2, barY + barH / 2, new Color(255, 255, 255, 0)); + g2.setPaint(spot); + g2.fill(new RoundRectangle2D.Float(barX, barY, barW / 2f, barH, 16, 16)); + for (int i = 0; i < barW; i += 10) { + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.03f)); + g2.drawLine(barX + i, barY + 6, barX + i + 6, barY + barH - 6); + } + g2.setComposite(AlphaComposite.SrcOver); + break; + } + + // 绘制图标占位 + int iconY = barY + 14; + int iconSize = Math.min(36, barH - 28); + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.95f)); + g2.setColor(new Color(255, 255, 255, 200)); + g2.fillOval(barX + 16, iconY, iconSize, iconSize); + + int trayX = barX + barW - 18 - (iconSize + 10) * 4; + for (int i = 0; i < 4; i++) { + int x = trayX + i * (iconSize + 10); + g2.fillRoundRect(x, iconY, iconSize, iconSize, 8, 8); + } + + g2.dispose(); + } + } +} diff --git a/src/main/java/org/tzd/explorer/DesktopIconRenderer.java b/src/main/java/org/tzd/explorer/DesktopIconRenderer.java deleted file mode 100644 index 779b1e7..0000000 --- a/src/main/java/org/tzd/explorer/DesktopIconRenderer.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.tzd.explorer; - -public class DesktopIconRenderer { -} diff --git a/src/main/java/org/tzd/explorer/LocalCall.java b/src/main/java/org/tzd/explorer/LocalCall.java new file mode 100644 index 0000000..0b0befd --- /dev/null +++ b/src/main/java/org/tzd/explorer/LocalCall.java @@ -0,0 +1,150 @@ +package org.tzd.explorer; + +import com.axis.innovators.box.tools.FolderCreator; +import java.io.IOException; + +/** + * @author tzdwindows 7 + */ +public class LocalCall { + private static final String LIBRARY = FolderCreator.getLibraryFolder(); + private static final String TASKBAR_EXE = "TaskbarTranslucentConsole.exe"; + + /** + * Enum representing the different taskbar accent modes + */ + public enum TaskbarAccentMode { + /** Disables any accent effect (需要将restartExplorer设置为真)*/ + @Description("Disables any accent effect") + ACCENT_DISABLED(0), + + /** Enables gradient effect (纯色任务栏,设置的alpha无效)*/ + @Description("Enables gradient effect") + ACCENT_ENABLE_GRADIENT(1), + + /** Enables transparent gradient effect (纯色任务栏,设置的alpha有效)*/ + @Description("Enables transparent gradient effect") + ACCENT_ENABLE_TRANSPARENTGRADIENT(2), + + /** Enables blur behind effect (设置alpha为0可实现透明任务栏) */ + @Description("Enables blur behind effect") + ACCENT_ENABLE_BLURBEHIND(3), + + /** Enables acrylic blur behind effect (Windows 10 Fluent Design) (模糊,设置的alpha无效)*/ + @Description("Enables acrylic blur behind effect (Windows 10 Fluent Design)") + ACCENT_ENABLE_ACRYLICBLURBEHIND(4), + + /** Invalid state (需要将restartExplorer设置为真)*/ + @Description("Invalid state") + ACCENT_INVALID_STATE(5); + + private final int value; + + TaskbarAccentMode(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + /** + * Gets the enum value from an integer + * @param value The integer value to convert + * @return Corresponding TaskbarAccentMode + * @throws IllegalArgumentException if the value is invalid + */ + public static TaskbarAccentMode fromValue(int value) { + for (TaskbarAccentMode mode : values()) { + if (mode.value == value) { + return mode; + } + } + throw new IllegalArgumentException("Invalid TaskbarAccentMode value: " + value); + } + } + + /** + * Changes the taskbar appearance + * @param mode The accent mode to apply + * @param color The color in hex format (0xRRGGBB) + * @param alpha The alpha value (0-255) + * @param restartExplorer Whether to restart explorer.exe + * @throws IOException If the process fails to start + * @throws InterruptedException If the process is interrupted + */ + public static void setTaskbarAppearance(TaskbarAccentMode mode, String color, int alpha, boolean restartExplorer) + throws IOException, InterruptedException { + if (color == null) color = "0x000000"; + String raw = color.trim(); + if (raw.startsWith("#")) raw = raw.substring(1); + if (raw.startsWith("0x") || raw.startsWith("0X")) raw = raw.substring(2); + if (raw.length() > 6) { + raw = raw.substring(raw.length() - 6); + } + while (raw.length() < 6) raw = "0" + raw; + + String colorArg = "0x" + raw.toUpperCase(); + + String exePath = LIBRARY + "\\" + TASKBAR_EXE; + java.util.List cmd = new java.util.ArrayList<>(); + cmd.add(exePath); + cmd.add("--mode"); + cmd.add(String.valueOf(mode.getValue())); + cmd.add("--color"); + cmd.add(colorArg); + cmd.add("--alpha"); + cmd.add(String.valueOf(alpha)); + if (restartExplorer) { + cmd.add("--restart"); + } + + System.out.println("Exec: " + String.join(" ", cmd)); + + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.redirectErrorStream(true); + + Process process = pb.start(); + StringBuilder output = new StringBuilder(); + try (java.io.BufferedReader reader = new java.io.BufferedReader( + new java.io.InputStreamReader(process.getInputStream(), java.nio.charset.StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append(System.lineSeparator()); + System.out.println(line); + } + } + + int exit = process.waitFor(); + if (exit != 0) { + throw new IOException("TaskbarTranslucentConsole exit code: " + exit + "\nOutput:\n" + output.toString()); + } + } + + /** + * Shows the help message for TaskbarTranslucentConsole.exe + * @throws IOException If the process fails to start + * @throws InterruptedException If the process is interrupted + */ + public static void showTaskbarHelp() throws IOException, InterruptedException { + String command = LIBRARY + "\\" + TASKBAR_EXE + " --help"; + Process process = Runtime.getRuntime().exec(command); + process.waitFor(); + } + + public static void main(String[] args) throws IOException, InterruptedException { + LocalCall.setTaskbarAppearance( + LocalCall.TaskbarAccentMode.ACCENT_ENABLE_BLURBEHIND, + "0x000000", + 0, + false + ); + } +} + +/** + * Custom annotation for enum descriptions + */ +@interface Description { + String value(); +} \ No newline at end of file diff --git a/src/main/resources/icons/windows/windows.png b/src/main/resources/icons/windows/windows.png new file mode 100644 index 0000000..836c4c1 Binary files /dev/null and b/src/main/resources/icons/windows/windows.png differ diff --git a/src/main/resources/icons/windows/windowsOptimization/windowsOptimization.png b/src/main/resources/icons/windows/windowsOptimization/windowsOptimization.png new file mode 100644 index 0000000..c7c4801 Binary files /dev/null and b/src/main/resources/icons/windows/windowsOptimization/windowsOptimization.png differ